mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-13 08:02:47 +00:00
* fix: track outstanding service log files on the rows themselves Adds `log_file.indexed_at` so the service log ingest can read outstanding rows instead of walking a cursor over `log_ts`. A row registered after the pass had gone by its minute was skipped for good, and no ordering fixes that — an arrival sequence fails the same way, since a row can take a lower value and commit after a higher one has moved the cursor past it. The migration marks existing rows with a sentinel; the first pass returns the ones the old cursor had not reached to the queue. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EPAP96jJNYpPQ8bpxZcU1C * [ee] refactor: drop the claim/confirm phase from the service log ingest queue Two states are enough: a row is outstanding or it is marked. The migration no longer creates the index for the claim sentinel, and the sqlx cache loses the two queries the event-time cursor used. * [ee] fix: make re-indexing a service log file idempotent Corrects the `init_last_log_file_sent` note: a rewritten row keeps the `indexed_at` it had, so one the indexers already took is not offered again. * [ee] fix: let a rebuild take the rows it covered out of the ingest queue Adds the query that releases them; the index layout stays v4. * [ee] fix: index the lookup a rebuild releases rows by A rebuild takes rows out of the queue by the file it read out of the store, which is the one lookup that arrives without a `log_ts`. The primary key is `(hostname, log_ts)`, so nothing covered it and each batch scanned every outstanding row — worst in exactly the state a rebuild follows. Verified at 50k outstanding rows: sequential scan becomes an index scan. Also records `log_file.indexed_at` in the schema reference. * [ee] fix: treat a state handed back without its line count as behind * [ee] fix: give the converted state a line count * [ee] fix: keep the converted cursor from being rewound by the rebuild * [ee] fix: inherit the legacy cursor from one source, not field by field * [ee] fix: count a file's lines against the buffer before reading it * [ee] fix: bound the row buffer on what it holds, not on reported counts * [ee] fix: settle the upgrade from the store rather than from event time * [ee] docs: describe the conversion's second half as it now works * [ee] refactor: settle the upgrade with one rebuild instead of reconciling The migration records existing rows as done rather than marking them with a sentinel: the indexer puts back what the old cursor had not reached on its first pass, which is the only place that cursor's position is known. * [ee] fix: repair the rows the old cursor skipped instead of recording them as done The migration marks pre-existing rows with a sentinel again, so the indexer can tell them from rows registered since and put the window's worth back on the queue. * [ee] fix: keep a source file whole in one partition * [ee] revert the file-atomic partition change * [ee] fix: dedupe the public reads, and repair an index without a cursor * [ee] fix: repair an index whose cursor is gone, and keep what the repair found * [ee] fix: seed a pass from both axes of what a rebuild recovered * [ee] fix: settle the cursor on what the store holds, not on what was read * [ee] fix: an empty rebuild must not claim ground it has not covered * [ee] test: pin the cursor a rebuild settles on * chore: update ee-repo-ref to bc0c7051585194474078b6c1941a3fb73893d9e5 This commit updates the EE repository reference after PR #755 was merged in windmill-ee-private. Previous ee-repo-ref: 328f5a90afeae9c683bf3294f0d9eb293a3e1a92 New ee-repo-ref: bc0c7051585194474078b6c1941a3fb73893d9e5 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
36 lines
2.3 KiB
SQL
36 lines
2.3 KiB
SQL
-- The service log ingest walked `log_file` with a cursor over `log_ts`, which is when a line
|
|
-- was written rather than when its row appeared. Rows do not arrive in that order — an upload
|
|
-- retried after a failure, a host that has just started, a batch the row limit cut mid-minute —
|
|
-- and a row that becomes visible behind the cursor is never read: it stays in `log_file` and its
|
|
-- lines stay out of search until retention drops them.
|
|
--
|
|
-- No ordering fixes this. A cursor over arrival order fails the same way, because `nextval` is
|
|
-- allocated before its INSERT commits: a row can be assigned a lower value and commit after a
|
|
-- higher one has already moved the cursor past it. Which rows are outstanding is a property of
|
|
-- the rows, so it is recorded on them.
|
|
ALTER TABLE log_file ADD COLUMN indexed_at TIMESTAMPTZ;
|
|
|
|
-- Rows that already existed are marked, not queued: on a 14-day window most were ingested long
|
|
-- ago and their raw files are gone. A sentinel rather than a timestamp, because the indexer has to
|
|
-- tell them apart from rows registered since — those start NULL — and it puts the window's worth of
|
|
-- them back on the queue on its first pass, keeping only what the columnar store can vouch for.
|
|
--
|
|
-- Not split here on the cursor the old ingest had reached. Below that cursor sits every row it
|
|
-- skipped, which is the loss this migration exists to stop; recording those as done would carry the
|
|
-- bug into its own fix.
|
|
UPDATE log_file SET indexed_at = 'epoch' WHERE indexed_at IS NULL;
|
|
|
|
-- The work queue, and the only index the ingest query needs: outstanding rows are a small
|
|
-- fraction of the table, so this stays proportional to what is left to do rather than to the
|
|
-- retention window.
|
|
CREATE INDEX index_log_file_pending ON log_file (log_ts) WHERE indexed_at IS NULL;
|
|
|
|
-- A rebuild takes rows out of the queue by the file it just read out of the store, which is
|
|
-- the one lookup that arrives without a `log_ts`: the primary key is `(hostname, log_ts)`, so
|
|
-- nothing else covers it and each batch would scan every outstanding row instead.
|
|
CREATE INDEX index_log_file_pending_path ON log_file (hostname, file_path) WHERE indexed_at IS NULL;
|
|
|
|
-- Reached once per pass while pre-migration rows survive, and never again after the first
|
|
-- conversion clears them.
|
|
CREATE INDEX index_log_file_premigration ON log_file (log_ts) WHERE indexed_at = 'epoch';
|