-- 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';