Merge pull request #56 from dj-oyu/fix/telegram-rate-limit
fix: prevent Telegram 429 rate limit errors during PDF OCR
This commit is contained in:
commit
f1705d8ce4
3 changed files with 25 additions and 8 deletions
|
|
@ -372,7 +372,7 @@ func (al *AgentLoop) processingIndicator(ctx context.Context, channel, chatID, l
|
|||
}
|
||||
|
||||
go func() {
|
||||
ticker := time.NewTicker(150 * time.Millisecond)
|
||||
ticker := time.NewTicker(3 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
frame := 0
|
||||
|
|
@ -596,8 +596,10 @@ func (al *AgentLoop) ocrPDF(
|
|||
return fmt.Sprintf("[file:%s]", pdfPath)
|
||||
}
|
||||
|
||||
// Track progress via stderr
|
||||
// Track progress via stderr, keep last lines for error diagnosis
|
||||
page := 0
|
||||
var stderrTail []string
|
||||
const maxTailLines = 20
|
||||
scanner := bufio.NewScanner(stderrPipe)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
|
@ -605,12 +607,17 @@ func (al *AgentLoop) ocrPDF(
|
|||
page++
|
||||
indicator.UpdateLabel(fmt.Sprintf("%s (%d/%s)...", modeLabel, page, totalStr))
|
||||
}
|
||||
stderrTail = append(stderrTail, line)
|
||||
if len(stderrTail) > maxTailLines {
|
||||
stderrTail = stderrTail[1:]
|
||||
}
|
||||
}
|
||||
|
||||
if waitErr := cmd.Wait(); waitErr != nil {
|
||||
logger.WarnCF("agent", "OCR command failed", map[string]any{
|
||||
"path": pdfPath,
|
||||
"error": waitErr.Error(),
|
||||
"path": pdfPath,
|
||||
"error": waitErr.Error(),
|
||||
"stderr": strings.Join(stderrTail, "\n"),
|
||||
})
|
||||
return fmt.Sprintf("[file:%s]", pdfPath)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ const (
|
|||
// for the same status/task bubble. EditMessage APIs are more rate-sensitive
|
||||
// than SendMessageDraft, so we throttle edits to avoid "(edited)" flicker
|
||||
// and API rate limit errors. Draft-based channels bypass this throttle.
|
||||
statusEditInterval = 500 * time.Millisecond
|
||||
// Telegram enforces ~20 messages/min per group chat, so 3s is safe.
|
||||
statusEditInterval = 3 * time.Second
|
||||
)
|
||||
|
||||
// statusMsgEntry tracks a status or task message ID for later editing.
|
||||
|
|
@ -85,8 +86,9 @@ func (m *Manager) handleStatusSend(ctx context.Context, name string, w *channelW
|
|||
if v, loaded := m.placeholders.Load(key); loaded {
|
||||
if entry, ok := v.(placeholderEntry); ok && entry.id != "" {
|
||||
if editor, ok := w.ch.(MessageEditor); ok {
|
||||
// Always record edit time to prevent retry storms on 429 errors.
|
||||
m.statusEditTimes.Store(key, time.Now())
|
||||
if err := editor.EditMessage(ctx, msg.ChatID, entry.id, msg.Content); err == nil {
|
||||
m.statusEditTimes.Store(key, time.Now())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -97,8 +99,8 @@ func (m *Manager) handleStatusSend(ctx context.Context, name string, w *channelW
|
|||
if v, loaded := m.statusMsgIDs.Load(key); loaded {
|
||||
if entry, ok := v.(statusMsgEntry); ok && entry.messageID != "" {
|
||||
if editor, ok := w.ch.(MessageEditor); ok {
|
||||
m.statusEditTimes.Store(key, time.Now())
|
||||
if err := editor.EditMessage(ctx, msg.ChatID, entry.messageID, msg.Content); err == nil {
|
||||
m.statusEditTimes.Store(key, time.Now())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -223,8 +225,8 @@ func (m *Manager) handleTaskStatusSend(ctx context.Context, name string, w *chan
|
|||
if v, loaded := m.taskMsgIDs.Load(taskKey); loaded {
|
||||
if entry, ok := v.(statusMsgEntry); ok && entry.messageID != "" {
|
||||
if editor, ok := w.ch.(MessageEditor); ok {
|
||||
m.statusEditTimes.Store(taskKey, time.Now())
|
||||
if err := editor.EditMessage(ctx, msg.ChatID, entry.messageID, msg.Content); err == nil {
|
||||
m.statusEditTimes.Store(taskKey, time.Now())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -305,6 +305,10 @@ func (c *TelegramChannel) sendChunk(
|
|||
}
|
||||
|
||||
if _, err := c.bot.SendMessage(ctx, tgMsg); err != nil {
|
||||
// Don't retry on rate limit errors — they aren't parse failures.
|
||||
if strings.Contains(err.Error(), "429") || strings.Contains(err.Error(), "Too Many Requests") {
|
||||
return fmt.Errorf("telegram send: %w", channels.ErrTemporary)
|
||||
}
|
||||
logParseFailed(err, params.useMarkdownV2)
|
||||
|
||||
tgMsg.Text = params.mdFallback
|
||||
|
|
@ -372,6 +376,10 @@ func (c *TelegramChannel) EditMessage(ctx context.Context, chatID string, messag
|
|||
}
|
||||
_, err = c.bot.EditMessageText(ctx, editMsg)
|
||||
if err != nil {
|
||||
// Don't retry on rate limit errors — they aren't parse failures.
|
||||
if strings.Contains(err.Error(), "429") || strings.Contains(err.Error(), "Too Many Requests") {
|
||||
return err
|
||||
}
|
||||
logParseFailed(err, useMarkdownV2)
|
||||
_, err = c.bot.EditMessageText(ctx, tu.EditMessageText(tu.ID(cid), mid, content))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue