Skip to content

fix(ingestion): phase-3 continued — R11 janitor, R1 heartbeat+fences, R7/R9/R23 RPC hardening#369

Merged
BigSimmo merged 2 commits into
mainfrom
claude/ingestion-concurrency-fixes-2
Jul 8, 2026
Merged

fix(ingestion): phase-3 continued — R11 janitor, R1 heartbeat+fences, R7/R9/R23 RPC hardening#369
BigSimmo merged 2 commits into
mainfrom
claude/ingestion-concurrency-fixes-2

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Continues phase-3 concurrency fixes from #346, following the docs in #339 (docs/ingestion-state-machine.md §6 violations, §8 backlog). The db-reliability hold (#342) has merged.

Shipped and verified

App-code (no schema.sql):

  • R11 janitor-side guardscripts/cleanup-storage.ts skips storage_cleanup_jobs rows whose document_id still resolves to a live document (FK is ON DELETE SET NULL; non-null + resolves = aborted delete). Defense-in-depth for fix(ingestion): phase-3 concurrency fixes — R11, R15/R16, R22, R24d #346's DELETE-side path-clearing.
  • R1 lease heartbeat — the worker refreshes locked_at during long jobs (scoped to locked_by = workerId), so a healthy worker past the 45-minute stale window is no longer false-reclaimed. Removes the R2–R8 enabler in the common case.

Migration 20260708120000 (NOT applied to live — operator apply per docs/supabase-migration-reconciliation.md; schema.sql reconciled, drift manifest regenerated, replays clean in 13s):

  • R1/R2 lease fencescomplete_ingestion_job + fail_or_retry_ingestion_job take an optional p_worker_id; a reclaimed worker matches 0 rows → ok:false lease_lost instead of clobbering the reclaimer's newer state. Backward compatible (default null); worker passes workerId, treats lease_lost as a stop, keeps the isMissingSchemaError fallback.
  • R7 — attempt-exhausted retries downgrade to terminal failed instead of a permanently-unclaimable pending that pins the batch.
  • R9refresh_import_batch_status locks the batch row before counting (fixes the lost-update that stuck batches as processing forever).
  • R23cleanup_abandoned re-asserts the open-job guard immediately before the deletes.

Gates (parent-checkout binaries; worktree has no node_modules): eslint ✅ prettier ✅ tsc ✅ · vitest drift-detection + supabase-schema replay guards + ingestion + storage-cleanup-safety ✅ (69 + tests) · drift:manifest regenerated via Docker ✅. check:indexing/reindex:health/check:drift (live) and the migration apply are operator steps.

Held — with live evidence (do NOT merge these here)

  • R17 (open-jobs partial-unique index) — lands in drift backlog item Bump @supabase/supabase-js from 2.105.4 to 2.106.1 #7 (active ingestion_jobs index reshape). Route through that workstream. Live is clean (0 docs with multiple open jobs), so it's safe whenever it's done.
  • R24e (ingestion_job_stages.job_id FK) — drift backlog item Bump gitleaks/gitleaks-action from 2 to 3 #8 plans to add this FK, but live has 253 orphan stage rows that would fail VALIDATE and 0 agent-job-id rows. The evidence says remove the FK from schema.sql (match live) — the opposite of the backlog plan. Needs the backlog owner's decision; flagged, not flipped.
  • Deep-memory delete-scoping (R24c/d)would crash live. document_sections has unique (document_id, section_index); scoping the delete to preserve agent sections and then re-inserting overlapping indexes is a unique violation. fix(ingestion): phase-3 concurrency fixes — R11, R15/R16, R22, R24d #346's route-side agent gate already closes the main concurrent vector. Needs a coordinated section-ownership design, not a small patch.

Refs #339 #346 #342
🤖 Generated with Claude Code

BigSimmo and others added 2 commits July 8, 2026 13:33
… storage

Defense-in-depth complement to the DELETE-route path-clearing already landed in
PR #346. scripts/cleanup-storage.ts now skips any storage_cleanup_jobs row whose
document_id still resolves to a live document: the ledger FK is ON DELETE SET
NULL, so a genuinely-deleted document has its ledger document_id nulled — a
non-null id that still resolves means the delete aborted and the paths still
belong to a live document. Protects pre-#346 poisoned rows and any abort path
that still leaves populated paths.

Pure partition logic extracted to src/lib/storage-cleanup-safety.ts with tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The worker never refreshed ingestion_jobs.locked_at during a job, so any build
longer than WORKER_STALE_AFTER_MINUTES (45m) was reclaimed by claim_ingestion_jobs
while the original worker was still alive — two workers on one document, the
enabler (R1) for the R2-R8 write-clobber class. updateJobProgress now doubles as
a lease heartbeat: shouldPersistJobProgress adds a heartbeat ceiling (1/3 of the
stale window) forcing a write during long silent phases, and the write refreshes
locked_at scoped to locked_by=workerId so a worker that already lost its lease
no-ops instead of stealing it back. Additive and lease-scoped; the residual
loser-write race is closed by the RPC locked_by fences (separate migration).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@supabase

supabase Bot commented Jul 8, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@BigSimmo
BigSimmo merged commit c0eaea7 into main Jul 8, 2026
5 checks passed
@BigSimmo BigSimmo changed the title fix(ingestion): phase-3 continued — R11 janitor guard + R1 lease heartbeat fix(ingestion): phase-3 continued — R11 janitor, R1 heartbeat+fences, R7/R9/R23 RPC hardening Jul 8, 2026
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