Skip to content

db: squash migrations - #26

Merged
michalkucharczyk merged 3 commits into
mainfrom
mku-db-migrations-cleanup
Aug 5, 2026
Merged

db: squash migrations#26
michalkucharczyk merged 3 commits into
mainfrom
mku-db-migrations-cleanup

Conversation

@michalkucharczyk

Copy link
Copy Markdown
Contributor
  • Squash 24 migrations into a 7-file baseline: no aggregate is created-then-dropped anymore, so fresh-DB migration deadlocks are structurally gone (store.rs retry reverted).
  • Two fixes on top: materialized_only=false on all count aggregates (5 groups accidentally lagged their refresh interval), dead compression config dropped from ingested_raw_events.
  • Breaking: every existing DB needs one wipe (sqlx ledger mismatch).

Fresh databases deadlocked during startup migrations: the old history
created continuous aggregates whose refresh/retention policy jobs start
running immediately (003/005/016), then dropped those aggregates in
later migrations (006/015/020). DROP MATERIALIZED VIEW ... CASCADE must
delete the policy jobs and races the TimescaleDB job scheduler —
relation locks vs per-job advisory locks, in opposite order. Which side
loses is a coin flip, so CI failed while production "worked" (there the
scheduler was the deadlock victim and simply restarted).

Replace the history with a baseline that creates only the final schema:

  001_core                 extensions, ingested_raw_events (+events view,
                           hot columns, 1h retention), nodes, event_types
  002_count_tables         14 per-group count tables (all 115 event types)
  003_count_aggregates     _1m/_1h continuous aggregates over count tables
  004_union_views          all_event_stats_30s/1m/1h, all_core_stats_1m
  005_node_stats_services  node_stats + event_services + 1m aggregates
  006_trackers             convergence, wp_tracking, DA stats/latency hists
  007_onchain              on-chain core/service/validator stats

No aggregate is ever dropped during migration, so the deadlock is
structurally impossible; the retry workaround in store.rs is reverted.

Verified schema-equivalent to the old history: both sets applied to
scratch databases, then diffed over normalized catalog state (columns
incl. ordinal positions, constraints, indexes, view definitions,
hypertable dimensions, compression settings, policy jobs, continuous-
aggregate materialized_only flags, seed rows) — empty diff. Full test
suite passes against the new baseline.

Existing databases must be recreated once: the _sqlx_migrations ledger
no longer matches (use clean-and-reset-all, or drop tart_test before
run-tests.sh). CI is unaffected — it always starts from fresh
containers.
The migration squash preserved a historical quirk: the aggregates for
the five newest count groups (status, connection, block, ticket_low,
wp_pipeline) ran with the default materialized_only = true, because the
old migration that enabled real-time mode (017) predated their creation
(020) and they were never revisited. As a result the all_event_stats_1m
and _1h UNION views mixed freshness: 016-era branches served data up to
the current minute while these five groups lagged by the refresh
interval (up to ~2 min on the 1m tier, ~1 h on the 1h tier).

Set materialized_only = false on all 28 count-table aggregates in the
baseline, so every branch of the UNION views has the same freshness
(node_stats_1m and service_stats_1m already had it). Edited in-place
rather than as a new migration — the squash requires recreating every
database anyway, so there is no ledger to preserve.

The performance caveat from the old migration 017 carries over: the
tail scan reads the raw count table for the un-materialized window on
every query. If aggregate queries slow down on a 1024-node network,
this setting is the first thing to check (per-view revert recipe in the
migration comment).

@s0me0ne-unkn0wn s0me0ne-unkn0wn left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks clean, and the reasoning makes sense. I confess I didn't thoroughly read through all the SQL, but structurally everything seems to be in its place.

Comment thread tests/README.md
Comment on lines +40 to +42
# NOTE: if your tart_test predates the migration squash (2026-08), drop it once
# first (`cargo sqlx database drop -y && cargo sqlx database create`) — the old
# _sqlx_migrations ledger doesn't match the squashed migration set.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that nobody writes tests by hand nowadays, this is better placed somewhere like AGENTS.md or CLAUDE.md. I wouldn't count on an agent developing something and adding a test for it to watch in this file for guidelines.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used that note in my tests recently :), yeah feel free to add agents or claude.md in some future work.

@michalkucharczyk
michalkucharczyk merged commit 4d663f2 into main Aug 5, 2026
6 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