Skip to content

Fix execution queue zombies and stop re-queueing failing configs - #698

Open
arthurschreiber wants to merge 1 commit into
mainfrom
fix-execution-queue-zombies
Open

Fix execution queue zombies and stop re-queueing failing configs#698
arthurschreiber wants to merge 1 commit into
mainfrom
fix-execution-queue-zombies

Conversation

@arthurschreiber

Copy link
Copy Markdown
Member

Context

The execution scheduler could wedge for hours — a 33-hour stall was observed on the production host (benchmark.vitess.io) between Jul 5 06:09 and Jul 6 15:35 UTC, and over a 4.3-day sample 47% of wall-clock time was idle. The root cause is a set of related bugs in the cron execution queue.

Changes

1. Fix queue-zombie leak (the stall)

executeElement mutates element.identifier.UUID before each retry, then removed the element from the queue map by its current identifier. Since the map is keyed by the identifier the element had when it was inserted, the delete missed and the entry leaked forever with Executing=true. Leaked entries fill the queue, count towards addToQueue's per-config limit, and make it report configs as "already full" — starving all new work.

Verified in production: the midnight cron on Jul 6 logged "not adding … already full" for tpcc-olap @ f240d1cb even though the DB had 0 finished and 60 failed runs for it.

executeElement now captures the original key up front and always removes by it (extracted into removeFromQueue). The recursive retry was rewritten as an iterative loop so cleanup happens in exactly one place. A regression test (TestRemoveFromQueueAfterUUIDMutation) covers the mutate-then-remove case.

2. Stop re-queueing permanently-failing configs

Failed executions do not count towards MaximumBenchmarkWithSameConfig, so a config that always fails (e.g. a workload that always times out) was re-added at full multiplicity on every cron tick and monopolised the benchmark machine. addToQueue now bails once a config reaches MaximumFailedBenchmarkWithSameConfig (20 = one full nightly cycle incl. retries) failed executions; a new git ref resets the counter. Counting uses the new exec.CountExecutionStatus, which reads the execution table alone (failed runs have no macrobenchmark row, so CountMacroBenchmark can't see them).

3. Watcher busy-loop

cronExecutionQueueWatcher was a sleep-less loop pegging a CPU core on the shared web host; it now polls once a second.

Testing

  • go test ./go/server/... ./go/exec/... (incl. the new regression test) ✅
  • golangci-lint run (v2.12.2, matching CI) — 0 issues ✅

🤖 Generated with Claude Code

The execution scheduler could wedge for hours (observed: a 33h stall on the
production host) because of three related issues in the cron queue:

1. executeElement mutated element.identifier.UUID between retries, then removed
   the element from the queue by its *current* identifier. Since the queue map
   is keyed by the identifier the element had when it was inserted, the delete
   missed and the entry leaked forever with Executing=true. Leaked entries fill
   the queue, count towards addToQueue's per-config limit, and make it report
   configs as "already full", starving new work. executeElement now removes the
   element by its original key on every exit path (extracted removeFromQueue).

2. Failed executions do not count towards MaximumBenchmarkWithSameConfig, so a
   permanently broken config (e.g. tpcc-olap timing out) was re-queued at full
   multiplicity on every cron tick and monopolised the benchmark machine.
   addToQueue now bails once a config has MaximumFailedBenchmarkWithSameConfig
   failed executions; a new git ref resets the counter. Counting uses the new
   exec.CountExecutionStatus, which reads the execution table alone (failed runs
   have no macrobenchmark row, so CountMacroBenchmark cannot see them).

3. cronExecutionQueueWatcher was a sleep-less busy loop pegging a CPU core on
   the shared web host; it now polls once a second.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@arthurschreiber
arthurschreiber requested a review from frouioui as a code owner July 7, 2026 09:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant