Repository navigation
Conversation
Signed-off-by: Jesse Hodges <hodges.jesse@gmail.com>
…ecks Signed-off-by: Jesse Hodges <hodges.jesse@gmail.com>
Signed-off-by: Jesse Hodges <hodges.jesse@gmail.com>
|
My concern is how much new behavior this adds to resolve the scheduler race. The option requires plan-time snapshot metadata, serialization through apply, scheduler-boundary counting, downstream coverage checks, and new rejection and recovery paths. For the hourly case, the replacement finishes its planned backfill through 10:00, but the incumbent has advanced through 11:00. This PR allows promotion with that hour missing. Production then serves less recent data until a later scheduler run repairs the replacement. Finalization does not mean that repair has completed. Could we handle this by backfilling the newly missing hour immediately before promotion, then retrying the existing strict check once? A second scheduler advance could still cause deployment to fail, but a successful deployment would retain the current coverage guarantee. I tried that approach in an isolated prototype. It worked for an hourly parent and child without replaying the whole plan or its plan-level hooks. It also exposed a downstream problem: if a child interval is already marked complete, filling the parent alone does not recompute the child. The overlap guard addresses that problem conservatively, but overlapping intervals can also be intentional. A forward-only child may reuse its production table and retain historical rows while its parent gets a replacement table. Our test confirmed that behavior, including the child using the new parent value on its next scheduled interval. So I’m not suggesting catch-up is a trivial replacement. I’d like to understand why accepting gaps is preferable to a bounded catch-up attempt, given that both approaches need to account for downstream coverage and table reuse. |
Related to #5825.
A production plan can finish its planned backfill and then fail the no-gap check because a scheduled run advanced the incumbent snapshot while the replacement was being built. This adds an opt-in policy that allows promotion and finalization when the replacement is missing only a bounded, contiguous trailing suffix created after the plan was built. The suffix stays missing in interval state so the normal scheduler can repair it.
Strict no-gap behavior remains the default (
0). The GitHub bot can opt in withmax_trailing_gap_intervals_on_deploy_to_prod=1; Python callers can useContext.plan_builder(..., no_gaps=True, max_trailing_gap_intervals=1). The underlying plan/promotion policy is independent of GitHub. This PR does not add a CLI flag or notebook magic option.Safety and scope
This is a bounded freshness tradeoff rather than the model-level locking proposed in the issue. Subsequent scheduler selections must include upstream dependencies. The bound applies to drift observed by the promotion check; an already-running scheduler is not fenced from advancing the old snapshot afterward. This change does not add durable repair tracking.
Validation
make stylepassed: Ruff, Ruff formatting, mypy, and migration validation.The implementation has also run in our production fork. Two production deployment attempts successfully used the allowance. For one, operations metadata and retained interval state corroborate subsequent repair on the exact promoted snapshot: the covering scheduler batch completed about 4m18s after finalization. This verifies one model's repair; it does not establish all downstream row values or a durable repair-time guarantee.