fix(indexing): real-time inserts index display values (#28) #33

Merged
KofTwentyTwo merged 1 commits from fix/28-insert-display-values into develop 2026-10-11 12:58:53 +00:00
KofTwentyTwo commented 2026-10-11 12:54:50 +00:00 (Migrated from github.com)

Summary

Real-time INSERT events were indexed from the event's own records, which carry raw values only. A foreign key was indexed as its id ("1"), and the record label came out as "2 - email", until the next basepull rewrote the document (found adopting 1.0.0-RC.2 in QRun-IO/Voyage#112).

QuickSearchRecordChangeListener now handles INSERT the same way as UPDATE: it re-reads the written records inside the write's transaction with shouldGenerateDisplayValues and shouldTranslatePossibleValues (the existing fetchCurrentRecords path), so a real-time document matches the one basepull, reconcile and full reindex build.

Failure handling is the same as for updates (#13):

  • a failed re-read (Exception or LinkageError) is logged right away ("Could not re-read inserted records ...");
  • after commit, the inserted keys are written to quickSearchFailedEvent (INDEX, PENDING) for basepull to replay;
  • on rollback nothing is recorded;
  • the host's insert never fails.

The change is confined to the real-time listener. It does not touch QuickSearchQBitProducer or config, so it does not overlap with #32.

Behaviour note

Every insert batch on an indexed table now runs one extra query, inside the transaction, and that query calls the host's possible-value providers. Updates already did this. The note is in docs/MIGRATION-1.0.md.

Tests

  • QuickSearchRecordChangeListenerTest (memory backend, table PVS over a company table):
    • testInsert_indexesDisplayValuesAndPossibleValueLabels: the published record has companyId display value "Acme Corp" and record label "widget - Acme Corp".
    • testInsert_reReadFails_recordsFailedEventsAfterCommit and testInsert_reReadFailsThenRollback_logsCauseAndRecordsNothing.
  • IndexDriftIntegrationTest.testInsert_documentCarriesDisplayValuesAndPossibleValueLabel (OpenSearch Testcontainers): with no basepull in between, a just-inserted record is found by its region's PVS label, its result label is "Rhoda - Northwind Territory", and the document's fieldValues.regionId holds the label.
  • Run against the unchanged listener, all four new tests fail; with the fix they pass.
  • CI=true ./mvnw verify passes locally (default profile, QQQ 4.1.0-RC.1): 356 unit tests, 20 integration tests, JaCoCo coverage gate met.

Closes #28. Part of #12.

🤖 Generated with Claude Code

## Summary Real-time INSERT events were indexed from the event's own records, which carry raw values only. A foreign key was indexed as its id ("1"), and the record label came out as "2 - email", until the next basepull rewrote the document (found adopting 1.0.0-RC.2 in QRun-IO/Voyage#112). `QuickSearchRecordChangeListener` now handles `INSERT` the same way as `UPDATE`: it re-reads the written records inside the write's transaction with `shouldGenerateDisplayValues` and `shouldTranslatePossibleValues` (the existing `fetchCurrentRecords` path), so a real-time document matches the one basepull, reconcile and full reindex build. Failure handling is the same as for updates (#13): - a failed re-read (`Exception` or `LinkageError`) is logged right away ("Could not re-read inserted records ..."); - after commit, the inserted keys are written to `quickSearchFailedEvent` (`INDEX`, `PENDING`) for basepull to replay; - on rollback nothing is recorded; - the host's insert never fails. The change is confined to the real-time listener. It does not touch `QuickSearchQBitProducer` or config, so it does not overlap with #32. ## Behaviour note Every insert batch on an indexed table now runs one extra query, inside the transaction, and that query calls the host's possible-value providers. Updates already did this. The note is in `docs/MIGRATION-1.0.md`. ## Tests - `QuickSearchRecordChangeListenerTest` (memory backend, table PVS over a `company` table): - `testInsert_indexesDisplayValuesAndPossibleValueLabels`: the published record has `companyId` display value "Acme Corp" and record label "widget - Acme Corp". - `testInsert_reReadFails_recordsFailedEventsAfterCommit` and `testInsert_reReadFailsThenRollback_logsCauseAndRecordsNothing`. - `IndexDriftIntegrationTest.testInsert_documentCarriesDisplayValuesAndPossibleValueLabel` (OpenSearch Testcontainers): with no basepull in between, a just-inserted record is found by its region's PVS label, its result label is "Rhoda - Northwind Territory", and the document's `fieldValues.regionId` holds the label. - Run against the unchanged listener, all four new tests fail; with the fix they pass. - `CI=true ./mvnw verify` passes locally (default profile, QQQ 4.1.0-RC.1): 356 unit tests, 20 integration tests, JaCoCo coverage gate met. Closes #28. Part of #12. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.