Skip to content

feat(remote): seed the drift baseline from the stored snapshot on connect - #197

Merged
veksen merged 1 commit into
mainfrom
feat-seed-drift-baseline
Jul 27, 2026
Merged

feat(remote): seed the drift baseline from the stored snapshot on connect#197
veksen merged 1 commit into
mainfrom
feat-seed-drift-baseline

Conversation

@veksen

@veksen veksen commented Jul 27, 2026

Copy link
Copy Markdown
Member

Closes Query-Doctor/Site#3670.

Goal

Make a stale Production Statistics snapshot heal itself, with no user action.

#195 added drift detection, but it measures against the last dump this process pushed. An analyzer that has never pushed has no baseline and never drifts. That is every project whose snapshot was seeded by hand.

Query Doctor's own project is the case: an analyzer connected for 55 days, heartbeating, that has pushed statistics zero times. Its snapshot was taken by a manual psql dump on 2026-06-18 and six tables added since are uncovered.

What

Before, drift armed only after this process dumped from source at least once.

After, the analyzer adopts the server's stored snapshot as its baseline on connect. The first schema poll then compares the live schema against it and re-dumps if it has fallen behind.

How

Remote.seedStatsBaseline takes a snapshot and records it as the drift baseline. ApiConnection.connectWithReconnect calls getProductionStats() after connecting and passes the result in. That RPC already exists and is already called on the CI path, so there is no contract change.

Two guards, both tested:

  • Seeding never pushes. These numbers came from the server. Emitting them would republish a stale snapshot as though it were a fresh dump.
  • Seeding is ignored once a baseline exists. Otherwise a reconnect would discard a fresher local baseline for the server's older copy, and re-dump on every reconnect.

The fetch is fire-and-forget. If it fails, drift stays inert until a local dump sets a baseline, which is the behaviour before this change.

Tests

seed-stats-baseline.test.ts, four cases: a seeded baseline makes a new table read as Shape Drift; an empty snapshot leaves drift inert; a second seed does not overwrite the first; seeding emits no statsApplied. No container needed, since seeding only writes to memory.

…nect

Closes #3670.

Drift is measured against the last dump this process pushed, so an analyzer
that has never pushed has no baseline and never drifts. That is every project
whose snapshot was seeded by hand. Query Doctor's own analyzer has been
connected for 55 days without pushing statistics once, on a snapshot taken by
a manual psql dump on 2026-06-18, leaving six tables uncovered.

On connect, adopt the snapshot the server already holds as the baseline. The
first schema poll then compares the live schema against it and re-dumps if it
has fallen behind. ServerApi.getProductionStats already exists and is already
called on the CI path, so no contract change is needed.

Seeding never pushes. The numbers came from the server, and echoing them back
would republish a stale snapshot as though it were a fresh dump. It is also
ignored once a baseline exists, so a reconnect can't discard a fresher local
one in favour of the server's older copy.

Co-Authored-By: Claude <noreply@anthropic.com>

@github-actions github-actions Bot 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.

Query Doctor Analysis

3 queries analyzed

0 regressed · 0 improved · 0 new · 0 removed

2 pre-existing issues

Using assumed statistics (10000000 rows/table). For better results, sync production stats.

More detail → get_ci_run({ runId: "019fa54e-fce8-76a2-bbd6-ca3c06df5b0c" }) · view run · docs

@veksen
veksen merged commit ce873b2 into main Jul 27, 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.

1 participant