fix(line): log loading refresh errors, skip typing without recorder

Address review feedback from @alexhoshina and Codex:
- Log sendLoading errors in ticker goroutine instead of discarding
- Only start typing indicator when PlaceholderRecorder is available
  to avoid wasted API calls and unnecessary goroutine creation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
ex-takashima 2026-02-26 20:29:09 +09:00
parent 3dc65ff7d7
commit 84667206b6

View file

@ -380,25 +380,23 @@ func (c *LINEChannel) processEvent(event lineEvent) {
// Thinking indicator (LINE loading animation is 1:1 only). // Thinking indicator (LINE loading animation is 1:1 only).
// For group/room chats, LINE provides no equivalent API. // For group/room chats, LINE provides no equivalent API.
// Only start if PlaceholderRecorder is available to avoid wasted API calls.
if !isGroup { if !isGroup {
typingCtx, typingCancel := context.WithTimeout(c.ctx, 5*time.Minute) if rec := c.GetPlaceholderRecorder(); rec != nil {
stop, err := c.StartTyping(typingCtx, chatID) typingCtx, typingCancel := context.WithTimeout(c.ctx, 5*time.Minute)
if err == nil { stop, err := c.StartTyping(typingCtx, chatID)
var stopOnce sync.Once if err == nil {
stopFn := func() { var stopOnce sync.Once
stopOnce.Do(func() { stopFn := func() {
stop() stopOnce.Do(func() {
typingCancel() stop()
}) typingCancel()
} })
if rec := c.GetPlaceholderRecorder(); rec != nil { }
rec.RecordTypingStop("line", chatID, stopFn) rec.RecordTypingStop("line", chatID, stopFn)
} else { } else {
// No recorder — stop immediately to avoid goroutine leaks. typingCancel()
stopFn()
} }
} else {
typingCancel()
} }
} }
@ -627,7 +625,11 @@ func (c *LINEChannel) StartTyping(ctx context.Context, chatID string) (func(), e
case <-typingCtx.Done(): case <-typingCtx.Done():
return return
case <-ticker.C: case <-ticker.C:
_ = c.sendLoading(typingCtx, chatID) if err := c.sendLoading(typingCtx, chatID); err != nil {
logger.DebugCF("line", "Failed to refresh loading indicator", map[string]any{
"error": err.Error(),
})
}
} }
} }
}() }()