Skip to content

fix: sort zoids in CacheWarmer._flush to prevent PK-index deadlock#61

Merged
jensens merged 1 commit into
mainfrom
fix/cache-warmer-deadlock
Apr 20, 2026
Merged

fix: sort zoids in CacheWarmer._flush to prevent PK-index deadlock#61
jensens merged 1 commit into
mainfrom
fix/cache-warmer-deadlock

Conversation

@jensens
Copy link
Copy Markdown
Member

@jensens jensens commented Apr 20, 2026

Summary

  • Sort zoids before the INSERT ... ON CONFLICT DO UPDATE into cache_warm_stats so concurrent Waitress workers acquire PK row locks in the same order and can never deadlock.
  • Observed in production: psycopg.errors.DeadlockDetected on INSERT ... while inserting index tuple (…) in relation "cache_warm_stats" between two worker processes.
  • Root cause: zoids = list(self._pending)set iteration order is unstable across processes, so two workers with overlapping pending sets upsert the same rows in opposing orders and deadlock on the PK index.
  • Added regression test in TestCacheWarmerFlushEdge that mocks the cursor and asserts the bigint[] bound to the INSERT is sorted. Verified the test fails on list(...) and passes on sorted(...).

Test plan

  • pytest tests/test_cache_warmer.py — 24/24 green locally
  • CI matrix (3.12 / 3.13 / 3.14) green
  • Watch production logs for DeadlockDetected from cache_warmer._flush after deploy

🤖 Generated with Claude Code

Concurrent Waitress workers with overlapping pending sets deadlocked
on cache_warm_stats PK index when their INSERT ... ON CONFLICT DO
UPDATE acquired row locks in opposing orders. Set iteration order is
not stable across processes, so two flushes could see the same zoids
in different orders.

Sort zoids before the upsert for a deterministic row-lock acquisition
order. Added regression test verifying the INSERT parameter is sorted.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jensens jensens merged commit dbddeb5 into main Apr 20, 2026
5 checks passed
@jensens jensens deleted the fix/cache-warmer-deadlock branch April 20, 2026 13:57
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