fix(correctness): pagination tiebreakers, dedup race, duration gating (0.87.6)
Three medium correctness fixes: 1. **Pagination ORDER BY missing tiebreakers** — four admin list queries sorted by a timestamp or `chapters.number` with no stable secondary sort. Add `id` tiebreakers across `repo::admin_view`, `repo::admin_audit`, `repo::bookmark`. 2. **`enqueue_pages` NOT EXISTS read-then-insert race** — concurrent admin clicks could land duplicate analyze_page jobs. Migration 0031 adds a partial unique index mirroring 0014; query relies on `ON CONFLICT DO NOTHING`. 3. **`record_duration` overwrote a prior done row's duration on a non-terminal failed retry of a force-re-analyze.** Gate the call on "did this attempt actually write a row?". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
17
backend/migrations/0031_crawler_jobs_analyze_page_dedup.sql
Normal file
17
backend/migrations/0031_crawler_jobs_analyze_page_dedup.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
-- Dedup analyze_page jobs in flight (mirrors 0014 for sync_chapter_content).
|
||||
--
|
||||
-- Without this, `repo::page_analysis::enqueue_pages`' `NOT EXISTS(... pending
|
||||
-- | running ...)` read-then-insert race let concurrent admin POSTs land
|
||||
-- duplicate jobs for the same page — visible as duplicate "now analyzing"
|
||||
-- SSE events and inflated `pending` counters in the admin dashboard, even
|
||||
-- though the worker's `skip-if-done` net (analysis/daemon.rs:210-217)
|
||||
-- prevented the actual duplicate vision call.
|
||||
--
|
||||
-- The partial unique index lets enqueue_pages drop the NOT EXISTS subquery
|
||||
-- and rely on `ON CONFLICT DO NOTHING` instead. At most one (pending|running)
|
||||
-- job per page_id can exist; the slot frees the moment the job transitions
|
||||
-- to done/failed/dead, so a force re-analyze still re-enqueues cleanly.
|
||||
CREATE UNIQUE INDEX crawler_jobs_analyze_page_dedup_idx
|
||||
ON crawler_jobs ((payload->>'page_id'))
|
||||
WHERE state IN ('pending', 'running')
|
||||
AND payload->>'kind' = 'analyze_page';
|
||||
Reference in New Issue
Block a user