You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Two-part fix for flaky bulk ingestion and the bench's duplicate uploads.
Idempotent ingest (root cause of "same doc ingested up to 6x"):
- New `idempotency_key` column on documents + partial unique index on
(org_id, idempotency_key) — migration 0007. NULL key = no dedup
(preserves current behavior for callers that don't opt in).
- All three ingest handlers (standalone/local in internal/api, multi-tenant
REST in internal/handler, Connect RPC in internal/connecthandler) honor the
`Idempotency-Key` header the SDK already sends: a repeat ingest returns the
original document instead of creating a duplicate, and the concurrent
same-key race is resolved by dropping the orphan source and returning the
winner. The SDK retry-on-transient (which re-POSTs after a reset that landed
AFTER the server committed) is now a no-op.
- db: ErrConflict sentinel mapped from SQLSTATE 23505; GetDocumentByIdempotencyKey.
Self-diagnosing not-found (resolves the pathless "object not found" mystery):
- Every storage backend's ErrNotFound now carries the resolved key/path
(local Get+Delete, s3 Get+Delete, gcs Get+Delete) so a failure can always be
attributed to a code path — pathless rows were pre-path-wrap leftovers.
- local.Get: the open-after-stat result is wrapped as retryable ErrNotFound
(previously a raw error getSourceWithRetry would NOT retry), and a Windows-only
bounded retry rides through the Defender scan window that transiently hides a
freshly-written file.
Docs: OpenAPI documents the Idempotency-Key header; README documents the
mandatory Windows Defender exclusion for the storage root.
Verified: go build/vet clean; storage + db (live-Postgres) tests pass; and an
end-to-end double-POST with one Idempotency-Key returns one document_id while a
keyless control gets its own.
0 commit comments