@substrat-run/kernel 0.148.0 → 0.149.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/attachment-sweep.d.ts +208 -0
- package/dist/attachment-sweep.d.ts.map +1 -0
- package/dist/attachment-sweep.js +318 -0
- package/dist/attachment-sweep.js.map +1 -0
- package/dist/index.d.ts +15 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -7
- package/dist/index.js.map +1 -1
- package/dist/invocation-line.d.ts +85 -0
- package/dist/invocation-line.d.ts.map +1 -1
- package/dist/invocation-line.js +43 -0
- package/dist/invocation-line.js.map +1 -1
- package/dist/migration-digest.d.ts +56 -0
- package/dist/migration-digest.d.ts.map +1 -1
- package/dist/migration-digest.js +92 -0
- package/dist/migration-digest.js.map +1 -1
- package/dist/migration-fence.d.ts +14 -0
- package/dist/migration-fence.d.ts.map +1 -0
- package/dist/migration-fence.js +515 -0
- package/dist/migration-fence.js.map +1 -0
- package/dist/migration-replay.d.ts +52 -0
- package/dist/migration-replay.d.ts.map +1 -0
- package/dist/migration-replay.js +140 -0
- package/dist/migration-replay.js.map +1 -0
- package/dist/module-migrations.d.ts +3 -3
- package/dist/module-migrations.js +3 -3
- package/dist/peer.d.ts +32 -2
- package/dist/peer.d.ts.map +1 -1
- package/dist/peer.js +99 -3
- package/dist/peer.js.map +1 -1
- package/dist/permission-eval.d.ts +8 -0
- package/dist/permission-eval.d.ts.map +1 -1
- package/dist/permission-eval.js +14 -0
- package/dist/permission-eval.js.map +1 -1
- package/dist/platform-sweep.d.ts +94 -1
- package/dist/platform-sweep.d.ts.map +1 -1
- package/dist/platform-sweep.js +130 -0
- package/dist/platform-sweep.js.map +1 -1
- package/dist/promote-review.d.ts +125 -0
- package/dist/promote-review.d.ts.map +1 -0
- package/dist/promote-review.js +181 -0
- package/dist/promote-review.js.map +1 -0
- package/dist/scope-host.d.ts +204 -42
- package/dist/scope-host.d.ts.map +1 -1
- package/dist/scope-host.js.map +1 -1
- package/dist/scope-store.d.ts +5 -5
- package/dist/scope-store.d.ts.map +1 -1
- package/dist/spine-restore.d.ts +2 -0
- package/dist/spine-restore.d.ts.map +1 -1
- package/dist/spine-restore.js +5 -0
- package/dist/spine-restore.js.map +1 -1
- package/dist/store-driver-releases.d.ts +306 -0
- package/dist/store-driver-releases.d.ts.map +1 -0
- package/dist/store-driver-releases.js +581 -0
- package/dist/store-driver-releases.js.map +1 -0
- package/dist/table-ownership.d.ts +5 -2
- package/dist/table-ownership.d.ts.map +1 -1
- package/dist/table-ownership.js +19 -10
- package/dist/table-ownership.js.map +1 -1
- package/dist/testing.d.ts +2 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +2 -0
- package/dist/testing.js.map +1 -1
- package/dist/upload-link.d.ts +60 -7
- package/dist/upload-link.d.ts.map +1 -1
- package/dist/upload-link.js +189 -25
- package/dist/upload-link.js.map +1 -1
- package/dist/version-migrations.d.ts +63 -1
- package/dist/version-migrations.d.ts.map +1 -1
- package/dist/version-migrations.js +174 -8
- package/dist/version-migrations.js.map +1 -1
- package/dist/vertical-scope-stores.d.ts +9 -9
- package/dist/vertical-scope-stores.d.ts.map +1 -1
- package/dist/vertical-scope-stores.js +29 -29
- package/dist/vertical-scope-stores.js.map +1 -1
- package/package.json +2 -2
- package/dist/store-kind-releases.d.ts +0 -137
- package/dist/store-kind-releases.d.ts.map +0 -1
- package/dist/store-kind-releases.js +0 -252
- package/dist/store-kind-releases.js.map +0 -1
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A store driver's releases, its rollouts and the holds that serialize them (D-63, #2300), shared by
|
|
3
|
+
* both adapters' directories.
|
|
4
|
+
*
|
|
5
|
+
* - `store_driver_releases`: a release's bytes were stored (the bytes themselves live outside the
|
|
6
|
+
* directory, keyed by driver and sha256). Insert-only: who uploaded a release, and from which
|
|
7
|
+
* commit, is never rewritten.
|
|
8
|
+
* - `store_driver_rollouts`: one row per attempt to move every script of the driver to a release, in
|
|
9
|
+
* `seq` order. A row is `rolling` until its holder ends it `good`, `failed` or `diverged`.
|
|
10
|
+
* - `store_driver_current`: the release the last `good` rollout moved every script to.
|
|
11
|
+
* - `store_driver_rollout_walks`: the walk ledger of a rollout paged over several requests (#2312).
|
|
12
|
+
* Each row is one declaration (vertical, binding, and the version that first declared it) an
|
|
13
|
+
* earlier request of the same attempt walked; the next request walks only what is not in it.
|
|
14
|
+
*
|
|
15
|
+
* "The immediately previous good release" (D-63) is recorded, never derived from an ordering:
|
|
16
|
+
* each rollout row names `previous_good_sha256`, the release a rollback from it returns to. A
|
|
17
|
+
* rollout of T from current F records F; a rollback goes to the current row's previous good X, and
|
|
18
|
+
* records X's own previous good, so after r1 → r2 → r3 one rollback reaches r2 and the next r1.
|
|
19
|
+
*
|
|
20
|
+
* A hold is a lease: `exclusive` for a rollout or a rollback, `shared` for a push or serve that
|
|
21
|
+
* rebuilds a script at the release it runs, which a rollout must not interleave with (a rebuild
|
|
22
|
+
* that read the old release and uploaded after the rollout moved the script would revert it).
|
|
23
|
+
* A begin or finish is refused unless the caller still holds the driver exclusively, so a holder
|
|
24
|
+
* whose lease lapsed cannot write over the next one; its `rolling` row reads as `diverged` to the
|
|
25
|
+
* next rollout, which converges every script again.
|
|
26
|
+
*
|
|
27
|
+
* - `store_driver_rebuilds` (#2309): the platform's walk that rebuilds every script of the driver
|
|
28
|
+
* at the release it runs, after what the platform builds a script from changed (a key list, the
|
|
29
|
+
* entry, its verifier). One row per driver: the `fingerprint` of what the platform builds from
|
|
30
|
+
* that the walk converges on, the last vertical it walked (`cursor`, in slug order), the
|
|
31
|
+
* verticals it could not rebuild, and whether it is `done`. A new fingerprint starts the walk
|
|
32
|
+
* again. The row carries its own lease, so two passes never walk one driver at once.
|
|
33
|
+
*/
|
|
34
|
+
import { substratError } from '@substrat-run/contracts';
|
|
35
|
+
import { driverDeclarationsOf } from './vertical-scope-stores.js';
|
|
36
|
+
/** Interpolated into both adapters' directory DDL, so `lint:spine-ddl` sees one spelling on each side. */
|
|
37
|
+
export const STORE_DRIVER_RELEASES_DDL = `
|
|
38
|
+
CREATE TABLE IF NOT EXISTS store_driver_releases (
|
|
39
|
+
driver TEXT NOT NULL,
|
|
40
|
+
sha256 TEXT NOT NULL,
|
|
41
|
+
source_commit TEXT NOT NULL,
|
|
42
|
+
uploaded_by TEXT NOT NULL,
|
|
43
|
+
uploaded_at TEXT NOT NULL,
|
|
44
|
+
PRIMARY KEY (driver, sha256)
|
|
45
|
+
);
|
|
46
|
+
CREATE TABLE IF NOT EXISTS store_driver_rollouts (
|
|
47
|
+
driver TEXT NOT NULL,
|
|
48
|
+
seq INTEGER NOT NULL,
|
|
49
|
+
sha256 TEXT NOT NULL,
|
|
50
|
+
action TEXT NOT NULL,
|
|
51
|
+
from_sha256 TEXT,
|
|
52
|
+
previous_good_sha256 TEXT,
|
|
53
|
+
state TEXT NOT NULL,
|
|
54
|
+
actor TEXT NOT NULL,
|
|
55
|
+
-- The hold the rollout runs under: a rolling row whose holder holds nothing has stopped.
|
|
56
|
+
holder TEXT NOT NULL,
|
|
57
|
+
started_at TEXT NOT NULL,
|
|
58
|
+
ended_at TEXT,
|
|
59
|
+
detail TEXT,
|
|
60
|
+
PRIMARY KEY (driver, seq)
|
|
61
|
+
);
|
|
62
|
+
CREATE TABLE IF NOT EXISTS store_driver_current (
|
|
63
|
+
driver TEXT PRIMARY KEY,
|
|
64
|
+
sha256 TEXT NOT NULL,
|
|
65
|
+
seq INTEGER NOT NULL
|
|
66
|
+
);
|
|
67
|
+
-- One declaration an attempt walked (#2312). The attempt is the seq of its first row; a row
|
|
68
|
+
-- continues it while the rows before it are paused at the same release and action.
|
|
69
|
+
CREATE TABLE IF NOT EXISTS store_driver_rollout_walks (
|
|
70
|
+
driver TEXT NOT NULL,
|
|
71
|
+
attempt INTEGER NOT NULL,
|
|
72
|
+
vertical_slug TEXT NOT NULL,
|
|
73
|
+
binding TEXT NOT NULL,
|
|
74
|
+
first_version_id TEXT NOT NULL,
|
|
75
|
+
PRIMARY KEY (driver, attempt, vertical_slug, binding, first_version_id)
|
|
76
|
+
);
|
|
77
|
+
CREATE TABLE IF NOT EXISTS store_driver_holds (
|
|
78
|
+
driver TEXT NOT NULL,
|
|
79
|
+
holder TEXT NOT NULL,
|
|
80
|
+
mode TEXT NOT NULL,
|
|
81
|
+
expires_at INTEGER NOT NULL,
|
|
82
|
+
PRIMARY KEY (driver, holder)
|
|
83
|
+
);
|
|
84
|
+
CREATE TABLE IF NOT EXISTS store_driver_rebuilds (
|
|
85
|
+
driver TEXT PRIMARY KEY,
|
|
86
|
+
fingerprint TEXT NOT NULL,
|
|
87
|
+
-- When this fingerprint was first walked towards: a restart keeps it, a new fingerprint resets it.
|
|
88
|
+
fingerprint_since TEXT NOT NULL,
|
|
89
|
+
cursor TEXT,
|
|
90
|
+
failures TEXT NOT NULL,
|
|
91
|
+
state TEXT NOT NULL,
|
|
92
|
+
holder TEXT,
|
|
93
|
+
lease_expires_at INTEGER NOT NULL,
|
|
94
|
+
-- When this walk began from its first script: a restart or a new fingerprint sets it, a pass
|
|
95
|
+
-- that continues the walk keeps it.
|
|
96
|
+
started_at TEXT NOT NULL,
|
|
97
|
+
-- The person who attested, when this walk began, that no control-plane deploy was rolling out.
|
|
98
|
+
attested_by TEXT,
|
|
99
|
+
-- When a walk towards this fingerprint last proved every script current; kept across a
|
|
100
|
+
-- restart at the same fingerprint, cleared by a new one.
|
|
101
|
+
verified_at TEXT,
|
|
102
|
+
updated_at TEXT NOT NULL,
|
|
103
|
+
finished_at TEXT
|
|
104
|
+
);
|
|
105
|
+
`;
|
|
106
|
+
/**
|
|
107
|
+
* The directory's names from before a store's code was called a driver (K-53's rename): the four
|
|
108
|
+
* release tables were `store_kind_*`, and they and `vertical_scope_stores` keyed by a `kind`
|
|
109
|
+
* column. The values are the same ids, so only names move.
|
|
110
|
+
*/
|
|
111
|
+
const LEGACY_STORE_DRIVER_TABLES = new Map([
|
|
112
|
+
['store_kind_releases', 'store_driver_releases'],
|
|
113
|
+
['store_kind_rollouts', 'store_driver_rollouts'],
|
|
114
|
+
['store_kind_current', 'store_driver_current'],
|
|
115
|
+
['store_kind_holds', 'store_driver_holds'],
|
|
116
|
+
]);
|
|
117
|
+
const DRIVER_KEYED_TABLES = [...LEGACY_STORE_DRIVER_TABLES.values(), 'vertical_scope_stores'];
|
|
118
|
+
/**
|
|
119
|
+
* The statements that move a directory built before the rename onto its names, to run before
|
|
120
|
+
* the directory's DDL on every start: that DDL is all `IF NOT EXISTS`, so it would leave an old
|
|
121
|
+
* table as it is and create an empty one beside it. Renames keep every row, a release uploaded
|
|
122
|
+
* before its pin included. Empty once moved, so a later start does nothing.
|
|
123
|
+
*
|
|
124
|
+
* A directory can hold both names: code from before the rename, run again after it (a rollback),
|
|
125
|
+
* creates the old tables empty beside the moved ones, and writes to them while it runs. Then the
|
|
126
|
+
* name that holds no rows is dropped, and the one that holds them ends under the new name. When
|
|
127
|
+
* both hold rows, both are left where they are: nothing is merged, and nothing with rows is
|
|
128
|
+
* dropped.
|
|
129
|
+
*
|
|
130
|
+
* `tables` is every table the directory holds; `columnsOf` answers a table's columns, and
|
|
131
|
+
* `hasRows` whether it holds any.
|
|
132
|
+
*/
|
|
133
|
+
export function legacyStoreDriverRenames(tables, columnsOf, hasRows) {
|
|
134
|
+
const held = new Set(tables.map((t) => t.toLowerCase()));
|
|
135
|
+
const statements = [];
|
|
136
|
+
const renamed = new Set();
|
|
137
|
+
for (const [from, to] of LEGACY_STORE_DRIVER_TABLES) {
|
|
138
|
+
if (!held.has(from))
|
|
139
|
+
continue;
|
|
140
|
+
if (held.has(to)) {
|
|
141
|
+
if (!hasRows(from)) {
|
|
142
|
+
statements.push(`DROP TABLE ${from}`);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (hasRows(to))
|
|
146
|
+
continue;
|
|
147
|
+
statements.push(`DROP TABLE ${to}`);
|
|
148
|
+
}
|
|
149
|
+
statements.push(`ALTER TABLE ${from} RENAME TO ${to}`);
|
|
150
|
+
renamed.add(to);
|
|
151
|
+
}
|
|
152
|
+
for (const table of DRIVER_KEYED_TABLES) {
|
|
153
|
+
const columns = renamed.has(table) ? ['kind'] : held.has(table) ? (columnsOf(table) ?? []) : [];
|
|
154
|
+
const lowered = columns.map((c) => c.toLowerCase());
|
|
155
|
+
if (lowered.includes('kind') && !lowered.includes('driver')) {
|
|
156
|
+
statements.push(`ALTER TABLE ${table} RENAME COLUMN kind TO driver`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return statements;
|
|
160
|
+
}
|
|
161
|
+
/** What to do about a table that holds rows under both names (see {@link legacyStoreDriverRenames}). */
|
|
162
|
+
const BOTH_NAMES_REMEDY = 'Restore a directory dump taken before the pre-rename code ran again (a restore replaces every table), ' +
|
|
163
|
+
'or export the store_kind_* rows, carry over any that are still wanted, and drop the store_kind_* tables by hand.';
|
|
164
|
+
/**
|
|
165
|
+
* The tables that hold rows under both names, which {@link legacyStoreDriverRenames} leaves
|
|
166
|
+
* alone, as one line a start logs: until one is cleared, a directory dump carries both and a
|
|
167
|
+
* restore of it is refused. Undefined when there are none. Reachable only after a rollback to
|
|
168
|
+
* pre-rename code that wrote a release, rollout or hold, which no registered driver allowed yet.
|
|
169
|
+
*/
|
|
170
|
+
export function legacyStoreDriverConflict(tables, hasRows) {
|
|
171
|
+
const held = new Set(tables.map((t) => t.toLowerCase()));
|
|
172
|
+
const both = [...LEGACY_STORE_DRIVER_TABLES].filter(([from, to]) => held.has(from) && held.has(to) && hasRows(from) && hasRows(to));
|
|
173
|
+
if (both.length === 0)
|
|
174
|
+
return undefined;
|
|
175
|
+
return (`substrat: the directory holds rows under both ${both.map(([from, to]) => `${from} and ${to}`).join(', ')}: ` +
|
|
176
|
+
`code from before the store driver rename (K-53) ran again and wrote them. Both are kept, and a directory ` +
|
|
177
|
+
`dump of it is refused at restore until one is cleared. ${BOTH_NAMES_REMEDY}`);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* A directory dump's tables with the pre-rename names mapped onto this code's (see
|
|
181
|
+
* {@link legacyStoreDriverRenames}), so a copy taken before the rename restores: the dump's rows
|
|
182
|
+
* go in by name, and a restore refuses a table it does not build. A dump that carries a table
|
|
183
|
+
* under both names keeps the one that holds rows, the way a start does; one where both hold rows
|
|
184
|
+
* is refused, since loading both would merge two histories.
|
|
185
|
+
*/
|
|
186
|
+
export function mapLegacyStoreDriverDump(tables) {
|
|
187
|
+
const byName = new Map(tables.map((t) => [t.name.toLowerCase(), t]));
|
|
188
|
+
const dropped = new Set();
|
|
189
|
+
for (const [from, to] of LEGACY_STORE_DRIVER_TABLES) {
|
|
190
|
+
const legacy = byName.get(from);
|
|
191
|
+
const current = byName.get(to);
|
|
192
|
+
if (!legacy || !current)
|
|
193
|
+
continue;
|
|
194
|
+
if (legacy.rows.length === 0)
|
|
195
|
+
dropped.add(legacy);
|
|
196
|
+
else if (current.rows.length === 0)
|
|
197
|
+
dropped.add(current);
|
|
198
|
+
else {
|
|
199
|
+
throw substratError('validation_failed', `restore refused: the dump carries rows in both ${legacy.name} and ${current.name}, the same table ` +
|
|
200
|
+
`before and after the store driver rename (K-53). Nothing was changed. ${BOTH_NAMES_REMEDY}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return tables.filter((t) => !dropped.has(t)).map((t) => {
|
|
204
|
+
const name = LEGACY_STORE_DRIVER_TABLES.get(t.name.toLowerCase()) ?? t.name;
|
|
205
|
+
if (!DRIVER_KEYED_TABLES.includes(name.toLowerCase()))
|
|
206
|
+
return t;
|
|
207
|
+
const columns = t.columns.map((c) => c.toLowerCase());
|
|
208
|
+
const keepsKind = columns.includes('kind') && !columns.includes('driver');
|
|
209
|
+
return { ...t, name, columns: keepsKind ? t.columns.map((c) => (c.toLowerCase() === 'kind' ? 'driver' : c)) : t.columns };
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
const rolloutOf = (r) => ({
|
|
213
|
+
driver: r.driver,
|
|
214
|
+
seq: Number(r.seq),
|
|
215
|
+
sha256: r.sha256,
|
|
216
|
+
action: r.action,
|
|
217
|
+
fromSha256: r.from_sha256,
|
|
218
|
+
previousGoodSha256: r.previous_good_sha256,
|
|
219
|
+
state: r.state,
|
|
220
|
+
actor: r.actor,
|
|
221
|
+
startedAt: r.started_at,
|
|
222
|
+
endedAt: r.ended_at,
|
|
223
|
+
detail: r.detail,
|
|
224
|
+
});
|
|
225
|
+
const ROLLOUT_COLUMNS = 'driver, seq, sha256, action, from_sha256, previous_good_sha256, state, actor, started_at, ended_at, detail';
|
|
226
|
+
function rolloutAt(db, driver, seq) {
|
|
227
|
+
const [row] = db.all(`SELECT ${ROLLOUT_COLUMNS} FROM store_driver_rollouts WHERE driver = ? AND seq = ?`, driver, seq);
|
|
228
|
+
return row ? rolloutOf(row) : undefined;
|
|
229
|
+
}
|
|
230
|
+
/** A stored release, or undefined. */
|
|
231
|
+
export function storeDriverReleaseIn(db, driver, sha256) {
|
|
232
|
+
const [row] = db.all('SELECT driver, sha256, source_commit, uploaded_by, uploaded_at FROM store_driver_releases WHERE driver = ? AND sha256 = ?', driver, sha256);
|
|
233
|
+
return row
|
|
234
|
+
? { driver: row.driver, sha256: row.sha256, sourceCommit: row.source_commit, uploadedBy: row.uploaded_by, uploadedAt: row.uploaded_at }
|
|
235
|
+
: undefined;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Record that a release's bytes are stored. The same sha256 again is the same release, and the
|
|
239
|
+
* row already written is returned as it stands (`created: false`). The same sha256 from another
|
|
240
|
+
* commit is refused (`conflict`): one bundle has one source the reviewer reads.
|
|
241
|
+
*/
|
|
242
|
+
export function recordStoreDriverReleaseIn(db, input) {
|
|
243
|
+
const held = storeDriverReleaseIn(db, input.driver, input.sha256);
|
|
244
|
+
if (held) {
|
|
245
|
+
if (held.sourceCommit !== input.sourceCommit) {
|
|
246
|
+
throw substratError('conflict', `release ${input.sha256} of '${input.driver}' is stored as built from ${held.sourceCommit}, not ${input.sourceCommit}`);
|
|
247
|
+
}
|
|
248
|
+
return { record: held, created: false };
|
|
249
|
+
}
|
|
250
|
+
db.run('INSERT INTO store_driver_releases (driver, sha256, source_commit, uploaded_by, uploaded_at) VALUES (?, ?, ?, ?, ?)', input.driver, input.sha256, input.sourceCommit, input.actor, input.at);
|
|
251
|
+
return { record: storeDriverReleaseIn(db, input.driver, input.sha256), created: true };
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* The driver's current release, every rollout, and where a rollback goes now.
|
|
255
|
+
*
|
|
256
|
+
* With `nowMs`, a `rolling` row whose holder no longer holds the driver exclusively is reported as
|
|
257
|
+
* `diverged` (read-time only, nothing is written): its holder stopped, and its scripts may be on
|
|
258
|
+
* either release. The next rollout's begin writes that state.
|
|
259
|
+
*
|
|
260
|
+
* `rollbackTarget` is, in order:
|
|
261
|
+
* - the target of a rollback that is the newest attempt since the current release, a `failed` one
|
|
262
|
+
* aside, and ended `paused` or `diverged` (`unfinishedRollback`): posting the rollback again
|
|
263
|
+
* continues it, and never turns it around onto the release it is leaving. A `failed` request
|
|
264
|
+
* changes nothing here: it moved nothing, or returned what its attempt moved, or (a later page's
|
|
265
|
+
* canary) moved nothing in its own request while earlier pages' verticals stay on the new
|
|
266
|
+
* release; those pages' `paused` rows are still since the current release, so the fleet still
|
|
267
|
+
* reads as mixed below. No rollout may begin while a
|
|
268
|
+
* rollback to an earlier release is unfinished, `paused` or `diverged` (`beginStoreDriverRolloutIn`):
|
|
269
|
+
* it is finished first, by posting it again. A rollback onto the current release (undoing a
|
|
270
|
+
* diverged rollout) does not block a rollout. A rollback to an earlier release cannot meet the
|
|
271
|
+
* schema rule (the route refuses one below the current schema), but one onto the current release
|
|
272
|
+
* can, and then it never finishes, so going forward must stay open;
|
|
273
|
+
* - the current release itself, when a rollout since it ended `diverged` or `paused` on ANOTHER
|
|
274
|
+
* release: the fleet may be mixed, and undoing that rollout means converging every script back
|
|
275
|
+
* on the release it was healthy on, never going past it. A row that moves scripts to the current
|
|
276
|
+
* release itself (a re-post of it, paged over several requests, or a rollback onto it) leaves
|
|
277
|
+
* every script on the current release whatever it ended, so it never makes the fleet mixed:
|
|
278
|
+
* otherwise re-posting the current release past one request's walk would turn the rollback
|
|
279
|
+
* onto the release being escaped (#2312);
|
|
280
|
+
* - otherwise the immediately previous good release.
|
|
281
|
+
* An unfinished attempt never changes what "previous good" means.
|
|
282
|
+
*/
|
|
283
|
+
export function storeDriverStateIn(db, driver, nowMs) {
|
|
284
|
+
const live = nowMs === undefined
|
|
285
|
+
? undefined
|
|
286
|
+
: new Set(db.all("SELECT holder FROM store_driver_holds WHERE driver = ? AND mode = 'exclusive' AND expires_at > ?", driver, nowMs).map((h) => h.holder));
|
|
287
|
+
const rows = db.all(`SELECT ${ROLLOUT_COLUMNS}, holder FROM store_driver_rollouts WHERE driver = ? ORDER BY seq`, driver);
|
|
288
|
+
const rollouts = rows.map((r) => live && r.state === 'rolling' && !(r.holder && live.has(r.holder))
|
|
289
|
+
? rolloutOf({ ...r, state: 'diverged', detail: 'its holder no longer holds the driver; the rollout stopped before it ended' })
|
|
290
|
+
: rolloutOf(r));
|
|
291
|
+
const [current] = db.all('SELECT sha256, seq FROM store_driver_current WHERE driver = ?', driver);
|
|
292
|
+
if (!current)
|
|
293
|
+
return { current: null, rollouts, rollbackTarget: null, unfinishedRollback: null };
|
|
294
|
+
const seq = Number(current.seq);
|
|
295
|
+
const row = rollouts.find((r) => r.seq === seq);
|
|
296
|
+
const previousGoodSha256 = row?.previousGoodSha256 ?? null;
|
|
297
|
+
const since = rollouts.filter((r) => r.seq > seq);
|
|
298
|
+
// A failed request never decides what comes next (see above).
|
|
299
|
+
const newest = since.filter((r) => r.state !== 'failed').at(-1);
|
|
300
|
+
const unfinishedRollback = newest?.action === 'rollback' && (newest.state === 'paused' || newest.state === 'diverged') ? newest.sha256 : null;
|
|
301
|
+
const mixed = since.some((r) => (r.state === 'diverged' || r.state === 'paused') && r.sha256 !== current.sha256);
|
|
302
|
+
return {
|
|
303
|
+
current: { sha256: current.sha256, seq, previousGoodSha256 },
|
|
304
|
+
rollouts,
|
|
305
|
+
rollbackTarget: unfinishedRollback ?? (mixed ? current.sha256 : previousGoodSha256),
|
|
306
|
+
unfinishedRollback,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Take, or renew, a hold on a driver. Answers false when another holder's live hold excludes it: an
|
|
311
|
+
* exclusive one for any request, or any one for an exclusive request. A lapsed hold is dropped
|
|
312
|
+
* first. Asking in the other mode than the one held is refused.
|
|
313
|
+
*
|
|
314
|
+
* `renew` only extends a hold the holder still holds: a holder whose lease lapsed gets false, even
|
|
315
|
+
* when nobody took the driver since, because a lapsed holder cannot know what happened meanwhile.
|
|
316
|
+
* With `rolloutSeq` it also answers false unless that rollout is still `rolling`, so a rollout
|
|
317
|
+
* whose row another holder ended stops instead of moving scripts the state no longer describes.
|
|
318
|
+
*/
|
|
319
|
+
export function holdStoreDriverIn(db, input) {
|
|
320
|
+
if (!(input.ttlMs > 0))
|
|
321
|
+
throw substratError('validation_failed', 'a store-driver hold needs a positive lifetime');
|
|
322
|
+
db.run('DELETE FROM store_driver_holds WHERE driver = ? AND expires_at <= ?', input.driver, input.nowMs);
|
|
323
|
+
const live = db.all('SELECT holder, mode FROM store_driver_holds WHERE driver = ?', input.driver);
|
|
324
|
+
const own = live.find((h) => h.holder === input.holder);
|
|
325
|
+
if (own && own.mode !== input.mode) {
|
|
326
|
+
throw substratError('conflict', `holder ${input.holder} holds '${input.driver}' ${own.mode}, not ${input.mode}`);
|
|
327
|
+
}
|
|
328
|
+
if ((input.renew || input.rolloutSeq !== undefined) && !own)
|
|
329
|
+
return false;
|
|
330
|
+
if (input.rolloutSeq !== undefined && rolloutAt(db, input.driver, input.rolloutSeq)?.state !== 'rolling')
|
|
331
|
+
return false;
|
|
332
|
+
const others = live.filter((h) => h.holder !== input.holder);
|
|
333
|
+
if (input.mode === 'exclusive' ? others.length > 0 : others.some((h) => h.mode === 'exclusive'))
|
|
334
|
+
return false;
|
|
335
|
+
db.run(`INSERT INTO store_driver_holds (driver, holder, mode, expires_at) VALUES (?, ?, ?, ?)
|
|
336
|
+
ON CONFLICT (driver, holder) DO UPDATE SET expires_at = excluded.expires_at`, input.driver, input.holder, input.mode, input.nowMs + input.ttlMs);
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
/** Drop a hold. Dropping one already gone is not an error. */
|
|
340
|
+
export function releaseStoreDriverHoldIn(db, input) {
|
|
341
|
+
db.run('DELETE FROM store_driver_holds WHERE driver = ? AND holder = ?', input.driver, input.holder);
|
|
342
|
+
}
|
|
343
|
+
function assertExclusive(db, driver, holder, nowMs) {
|
|
344
|
+
const [row] = db.all("SELECT 1 AS held FROM store_driver_holds WHERE driver = ? AND holder = ? AND mode = 'exclusive' AND expires_at > ?", driver, holder, nowMs);
|
|
345
|
+
if (!row)
|
|
346
|
+
throw substratError('conflict', `'${driver}' is not held exclusively by ${holder}`);
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Begin a rollout or a rollback of a stored release, as the exclusive holder. A rollout left
|
|
350
|
+
* `rolling` by an earlier holder ends `diverged` here: its scripts may be on either release, and
|
|
351
|
+
* this rollout reaches all of them. A rollback must name the current release's previous good one.
|
|
352
|
+
*/
|
|
353
|
+
export function beginStoreDriverRolloutIn(db, input) {
|
|
354
|
+
assertExclusive(db, input.driver, input.holder, input.nowMs);
|
|
355
|
+
if (!storeDriverReleaseIn(db, input.driver, input.sha256)) {
|
|
356
|
+
throw substratError('not_found', `release ${input.sha256} of '${input.driver}' is not stored`);
|
|
357
|
+
}
|
|
358
|
+
db.run(`UPDATE store_driver_rollouts SET state = 'diverged', ended_at = ?, detail = 'its holder stopped before the rollout ended'
|
|
359
|
+
WHERE driver = ? AND state = 'rolling'`, input.at, input.driver);
|
|
360
|
+
const { current, rollbackTarget, unfinishedRollback } = storeDriverStateIn(db, input.driver, input.nowMs);
|
|
361
|
+
// A rollback under way to an earlier release blocks every rollout until it ends good. One onto
|
|
362
|
+
// the current release (undoing a diverged rollout) does not: if a script refuses to go below its
|
|
363
|
+
// schema, that rollback can never finish, and going forward is the way out.
|
|
364
|
+
if (input.action === 'rollout' && unfinishedRollback && unfinishedRollback !== current?.sha256) {
|
|
365
|
+
throw substratError('conflict', `a rollback of '${input.driver}' to ${unfinishedRollback} is part way through; post the rollback again to finish it before any rollout`);
|
|
366
|
+
}
|
|
367
|
+
let previousGood;
|
|
368
|
+
if (input.action === 'rollback') {
|
|
369
|
+
if (!current || !rollbackTarget)
|
|
370
|
+
throw substratError('conflict', `'${input.driver}' has no previous good release to roll back to`);
|
|
371
|
+
if (rollbackTarget !== input.sha256) {
|
|
372
|
+
throw substratError('conflict', `a rollback of '${input.driver}' returns to ${rollbackTarget}, not ${input.sha256}`);
|
|
373
|
+
}
|
|
374
|
+
if (input.sha256 === current.sha256) {
|
|
375
|
+
// Undoing a diverged rollout: back onto the current release, whose previous good stays.
|
|
376
|
+
previousGood = current.previousGoodSha256;
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
const [made] = db.all(`SELECT previous_good_sha256 FROM store_driver_rollouts
|
|
380
|
+
WHERE driver = ? AND sha256 = ? AND state = 'good' ORDER BY seq DESC LIMIT 1`, input.driver, input.sha256);
|
|
381
|
+
previousGood = made?.previous_good_sha256 ?? null;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
// Rolling out the current release again (a resume) keeps where a rollback from it returns to.
|
|
386
|
+
previousGood = current ? (current.sha256 === input.sha256 ? current.previousGoodSha256 : current.sha256) : null;
|
|
387
|
+
}
|
|
388
|
+
const next = Number(db.all('SELECT COALESCE(MAX(seq), 0) + 1 AS next FROM store_driver_rollouts WHERE driver = ?', input.driver)[0].next);
|
|
389
|
+
db.run(`INSERT INTO store_driver_rollouts (${ROLLOUT_COLUMNS}, holder) VALUES (?, ?, ?, ?, ?, ?, 'rolling', ?, ?, NULL, NULL, ?)`, input.driver, next, input.sha256, input.action, current?.sha256 ?? null, previousGood, input.actor, input.at, input.holder);
|
|
390
|
+
return rolloutAt(db, input.driver, next);
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* End a rollout the caller began, as the exclusive holder. A good one makes its release current.
|
|
394
|
+
*
|
|
395
|
+
* `walked` is what this request walked, and only a `paused` end takes it (#2312): it joins the
|
|
396
|
+
* attempt's ledger in the transaction that writes the state, so a request that stops before its
|
|
397
|
+
* end leaves no ledger rows, and the next attempt walks those verticals again rather than skip
|
|
398
|
+
* them. What keeps a dead ledger unread is the attempt key (`attemptOf`); the deletes here keep the
|
|
399
|
+
* table to the one attempt a driver can continue: any end drops every other attempt's rows, and any
|
|
400
|
+
* end but `paused` this attempt's too.
|
|
401
|
+
*/
|
|
402
|
+
export function finishStoreDriverRolloutIn(db, input) {
|
|
403
|
+
assertExclusive(db, input.driver, input.holder, input.nowMs);
|
|
404
|
+
const row = rolloutAt(db, input.driver, input.seq);
|
|
405
|
+
if (!row)
|
|
406
|
+
throw substratError('not_found', `'${input.driver}' has no rollout ${input.seq}`);
|
|
407
|
+
if (row.state !== 'rolling')
|
|
408
|
+
throw substratError('conflict', `rollout ${input.seq} of '${input.driver}' already ended ${row.state}`);
|
|
409
|
+
if (input.walked && input.state !== 'paused') {
|
|
410
|
+
throw substratError('validation_failed', `only a paused rollout records what it walked; ${input.seq} of '${input.driver}' ends ${input.state}`);
|
|
411
|
+
}
|
|
412
|
+
db.run('UPDATE store_driver_rollouts SET state = ?, ended_at = ?, detail = ? WHERE driver = ? AND seq = ?', input.state, input.at, input.detail, input.driver, input.seq);
|
|
413
|
+
const attempt = attemptOf(db, input.driver, input.seq, row.sha256, row.action);
|
|
414
|
+
db.run(`DELETE FROM store_driver_rollout_walks WHERE driver = ?${input.state === 'paused' ? ' AND attempt <> ?' : ''}`, ...(input.state === 'paused' ? [input.driver, attempt] : [input.driver]));
|
|
415
|
+
if (input.state === 'paused') {
|
|
416
|
+
for (const target of input.walked ?? []) {
|
|
417
|
+
for (const store of target.stores) {
|
|
418
|
+
db.run(`INSERT OR IGNORE INTO store_driver_rollout_walks (driver, attempt, vertical_slug, binding, first_version_id) VALUES (?, ?, ?, ?, ?)`, input.driver, attempt, target.vertical, store.binding, store.firstVersionId);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (input.state === 'good') {
|
|
423
|
+
db.run(`INSERT INTO store_driver_current (driver, sha256, seq) VALUES (?, ?, ?)
|
|
424
|
+
ON CONFLICT (driver) DO UPDATE SET sha256 = excluded.sha256, seq = excluded.seq`, input.driver, row.sha256, input.seq);
|
|
425
|
+
}
|
|
426
|
+
return rolloutAt(db, input.driver, input.seq);
|
|
427
|
+
}
|
|
428
|
+
const rebuildRowOf = (db, driver) => db.all('SELECT driver, fingerprint, fingerprint_since, cursor, failures, state, holder, lease_expires_at, started_at, attested_by, verified_at, updated_at, finished_at FROM store_driver_rebuilds WHERE driver = ?', driver)[0];
|
|
429
|
+
const rebuildOf = (r) => ({
|
|
430
|
+
driver: r.driver,
|
|
431
|
+
fingerprint: r.fingerprint,
|
|
432
|
+
fingerprintSince: r.fingerprint_since,
|
|
433
|
+
cursor: r.cursor,
|
|
434
|
+
failures: JSON.parse(r.failures),
|
|
435
|
+
state: r.state,
|
|
436
|
+
startedAt: r.started_at,
|
|
437
|
+
attestedBy: r.attested_by,
|
|
438
|
+
verifiedAt: r.verified_at,
|
|
439
|
+
updatedAt: r.updated_at,
|
|
440
|
+
finishedAt: r.finished_at,
|
|
441
|
+
});
|
|
442
|
+
/** The driver's fleet rebuild, or undefined before its first. */
|
|
443
|
+
export function storeDriverRebuildIn(db, driver) {
|
|
444
|
+
const row = rebuildRowOf(db, driver);
|
|
445
|
+
return row ? rebuildOf(row) : undefined;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Take the lease on a driver's fleet rebuild, towards `fingerprint`, for `ttlMs`. Answers the
|
|
449
|
+
* rebuild as it stands, or null while another holder's lease is live. A rebuild towards another
|
|
450
|
+
* fingerprint (or none yet) starts over: no vertical is walked and none has failed, because every
|
|
451
|
+
* script may have been built from something else than what the platform builds from now. With
|
|
452
|
+
* `restart`, a rebuild already `done` at this fingerprint starts over too (a re-verification: a
|
|
453
|
+
* script uploaded since by a control plane still building from older inputs is found and rebuilt).
|
|
454
|
+
* With `attestedBy` (a person attesting no control-plane deploy is rolling out), the rebuild starts
|
|
455
|
+
* over and the new walk carries the attestation, unless a walk this attestation (any person's, at
|
|
456
|
+
* this fingerprint) already started is under way: that walk is continued, so repeating an attested
|
|
457
|
+
* run finishes a fleet larger than one run. Any other start clears it.
|
|
458
|
+
*/
|
|
459
|
+
export function claimStoreDriverRebuildIn(db, input) {
|
|
460
|
+
if (!(input.ttlMs > 0))
|
|
461
|
+
throw substratError('validation_failed', 'a store-driver rebuild lease needs a positive lifetime');
|
|
462
|
+
const row = rebuildRowOf(db, input.driver);
|
|
463
|
+
if (row && row.holder !== null && row.holder !== input.holder && Number(row.lease_expires_at) > input.nowMs)
|
|
464
|
+
return null;
|
|
465
|
+
const lease = input.nowMs + input.ttlMs;
|
|
466
|
+
// An attested walk under way at these lists is the attestation's own: continued, never restarted.
|
|
467
|
+
const attestedUnderway = row?.fingerprint === input.fingerprint && row.state === 'running' && row.attested_by !== null;
|
|
468
|
+
if (!row ||
|
|
469
|
+
row.fingerprint !== input.fingerprint ||
|
|
470
|
+
(input.restart && row.state === 'done') ||
|
|
471
|
+
(input.attestedBy !== undefined && !attestedUnderway)) {
|
|
472
|
+
db.run(`INSERT INTO store_driver_rebuilds (driver, fingerprint, fingerprint_since, cursor, failures, state, holder, lease_expires_at, started_at, attested_by, verified_at, updated_at, finished_at)
|
|
473
|
+
VALUES (?, ?, ?, NULL, '[]', 'running', ?, ?, ?, ?, NULL, ?, NULL)
|
|
474
|
+
ON CONFLICT (driver) DO UPDATE SET fingerprint = excluded.fingerprint, cursor = NULL, failures = '[]', state = 'running',
|
|
475
|
+
fingerprint_since = CASE WHEN store_driver_rebuilds.fingerprint = excluded.fingerprint
|
|
476
|
+
THEN store_driver_rebuilds.fingerprint_since ELSE excluded.fingerprint_since END,
|
|
477
|
+
verified_at = CASE WHEN store_driver_rebuilds.fingerprint = excluded.fingerprint
|
|
478
|
+
THEN store_driver_rebuilds.verified_at ELSE NULL END,
|
|
479
|
+
holder = excluded.holder, lease_expires_at = excluded.lease_expires_at, started_at = excluded.started_at,
|
|
480
|
+
attested_by = excluded.attested_by, updated_at = excluded.updated_at, finished_at = NULL`, input.driver, input.fingerprint, input.at, input.holder, lease, input.at, input.attestedBy ?? null, input.at);
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
db.run('UPDATE store_driver_rebuilds SET holder = ?, lease_expires_at = ? WHERE driver = ?', input.holder, lease, input.driver);
|
|
484
|
+
}
|
|
485
|
+
return rebuildOf(rebuildRowOf(db, input.driver));
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Record how far the lease holder's walk got, renewing the lease for `ttlMs`, or with `release`
|
|
489
|
+
* dropping it. `done` ends the rebuild; it needs no failure left. Refused (`conflict`) unless the
|
|
490
|
+
* caller is still the row's holder, towards `fingerprint`: once another pass claimed the row (a
|
|
491
|
+
* lapsed lease) or restarted it (a new fingerprint), the old holder writes nothing. A holder whose
|
|
492
|
+
* lease lapsed while nobody claimed the row still records what it did, which is then true. With
|
|
493
|
+
* `verified` (only with `done`), the walk proved every script current, and `verifiedAt` is set.
|
|
494
|
+
*/
|
|
495
|
+
export function advanceStoreDriverRebuildIn(db, input) {
|
|
496
|
+
const row = rebuildRowOf(db, input.driver);
|
|
497
|
+
if (!row || row.holder !== input.holder || row.fingerprint !== input.fingerprint) {
|
|
498
|
+
throw substratError('conflict', `the rebuild of '${input.driver}' is not held by ${input.holder}`);
|
|
499
|
+
}
|
|
500
|
+
if (input.done && input.failures.length > 0) {
|
|
501
|
+
throw substratError('validation_failed', `the rebuild of '${input.driver}' is not done while a vertical failed`);
|
|
502
|
+
}
|
|
503
|
+
if (input.verified && !input.done) {
|
|
504
|
+
throw substratError('validation_failed', `the rebuild of '${input.driver}' proves nothing before it is done`);
|
|
505
|
+
}
|
|
506
|
+
db.run(`UPDATE store_driver_rebuilds SET cursor = ?, failures = ?, state = ?, holder = ?, lease_expires_at = ?, updated_at = ?, finished_at = ?,
|
|
507
|
+
verified_at = COALESCE(?, verified_at)
|
|
508
|
+
WHERE driver = ?`, input.cursor, JSON.stringify(input.failures), input.done ? 'done' : 'running', input.release ? null : input.holder, input.release ? 0 : input.nowMs + input.ttlMs, input.at, input.done ? input.at : null, input.verified ? input.at : null, input.driver);
|
|
509
|
+
return rebuildOf(rebuildRowOf(db, input.driver));
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* The attempt the rollout at `seq` belongs to: the seq of the first row of the run of `paused`
|
|
513
|
+
* rows of the same release and action just before it, or `seq` itself. Any other row between
|
|
514
|
+
* (good, failed, diverged, a rolling one left by a holder that stopped, another release) ends the
|
|
515
|
+
* run, so its ledger is never read: what it walked may since have been moved elsewhere.
|
|
516
|
+
*/
|
|
517
|
+
function attemptOf(db, driver, seq, sha256, action) {
|
|
518
|
+
const before = db.all('SELECT seq, sha256, action, state FROM store_driver_rollouts WHERE driver = ? AND seq < ? ORDER BY seq DESC', driver, seq);
|
|
519
|
+
let attempt = seq;
|
|
520
|
+
for (const row of before) {
|
|
521
|
+
if (row.state !== 'paused' || row.sha256 !== sha256 || row.action !== action)
|
|
522
|
+
break;
|
|
523
|
+
attempt = Number(row.seq);
|
|
524
|
+
}
|
|
525
|
+
return attempt;
|
|
526
|
+
}
|
|
527
|
+
/** Rows in (vertical, binding) order, grouped by vertical. */
|
|
528
|
+
function targetsOf(rows) {
|
|
529
|
+
const byVertical = new Map();
|
|
530
|
+
for (const r of rows) {
|
|
531
|
+
const stores = byVertical.get(r.vertical_slug) ?? [];
|
|
532
|
+
stores.push({ binding: r.binding, firstVersionId: r.first_version_id });
|
|
533
|
+
byVertical.set(r.vertical_slug, stores);
|
|
534
|
+
}
|
|
535
|
+
return [...byVertical].map(([vertical, stores]) => ({ vertical, stores }));
|
|
536
|
+
}
|
|
537
|
+
const assertLimit = (limit) => {
|
|
538
|
+
if (!(Number.isInteger(limit) && limit > 0))
|
|
539
|
+
throw substratError('validation_failed', 'a rollout page needs a positive limit');
|
|
540
|
+
};
|
|
541
|
+
/** A declaration the attempt walked: the ledger row of the same vertical, binding and first version. */
|
|
542
|
+
const WALKED = `EXISTS (SELECT 1 FROM store_driver_rollout_walks AS w
|
|
543
|
+
WHERE w.driver = s.driver AND w.attempt = ? AND w.vertical_slug = s.vertical_slug
|
|
544
|
+
AND w.binding = s.binding AND w.first_version_id = s.first_version_id)`;
|
|
545
|
+
/**
|
|
546
|
+
* What the next request of a rollout of `sha256` (or a rollback to it) walks (#2312): the first
|
|
547
|
+
* `limit` verticals, in (vertical, binding) order, with a declaration of the driver that the attempt
|
|
548
|
+
* it would continue has not walked, and how many verticals are pending in all. Asked before the
|
|
549
|
+
* request's row begins, as the exclusive holder will begin it: a request that continues no attempt
|
|
550
|
+
* walks every declaration. `walked` counts the verticals the continued attempt walked that still
|
|
551
|
+
* declare the driver. `unreadable` is `driverDeclarationsOf`'s: a caller that must reach every script
|
|
552
|
+
* refuses while it is not empty.
|
|
553
|
+
*/
|
|
554
|
+
export function storeDriverRolloutPendingIn(db, input) {
|
|
555
|
+
assertLimit(input.limit);
|
|
556
|
+
// Indexes every vertical not indexed yet, and names the ones that cannot say what they declare.
|
|
557
|
+
const { unreadable } = driverDeclarationsOf(db, input.driver);
|
|
558
|
+
const next = Number(db.all('SELECT COALESCE(MAX(seq), 0) + 1 AS next FROM store_driver_rollouts WHERE driver = ?', input.driver)[0].next);
|
|
559
|
+
const attempt = attemptOf(db, input.driver, next, input.sha256, input.action);
|
|
560
|
+
const rows = db.all(`SELECT s.vertical_slug, s.binding, s.first_version_id, ${WALKED} AS walked
|
|
561
|
+
FROM vertical_scope_stores AS s WHERE s.driver = ? ORDER BY s.vertical_slug, s.binding`, attempt, input.driver);
|
|
562
|
+
const pending = targetsOf(rows.filter((r) => !r.walked));
|
|
563
|
+
const walked = new Set(rows.filter((r) => r.walked).map((r) => r.vertical_slug)).size;
|
|
564
|
+
return { verticals: pending.slice(0, input.limit), pending: pending.length, walked, unreadable };
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* What the attempt of the rollout at `seq` walked in its EARLIER requests and still declares the
|
|
568
|
+
* driver, in (vertical, binding) order: the verticals a failure part way returns, besides the ones
|
|
569
|
+
* its own request reached (#2312). At most `limit`, and `walked` counts them all.
|
|
570
|
+
*/
|
|
571
|
+
export function storeDriverRolloutWalkedIn(db, input) {
|
|
572
|
+
assertLimit(input.limit);
|
|
573
|
+
const row = rolloutAt(db, input.driver, input.seq);
|
|
574
|
+
if (!row)
|
|
575
|
+
throw substratError('not_found', `'${input.driver}' has no rollout ${input.seq}`);
|
|
576
|
+
const attempt = attemptOf(db, input.driver, input.seq, row.sha256, row.action);
|
|
577
|
+
const walked = targetsOf(db.all(`SELECT s.vertical_slug, s.binding, s.first_version_id FROM vertical_scope_stores AS s
|
|
578
|
+
WHERE s.driver = ? AND ${WALKED} ORDER BY s.vertical_slug, s.binding`, input.driver, attempt));
|
|
579
|
+
return { verticals: walked.slice(0, input.limit), walked: walked.length };
|
|
580
|
+
}
|
|
581
|
+
//# sourceMappingURL=store-driver-releases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-driver-releases.js","sourceRoot":"","sources":["../src/store-driver-releases.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ScopedSql } from './scope-host.js';
|
|
1
|
+
import type { ScopedSql, SqlMigration } from './scope-host.js';
|
|
2
2
|
/**
|
|
3
3
|
* The spine table the ownership lives in — a scope table, so it travels with the scope's data.
|
|
4
4
|
* The name is spelled out rather than interpolated: `lint:spine-ddl` reads this text as written.
|
|
@@ -60,7 +60,10 @@ export interface TableStep {
|
|
|
60
60
|
* afterwards (`recordOwnershipSteps`), so the journal's `rows_changed` counts the migration's
|
|
61
61
|
* own writes and none of the kernel's bookkeeping.
|
|
62
62
|
*/
|
|
63
|
-
export declare function runMigrationStatements(sql: ScopedSql,
|
|
63
|
+
export declare function runMigrationStatements(sql: ScopedSql, migration: SqlMigration, exec: (statement: string) => void, step: {
|
|
64
|
+
readonly key: string;
|
|
65
|
+
readonly authored: boolean;
|
|
66
|
+
}): TableStep[];
|
|
64
67
|
/** Apply each recorded step to the ledger, in statement order, through `applyTableChange`. */
|
|
65
68
|
export declare function recordOwnershipSteps(sql: ScopedSql, moduleId: string, steps: readonly TableStep[], at: string): void;
|
|
66
69
|
/**
|