Repository navigation
Conversation
…ent exhaustion [ENG-2792] Drives the live taxonomy provider, the worker's final attempt on a connection reset, the reconcile sweep, and the repair job against a real Postgres and River. Text records recover; categorical records the live path accepts are never selected for repair. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…NG-2792] The live taxonomy provider, readiness counts and taxonomy run input select any record carrying text, including the option labels choice and matrix expansion store on categorical rows. The repair sweep and the backlog gauge additionally required field_type = 'text', so a categorical record that exhausted its attempts on transient provider errors was never repaired, and its directory never reached taxonomy readiness. This stranded 6,642 records in the EU incident. Drop the extra predicate so all five paths select through taxonomyEmbeddingEligibleTextSQL, document it as the single rule, and add a parity test over every field_type enum value. The gauge test that pinned the categorical exclusion now expects it to be counted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… rule [ENG-2792] The failed-records gauge still gated its taxonomy_embedding arm on the text-enrichment eligibility (field_type = 'text', value_text only), so a categorical record that exhausted its attempts showed as pending but never as failed. The backfill command kept its own taxonomy rule with a bare btrim, selecting whitespace-only records it re-enqueues on every run. Both now select through taxonomyEmbeddingEligibleTextSQL, and the parity test covers the pending and failed-records gauges and the backfill list and count for every field type. The new tests and two neighbours closed their pool with defer before t.Cleanup ran, so fixtures and up to 1,000 repair jobs leaked into the shared test database per run and broke the next run's sweep. They now register db.Close with t.Cleanup first. The taxonomy page now states the full set of conditions for repair. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ENG-2792] Run the repair-selection test's exclusions (active job, terminal marker, model and revision checks, cooldown, whitespace) for categorical as well as text records, and correct three comments and a docs line that still described taxonomy embeddings as text-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
WalkthroughTaxonomy embedding eligibility now includes non-blank translated text, or non-blank source text when no translation is available, across field types. Pending selection, backfill, backlog counts, and failed-record aggregation use the shared eligibility rule. Integration tests compare eligibility across these paths and cover recovery after a transient provider failure and cooldown. The documentation describes field-type coverage and reconciliation retry conditions. Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What does this PR do?
Ref ENG-2792 (https://linear.app/formbricks/issue/ENG-2792) — this is the incident slice only. The ticket stays open for the durable-enqueue, stale-embedding and operator-repair work.
On 22 October an EU directory stayed on "Preparing your feedback": 6,642 categorical records had used up their taxonomy-embedding attempts on provider connection resets, and nothing ever retried them. The cause is one rule kept in several places that had drifted apart:
ListPendingTaxonomyEmbeddingIDs)hub_enrichment_pending_records{taxonomy_embedding})hub_enrichment_failed_records{taxonomy_embedding})backfill-embeddings -taxonomySo a categorical record (matrix and multi-choice answers store the option label in
value_text) was embedded live and counted toward readiness, but couldn't be repaired, and both gauges reported the stuck backlog as zero. Every path now selects throughtaxonomyEmbeddingEligibleTextSQL, and the comments say why there's deliberately nofield_typepredicate on it.The backfill command also stops picking up tab- or NBSP-only records it would re-enqueue on every run. The taxonomy docs page said only text records take part; it now says what actually happens and when repair kicks in.
Tests added
TestTaxonomyEmbeddingRecoversAfterTransientExhaustionreproduces the incident against real Postgres and River. The live provider enqueues, the worker's final attempt fails onECONNRESET, the cooldown passes, the sweep queues a repair, the repair embeds the record, and readiness shows full coverage. Text passes onmainand categorical fails; both pass here.TestTaxonomyEmbeddingEligibilityAgreesAcrossPathsreads everyfield_typefrom the DB enum (so a new type is covered without touching the test) and asserts live enqueue, repair, readiness, both gauges and the backfill list/count agree on a record with text and a blank one. Reverting any single fix makes it fail (checked for each).TestListPendingTaxonomyEmbeddingIDsnow runs every exclusion (active job, terminal marker, model and revision checks, cooldown, whitespace) for categorical as well as text records.Test hygiene fix (same area). The new tests and two neighbours (
TestListPendingTaxonomyEmbeddingIDs,TestCountFailedRecordsAggregateIncludesOnlyCurrentTaxonomyEmbeddingFailures) closed their pool withdeferbeforet.Cleanupran. The cleanup silently hit a closed pool and up to 1,000 repair jobs leaked per run, which broke the next run's sweep. They now uset.Cleanup(db.Close), like the rest oftests/.How should this be tested?
Automated (against a pgvector Postgres with goose and River migrations):
To see the bug, check out
mainand run the same tests with onlytests/embedding_reconcile_recovery_test.gocopied over: the categorical subtest fails at "reconciler must enqueue a repair".Live smoke I ran. Real
hub-apiandhub-workerbinaries againstai-test-server(OpenAI-compatible stub with runtime failure injection), a fresh database per scenario,EMBEDDING_MAX_ATTEMPTS=1so the first failure is final. Branch vsmain:RETRY_AFTER=30s)TARGET_DEPTH=5, 40 strandedvalue_textre-embedsSIGKILLmid-repair, rescue 20sbackfill-embeddings -taxonomy -count-onlywith tab/NBSP rowsThe original incident repro (10 text + 10 categorical, provider down then back) goes from 10 stranded on
mainto 0 here.Gates:
make build,make lint(0 issues),make migrate-validate, and the fullgo test ./...twice back to back against the same DB (all 21 packages pass, 0 leaked jobs).Not verified locally:
pnpm check/pnpm buildfor the docs page (one prose sentence; the docs-build workflow on this PR covers it).Risk and rollout
Found while testing, not changed here (pre-existing, parked for the rest of the ticket):
value_texton a non-text record leaves its old vectors behind.Checklist
Required
make buildmake tests(integration tests intests/)make fmtandmake lint; no new warningsgit pull origin mainmigrations/with goose annotations and ranmake migrate-validate(no schema change)Appreciated
docs/if changes were necessarymake tests-coveragefor meaningful logic changes