fix(PROJ-86): stale sync_running-Flag beim Scheduler-Start automatisch bereinigen
Ein IMAP-Konto blieb wegen sync_running=true seit 2026-07-05 (Prozess-Crash vor dem defer in runSyncWithRetry) für den Scheduler auf ewig "beschäftigt" - checkAccounts überspringt Konten mit SyncRunning=true. Neue Store-Methode ClearStaleSyncRunning() wird jetzt bei jedem Scheduler.Start() aufgerufen und setzt verwaiste Flags zurück, bevor der Scheduler-Loop startet. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UPFC6Jk2ke1Pq9XcuVGP1R
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
25865423f9
commit
e1f39ce56f
@@ -81,6 +81,12 @@ func (s *Scheduler) SetAuditLogger(a *audit.Logger) {
|
|||||||
// Start launches the background scheduler goroutine.
|
// Start launches the background scheduler goroutine.
|
||||||
// Call Stop to shut it down gracefully.
|
// Call Stop to shut it down gracefully.
|
||||||
func (s *Scheduler) Start() {
|
func (s *Scheduler) Start() {
|
||||||
|
if n, err := s.store.ClearStaleSyncRunning(context.Background()); err != nil {
|
||||||
|
s.logger.Error("imap scheduler: clear stale sync_running failed", "err", err)
|
||||||
|
} else if n > 0 {
|
||||||
|
s.logger.Warn("imap scheduler: cleared stale sync_running flags left over from a prior crash/kill", "accounts", n)
|
||||||
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
s.cancel = cancel
|
s.cancel = cancel
|
||||||
|
|
||||||
|
|||||||
@@ -349,6 +349,21 @@ func (s *Store) UpdateSyncInterval(ctx context.Context, id int64, intervalMin in
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClearStaleSyncRunning resets sync_running=true for every account back to
|
||||||
|
// false. Called once at process startup: sync_running is only ever set on
|
||||||
|
// this same process, so any row still marked running is a leftover from a
|
||||||
|
// prior process that crashed/was killed mid-sync (the defer in
|
||||||
|
// runSyncWithRetry never ran) — without this, the scheduler would skip that
|
||||||
|
// account forever (checkAccounts skips accounts with SyncRunning=true).
|
||||||
|
// Returns the number of accounts reset.
|
||||||
|
func (s *Store) ClearStaleSyncRunning(ctx context.Context) (int, error) {
|
||||||
|
tag, err := s.pool.Exec(ctx, `UPDATE imap_accounts SET sync_running = false WHERE sync_running = true`)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("imap store: clear stale sync running: %w", err)
|
||||||
|
}
|
||||||
|
return int(tag.RowsAffected()), nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetSyncRunning marks whether a background sync is currently active for an account.
|
// SetSyncRunning marks whether a background sync is currently active for an account.
|
||||||
func (s *Store) SetSyncRunning(ctx context.Context, id int64, running bool) error {
|
func (s *Store) SetSyncRunning(ctx context.Context, id int64, running bool) error {
|
||||||
_, err := s.pool.Exec(ctx,
|
_, err := s.pool.Exec(ctx,
|
||||||
|
|||||||
Reference in New Issue
Block a user