diff --git a/backend/windmill-common/src/min_version.rs b/backend/windmill-common/src/min_version.rs index fe6dd98ca4..80b3871f3d 100644 --- a/backend/windmill-common/src/min_version.rs +++ b/backend/windmill-common/src/min_version.rs @@ -8,17 +8,6 @@ use semver::Version; // reads that column is live, and those runnables run as their deployer with no error anywhere. pub const MIN_VERSION_SUPPORTS_ON_BEHALF_OF_PRINCIPAL: VC = vc(1, 776, 0, "On-behalf-of principal"); - -/// Names the release that stops reading `schedule.email`. Errs a minor high for the same reason -/// as the constant above: the column is still written for the workers below this version whose -/// `get_schedule_opt` selects it, inside the same transaction as the job completion — a missing -/// column would roll that completion back and leave the occurrence to be re-executed. -/// -/// Nothing gates on this at runtime; it exists so `vc()`'s compile-time assert fires once -/// `MIN_KEEP_ALIVE_VERSION` passes it. Even then the column takes two releases to remove, because -/// a rolling deploy runs both versions at once: see `docs/schedule-email-removal.md`. -pub const MIN_VERSION_DERIVES_SCHEDULE_EMAIL: VC = - vc(1, 777, 0, "Schedule email derived from permissioned_as"); pub const MIN_VERSION_SUPPORTS_NODE_DEBOUNCING: VC = vc(1, 658, 0, "Flow node debouncing"); pub const MIN_VERSION_SUPPORTS_TOKEN_HASH: VC = vc(1, 659, 0, "Token hash storage"); pub const MIN_VERSION_SUPPORTS_SYNC_JOBS_DEBOUNCING: VC = vc(1, 602, 0, "Sync jobs debouncing"); diff --git a/backend/windmill-types/src/schedule.rs b/backend/windmill-types/src/schedule.rs index b74d3186a5..3f184b2ead 100644 --- a/backend/windmill-types/src/schedule.rs +++ b/backend/windmill-types/src/schedule.rs @@ -71,10 +71,8 @@ impl Schedule { /// response says what the *next run* will resolve to. The workspace export reads the stored /// column, so a synced file reproduces the row — a principal whose account has since been /// removed keeps the address the file already had instead of turning into a synthetic -/// `@unknown.windmill.dev`. The column goes when -/// `windmill_common::min_version::MIN_VERSION_DERIVES_SCHEDULE_EMAIL` expires (not a link: this -/// crate is below `windmill-common`, not above it); this field stays, filled by deriving on both -/// paths. +/// `@unknown.windmill.dev`. The column goes once no supported worker still reads it +/// (`docs/schedule-email-removal.md`); this field stays, filled by deriving on both paths. // No `Deserialize`: `Schedule` is flattened in, and serde's flatten buffers through an untagged // representation that `RawValue` (this type's `args`) cannot be read back from. `FromRow` is // unaffected — it reads columns by name. diff --git a/docs/schedule-email-removal.md b/docs/schedule-email-removal.md index e3ed8d4e2d..afd874c8bd 100644 --- a/docs/schedule-email-removal.md +++ b/docs/schedule-email-removal.md @@ -2,13 +2,18 @@ A schedule's identity is its `permissioned_as`; the address beside it is a function of that principal. `schedule.email` is no longer read for the identity, but it is still written, because -workers below `MIN_VERSION_DERIVES_SCHEDULE_EMAIL` (`windmill-common/src/min_version.rs`) select -it in `get_schedule_opt` — inside the same transaction as the job completion, so a missing column -rolls that completion back and the occurrence runs again. +workers before **1.777** select it in `get_schedule_opt` — inside the same transaction as the job +completion, so a missing column rolls that completion back and the occurrence runs again. That is +the failure to keep in mind throughout: not a wrong address, a schedule that runs twice. -When that constraint stops compiling, no supported worker reads the column. Removal still takes -two releases: the last readers are this codebase's own, and a rolling deploy runs both versions -at once. +The column can go once no worker older than 1.777 can be live, in practice once +`MIN_KEEP_ALIVE_VERSION` (`windmill-common/src/min_version.rs`) has passed it. There is no +`MIN_VERSION_*` constant for this and it does not need one: those gate behavior at runtime, and +nothing here does — the write is unconditional, so no worker meets the column's absence until +someone follows the steps below. + +Removal still takes two releases: the last readers are this codebase's own, and a rolling deploy +runs both versions at once. ## Release A — code only, column untouched