fix(warehouse-sources): hold imports for every converging rewrite - #95861
fix(warehouse-sources): hold imports for every converging rewrite#95861posthog[bot] wants to merge 5 commits into
Conversation
A repartition rewrite that spans several activity budgets resumes only while live stays at the Delta version its checkpoint was built against, and the schema's own merge is what moves it. The hold that stops that merge was gated behind a rollout flag targeting one schema, so every other large table discarded its checkpoint on each sync and restarted from row 0 until the controller gave up terminally. Drop the gate so a live rewrite checkpoint holds the import the same way a staged swap already does. The hold stays self-limiting: `held_at` is restamped on every checkpoint write, so a rewrite that stops advancing releases it. Also drop `capture_exception` on the terminal skip path, which opened an error tracking issue next to the skip event that already records the outcome. Generated-By: PostHog Desktop Task-Id: 75a24576-1509-4d7a-9aaf-d393e79bfd8c
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
🦔 PostHog Review reviewed this pull requestFound 1 must fix, 3 should fix, 1 consider. Published 5 findings (view the review). Resolved comments: 4 fixed |
🤖 CI report
|
There was a problem hiding this comment.
Not approved — escalated to a human reviewer.
Re-add the stamphog label to request another review once you have addressed this.
This removes a rollout-flag gate so that every schema (not just flag-targeted ones) now pauses its import while a multi-run repartition rewrite converges — a production behavior change to the warehouse data-import path with no independent review, and the bot author carries no familiarity signal to substitute for one.
- Widens the import-hold behavior from flag-targeted schemas to all schemas with a converging rewrite checkpoint, with zero reviews on the PR.
- Author is posthog[bot] (machine user via self-driving inbox task), not on the owning team, and familiarity carries no signal for this author type — no independent assurance covers this risky-territory change.
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 52L, 4F substantive, 87L/6F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T1-agent / T1c-medium (87L, 6F, single-area, fix) |
| stamphog 2.0.0b4 | .stamphog/policy.yml @ 55c523b · reviewed head 55c523b |
|
PostHog Review alpha 🦔 If you find any issues helpful - please reply "valid", "invalid", etc., for evaluation purposes 🙏 |
There was a problem hiding this comment.
PostHog Review
Found 1 must fix, 3 should fix, 1 consider.
Other findings (outside the changed lines)
Valid issues on this PR's files that sit on lines GitHub won't let us comment on inline.
Terminal budget failures lose stable observability
Priority: consider | File: products/warehouse_sources/backend/temporal/data_imports/workflow_activities/repartition_table.py:496-512 | Category: best_practice
Why we think it's a valid issue
- Checked: the terminal branch at
repartition_table.py:496-513, the sibling telemetry paths in the same file (_capture_stood_downat:602-624,_handle_failureat:841-877,_give_upat:735-754), the metric label space, and the raise site ofRepartitionTooLargeForBudgetErroratpipelines/core/repartition.py:1347. - Found: the branch catches two outcomes of unequal severity.
RepartitionUnpartitionableErroris benign, so dropping its report is correct.RepartitionTooLargeForBudgetErrormarks a table the controller abandons for good, and this PR's own docstring edit atrepartition.py:122-134narrows its meaning further: with the hold now always on, reaching it means the temp is gone or the hold lapsed, so it is an anomaly, not a designed outcome. - Found: the surviving signals lack the stable fields every sibling path carries.
props.update({"trigger_reason": ..., "reason": str(e)})at:508writes the raw message, which for the budget error embedsrows_written, the live row count, andschema_id(repartition.py:1347-1351), so the value differs on each occurrence._capture_stood_downsets"terminal": Falseat:618, and both failure paths seterror_typeat:745and:841. The terminal skip sets neither. The branch also emits no log line. - Found: the metric label is shared.
outcome="skipped"at:510is the same label the completed path emits at:575for the benignlive_unreadableandno_delta_tableresults (repartition.py:1261,:1283), so the counter cannot separate an abandoned table from a table that was simply unreadable this run. - Found: the removal contradicts a rule the file states twice.
repartition_table.py:750-753says the give-up captures "so a table the controller has abandoned surfaces as an issue instead of only a metric", and calls itself "the only terminal path that did not already report to error tracking". After this diff that sentence is false, andrepartition.py:216repeats the same principle forRepartitionAttemptsExhausted. - Impact: a table that can never converge is now visible only through one analytics event whose grouping key changes per occurrence, plus a counter label shared with benign skips. The table stays on the coarse layout that triggers the OOM, and the cooldown re-arms it at most daily, so the condition persists while nothing distinct reports it.
- Priority: lowered to
consider. The event and the counter still fire, and an operator can match thereasontext, so "cannot alert" overstates the loss. The path is also rarer after the hold fix. The gap is real and the fix is two props, but it costs telemetry shape, not correctness or user data.
Issue description
This deletion suppresses both terminal exception types. RepartitionTooLargeForBudgetError means a budget-exhausted checkpoint became unusable. The remaining metric combines this failure with benign skips. The event stores only a changing message with row counts and schema data. Operators cannot reliably group or alert on failed convergence.
Suggested fix
Add stable fields such as terminal=True, error_type=type(e).__name__, and a bounded reason_code. Alert on the budget-error code before removing its exception report.
The repartitioning runbook still contrasted the swap hold against a hold rollout flag this PR deletes, and never described the rewrite checkpoint hold at all. Drop the dead flag reference and add the checkpoint hold: what sets it, the event each held run records, the 48h lapse, and how it is released. Generated-By: PostHog Desktop Task-Id: e7ad8d78-ad98-4a02-84c2-8a23d6a7c4f4
Turning a controller flag off skips a queued rewrite, but left its checkpoint in place. The checkpoint holds the schema's imports until it ages out, and nothing resumes the rewrite while the flag is off, so the lever support uses to free a table stalled its syncs for up to two days instead. Drop the checkpoint on the release path. Nothing is lost: the imports that resume move the live Delta version the checkpoint is fenced on, and its temp table is swept before the next fresh rebuild. Generated-By: PostHog Desktop Task-Id: e7ad8d78-ad98-4a02-84c2-8a23d6a7c4f4
A table whose Delta log references missing data files heals inside the import activity, downstream of the repartition hold. The repartition activity and the detection pass both stand aside for that marker, but the hold did not, so a hollow table with a live rewrite checkpoint waited for the checkpoint to age out before its repair could run. Skip the checkpoint hold when a revive is pending. The revive rebuilds the table from source, so the checkpoint it holds for cannot survive it either way. A staged swap still holds: the revive is best-effort, and a merge that runs after it fails would land against a layout the schema row no longer describes. Generated-By: PostHog Desktop Task-Id: e7ad8d78-ad98-4a02-84c2-8a23d6a7c4f4
The hold ran before the activity read the reset request, so a resync, a sync-method change, or the automatic column-widening recovery could land on a table with a live rewrite checkpoint and complete having imported nothing and ignored the reset. No error surfaced, and each advancing rewrite renewed the hold, so the request could wait out the whole repartition. Resolve the reset before the hold and let it through. The rewrite is re-bucketing data the reset is about to delete, and its checkpoint is fenced on the live version the rebuild replaces, so there is nothing left to protect. A staged swap still holds: its temp table may be the only complete copy, and merging across a half-applied layout corrupts the table rather than dating it. Generated-By: PostHog Desktop Task-Id: e7ad8d78-ad98-4a02-84c2-8a23d6a7c4f4
Problem
capture_exception, so a handled outcome opened an error tracking issue next to thewarehouse_repartition_skippedevent that already records it.Changes
held_atis restamped on every checkpoint write, so a rewrite that stops advancing releases the hold and the worst case is a stale table, never a stopped one.data-warehouse-repartition-holdflag constant and its helper are removed, and comments that explained the gate are updated. The flag row can be deleted after this deploys.Note
This widens who can be held. Both holds follow from a repartition the schema already opted into, and holding is the cheaper trade: the alternative is not a fresher table, it is a rewrite that burns a full activity budget per run and converges on nothing.
How did you test this code?
pytest products/warehouse_sources/backend/temporal/data_imports/workflow_activities/tests/test_import_data_sync.py -k repartitionand.../pipelines/core/test_repartition.pypass locally.test_repartition_controller.pywas not run: this sandbox has no Postgres, so it was only collected. CI runs it.test_an_in_flight_repartition_holds_the_importgains arewrite_checkpointcase: it fails if the rewrite branch is re-gated or dropped, which is the exact defect fixed here. Extended rather than added, because the swap case already covers this function.test_a_terminal_rewrite_error_clears_pendinggains one assertion: a terminal skip must not report an exception.Automatic notifications
Docs update
None.
🤖 Agent context
Autonomy: Fully autonomous
/writing-tests,/writing-simplified-technical-english, plus the repo comment and PR-description conventions.rewrite_converginghold. The fix therefore removes the gate rather than adding a hold.gh pr list --state open --search repartitionfound no PR covering this. PR chore(warehouse): remove the always-on auto-coarsen rollout flag #95006 removes a different always-on warehouse rollout flag.Created with PostHog Desktop from this inbox report.