server: drainer uses dispatch-core to avoid duplicate pending_run enqueue
Extract dispatchBackupForGroupCore (persist+marshal+send, no enqueue on failure) from dispatchBackupForGroup. drainOne now calls the core directly so a failed Send only bumps the existing pending_runs row via BumpPendingRunAttempt — not create a second row — stopping the geometric duplication on repeated drain failures. dispatchBackupForGroup (schedule.fire path) wraps the core and keeps its enqueue-on-failure behaviour unchanged. TestDrainPendingBumpsOnSendFailure strengthened: asserts exactly 1 row remains after a send failure (was tolerating >=1 duplicate rows).
This commit is contained in:
@@ -255,11 +255,13 @@ func TestDrainPendingBumpsOnSendFailure(t *testing.T) {
|
||||
Attempt: 1, NextAttemptAt: now.Add(-time.Second), ScheduledAt: now.Add(-time.Minute),
|
||||
})
|
||||
|
||||
// The original row was bumped (attempt=2) — the G1.1 path may have
|
||||
// also enqueued a duplicate row from inside dispatchBackupForGroup's
|
||||
// failed Send. So we expect exactly the original row updated, plus
|
||||
// possibly one duplicate. Either way: pending count >= 1, no row
|
||||
// deleted, and the original row's attempt bumped to 2.
|
||||
// The original row must be bumped to attempt=2 with a non-empty
|
||||
// last_error. Critically, NO duplicate row should have been created:
|
||||
// drainOne calls dispatchBackupForGroupCore (not dispatchBackupForGroup)
|
||||
// so the enqueue-on-failure path is bypassed and the count stays at 1.
|
||||
if n := countPendingForHost(t, st, hostID); n != 1 {
|
||||
t.Errorf("pending rows after send failure: got %d, want 1 (no duplicate enqueue)", n)
|
||||
}
|
||||
var attempt int
|
||||
var lastErr string
|
||||
if err := st.DB().QueryRow(
|
||||
@@ -273,12 +275,6 @@ func TestDrainPendingBumpsOnSendFailure(t *testing.T) {
|
||||
if lastErr == "" {
|
||||
t.Errorf("last_error empty after bump")
|
||||
}
|
||||
// No successful backup job persisted via DrainPending.
|
||||
// (dispatchBackupForGroup *does* create a job row before attempting
|
||||
// the send and leaves it on send-failure; that row exists. The
|
||||
// "successful job" we care about would be one that wasn't followed
|
||||
// by an enqueue — there aren't any here. Asserting on the bump is
|
||||
// the cleaner signal.)
|
||||
}
|
||||
|
||||
func TestDrainPendingDropsRowsForGoneSchedule(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user