Skip to content

fix(indexstore): make UpsertRun overwrite existing rows and stop dropping recent runs#253

Merged
skylenet merged 3 commits into
ethpandaops:masterfrom
damilolaedwards:fix/indexstore-upsert-and-recent-runs
Jul 1, 2026
Merged

fix(indexstore): make UpsertRun overwrite existing rows and stop dropping recent runs#253
skylenet merged 3 commits into
ethpandaops:masterfrom
damilolaedwards:fix/indexstore-upsert-and-recent-runs

Conversation

@damilolaedwards

Copy link
Copy Markdown
Contributor

Summary

Two data-correctness fixes in the index store.

UpsertRun never updated existing rows

UpsertRun ran Where(...).Assign(run).FirstOrCreate(run) with the same struct pointer as both the assign source and the query destination. FirstOrCreate loads the found row into run before building the update, so the update set every column to the value it already had, a no-op. Re-indexing a run (status change, corrected test counts, HasResult flip, end timestamp) silently kept the original values, and zero-valued fields could never be written.

Replaced it with an INSERT ... ON CONFLICT(discovery_path, run_id) DO UPDATE upsert that writes every column, including zero values, and still does not duplicate the row.

ListTestStatsBySuiteRecent dropped recent runs

The query used SELECT DISTINCT client, run_id, run_start and counted per row. A run whose stats carry inconsistent run_start values (e.g. a backfill rewrote some) produced several rows for one run_id, consumed several of the per-client slots, and evicted other recent runs. Changed it to SELECT client, run_id, MAX(run_start) ... GROUP BY client, run_id so each run counts once.

Tests

  • upsert_recent_test.go: re-index overwrites all fields including zeros without duplicating; insert path; inconsistent run_start returns both runs; per-client cap still honored.
  • Updated TestStore_UpsertRunIdempotent, which previously asserted the buggy first-write-wins behavior, to expect last-write-wins.

Full pkg/api/indexstore suite passes; go vet and gofmt clean.

damilolaedwards and others added 2 commits June 28, 2026 23:43
… order deterministic

The UpsertRun ON CONFLICT clause used UpdateAll, which overwrote indexed_at
with the re-index time on every re-index, losing the original first-index
timestamp (exposed via the API as indexed_at, distinct from reindexed_at).
Replace UpdateAll with an explicit column list that omits id and indexed_at,
so zero-valued fields are still written but indexed_at is preserved.

Also add a secondary sort key (run_id DESC) to ListTestStatsBySuiteRecent so
that when more runs than the per-client cap share the same run_start, the same
runs are kept deterministically on every call and across SQLite and Postgres.

Add a regression test asserting indexed_at survives a re-index while
reindexed_at is recorded.
@skylenet

Copy link
Copy Markdown
Member

Thank you so much for your fixes @damilolaedwards 🙏

@skylenet skylenet merged commit 1659996 into ethpandaops:master Jul 1, 2026
7 checks passed
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.

2 participants