Skip to content

Fix RedisWorker fetch_task() head-of-line blocking - #7901

Open
dkliban wants to merge 1 commit into
pulp:mainfrom
dkliban:fetch-task-blocked-resource-skip
Open

Fix RedisWorker fetch_task() head-of-line blocking#7901
dkliban wants to merge 1 commit into
pulp:mainfrom
dkliban:fetch-task-blocked-resource-skip

Conversation

@dkliban

@dkliban dkliban commented Jul 24, 2026

Copy link
Copy Markdown
Member

Summary

  • Fix head-of-line blocking in RedisWorker.fetch_task() when the queue head is dominated by tasks needing the same exclusive resource
  • After acquire_locks reports a resource is blocked, exclude tasks needing that resource from subsequent DB queries using reserved_resources_record__overlap
  • Add both raw and shared: prefixed variants to the exclusion set so tasks needing shared access to an exclusively-locked resource are also skipped
  • Replace exponential-doubling strategy with loop-until-stable: re-query from position 0 with growing exclusions until no new blocked resources are discovered

Test plan

  • 8 mock-based unit tests covering algorithm logic (blocked resource skip, sentinel filtering, loop termination, FIFO preservation)
  • 5 integration tests running fetch_task() against real PostgreSQL with mocked Redis (25 blocked tasks + 1 free, all blocked, multiple blocked resources, shared exclusion, FIFO order)
  • Verify no regressions in existing unit test suite
  • Manual verification in staging with bulk task creation for one resource while tasks for other resources are pending

Fixes #7900

🤖 Generated with Claude Code

When the task queue head is dominated by tasks needing the same exclusive
resource (e.g., 17,000 tasks for one repository), all workers scan the
same blocked tasks and never reach tasks with free resources further down.

Replace the exponential-doubling strategy with blocked-resource DB-level
exclusion: after acquire_locks reports a resource is blocked, exclude
tasks needing that resource from subsequent queries using
reserved_resources_record array overlap. The loop re-queries from
position 0 with growing exclusions until no new blocked resources are
discovered.

In the incident scenario (2026-07-24), this reduces task selection from
~10 exponentially growing queries to 2 queries: one to discover the
blocked resource, one filtered query that skips all 17,000 blocked tasks
and returns tasks with free resources.

Fixes: pulp#7900

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@dkliban
dkliban force-pushed the fetch-task-blocked-resource-skip branch from 423a674 to a266ef2 Compare July 26, 2026 00:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RedisWorker fetch_task() head-of-line blocking: workers starved when queue head is serialized on one resource (WORKER_TYPE=redis)

1 participant