@substrat-run/control-plane-api 0.148.0 → 0.150.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/api.d.ts +19 -11
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +321 -93
- package/dist/api.js.map +1 -1
- package/dist/attachment-sweep.d.ts +30 -0
- package/dist/attachment-sweep.d.ts.map +1 -0
- package/dist/attachment-sweep.js +80 -0
- package/dist/attachment-sweep.js.map +1 -0
- package/dist/browser.d.ts +3 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +3 -0
- package/dist/browser.js.map +1 -1
- package/dist/cf-observability.d.ts.map +1 -1
- package/dist/cf-observability.js +3 -1
- package/dist/cf-observability.js.map +1 -1
- package/dist/deploy.d.ts +25 -11
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +32 -17
- package/dist/deploy.js.map +1 -1
- package/dist/index.d.ts +9 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/observability.d.ts +28 -0
- package/dist/observability.d.ts.map +1 -1
- package/dist/observability.js +35 -0
- package/dist/observability.js.map +1 -1
- package/dist/platform-entry.generated.d.ts +1 -1
- package/dist/platform-entry.generated.d.ts.map +1 -1
- package/dist/platform-entry.generated.js +2 -2
- package/dist/platform-entry.generated.js.map +1 -1
- package/dist/platform-scope-stores.d.ts +12 -12
- package/dist/platform-scope-stores.d.ts.map +1 -1
- package/dist/platform-scope-stores.js +21 -21
- package/dist/platform-scope-stores.js.map +1 -1
- package/dist/scope-copy-cleanup.d.ts +1 -1
- package/dist/scope-copy-cleanup.d.ts.map +1 -1
- package/dist/scope-copy-cleanup.js.map +1 -1
- package/dist/staff-client.d.ts +10 -2
- package/dist/staff-client.d.ts.map +1 -1
- package/dist/staff-client.js +6 -1
- package/dist/staff-client.js.map +1 -1
- package/dist/store-entry.d.ts +19 -19
- package/dist/store-entry.d.ts.map +1 -1
- package/dist/store-entry.generated.d.ts +16 -16
- package/dist/store-entry.generated.d.ts.map +1 -1
- package/dist/store-entry.generated.js +19 -19
- package/dist/store-entry.generated.js.map +1 -1
- package/dist/store-entry.js +43 -43
- package/dist/store-entry.js.map +1 -1
- package/dist/store-rebuild.d.ts +142 -0
- package/dist/store-rebuild.d.ts.map +1 -0
- package/dist/store-rebuild.js +223 -0
- package/dist/store-rebuild.js.map +1 -0
- package/dist/store-releases.d.ts +60 -49
- package/dist/store-releases.d.ts.map +1 -1
- package/dist/store-releases.js +134 -100
- package/dist/store-releases.js.map +1 -1
- package/dist/store-script.d.ts +37 -19
- package/dist/store-script.d.ts.map +1 -1
- package/dist/store-script.js +38 -23
- package/dist/store-script.js.map +1 -1
- package/dist/vertical-client.d.ts +29 -2
- package/dist/vertical-client.d.ts.map +1 -1
- package/dist/vertical-client.js +54 -2
- package/dist/vertical-client.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The platform's rebuild of every store script (#2309, D-63).
|
|
3
|
+
*
|
|
4
|
+
* A store script is built from a driver's release and from what the platform adds to every script:
|
|
5
|
+
* the entry, its verifier, the compatibility flags and both audiences' public key lists. A push, a
|
|
6
|
+
* serve or a rollout rebuilds the scripts it reaches. This walk rebuilds the rest when the platform's
|
|
7
|
+
* half changes, so a key dropped from a list (a revocation) or a verifier fix reaches every script
|
|
8
|
+
* whether or not its vertical is pushed again.
|
|
9
|
+
*
|
|
10
|
+
* What the platform builds from is one digest, `storePlatformFingerprint`. Each driver has one
|
|
11
|
+
* rebuild row in the directory: the fingerprint it converges on, the last vertical it walked, and
|
|
12
|
+
* the verticals it could not rebuild. A pass:
|
|
13
|
+
*
|
|
14
|
+
* - does nothing for a driver whose row is `done` at the current fingerprint (one directory read);
|
|
15
|
+
* - takes the row's lease (so two passes never walk one driver), then a **shared** hold on the
|
|
16
|
+
* driver, the hold a push takes. A rollout or rollback holds the driver exclusively, so a pass
|
|
17
|
+
* that meets one stops and the next pass continues. Under the shared hold no rollout can move a
|
|
18
|
+
* script between this walk's read of the release a script runs and its upload, which would
|
|
19
|
+
* upload the old release back over the new one;
|
|
20
|
+
* - rebuilds each script at the release it already runs (no `to`), so a rollout that paused part
|
|
21
|
+
* way, or a rollback that has not finished, keeps every script where it is. A script that does not
|
|
22
|
+
* exist is left alone, and one already built from the current fingerprint is not uploaded again;
|
|
23
|
+
* - walks the driver's canary script first, then each vertical that declared the driver, in slug
|
|
24
|
+
* order, recording the cursor after each, then retries the verticals that failed. At most
|
|
25
|
+
* `budget` scripts per pass, across drivers.
|
|
26
|
+
*
|
|
27
|
+
* The cursor is a slug, and a vertical behind it is not walked again. That is sound because every
|
|
28
|
+
* upload builds from the platform's current inputs: a vertical pushed or served after the walk
|
|
29
|
+
* passed its slug was built from the fingerprint the walk converges on, and one ahead of the cursor
|
|
30
|
+
* is reached and found current (no upload).
|
|
31
|
+
*/
|
|
32
|
+
import type { PlatformActorId, ScopeStoreNeed, StoreDriverRegistration } from '@substrat-run/contracts';
|
|
33
|
+
import { type HostAdmin, type StoreDriverRebuildRecord } from '@substrat-run/kernel';
|
|
34
|
+
import { type StoreReleaseBytes } from './store-releases.js';
|
|
35
|
+
import type { ScopeStoreEnsurerOptions } from './store-script.js';
|
|
36
|
+
type LoadRelease = ScopeStoreEnsurerOptions['loadRelease'];
|
|
37
|
+
/**
|
|
38
|
+
* The subrequests a pass of the walk may spend by default. A Worker invocation gets 1000 on the
|
|
39
|
+
* paid plan; the scheduled pass shares its invocation with every other phase, so it takes half.
|
|
40
|
+
* A staff request runs alone and may take {@link STORE_REBUILD_REQUEST_SUBREQUESTS}.
|
|
41
|
+
*/
|
|
42
|
+
export declare const STORE_REBUILD_PASS_SUBREQUESTS = 500;
|
|
43
|
+
export declare const STORE_REBUILD_REQUEST_SUBREQUESTS = 900;
|
|
44
|
+
/** The scripts a pass with `subrequests` to spend may walk: {@link STORE_REBUILD_SUBREQUESTS_PER_SCRIPT} each. */
|
|
45
|
+
export declare const storeRebuildBudget: (subrequests: number) => number;
|
|
46
|
+
/**
|
|
47
|
+
* How long a `done` rebuild stands before a scheduled pass walks it again. A walk that is done
|
|
48
|
+
* proves every script was current when it read it; a control plane still serving the older inputs
|
|
49
|
+
* (a deploy rolling out gradually) can upload a script after that. Walking it again reads each
|
|
50
|
+
* script's settings and uploads only a script that is not current.
|
|
51
|
+
*/
|
|
52
|
+
export declare const STORE_REBUILD_REVERIFY_MS: number;
|
|
53
|
+
/**
|
|
54
|
+
* How long after a fingerprint first appears a walk is not yet proof (#2309 review). While a
|
|
55
|
+
* control-plane deploy rolls out, the version still building from the older inputs can push a
|
|
56
|
+
* script after the walk read it. Only a walk that STARTED this long after its fingerprint was first
|
|
57
|
+
* walked towards proves every script current: a walk that spans passes reads its first scripts when
|
|
58
|
+
* it starts, so when it finishes says nothing about them. A done walk that started inside the window
|
|
59
|
+
* reads as settling, and the scheduled pass walks it again once the window has passed. A deploy that
|
|
60
|
+
* takes longer to roll out is followed by `store-driver rebuild`, or by a person's attestation that
|
|
61
|
+
* it has finished. The default; the control plane reads `STORE_REBUILD_SETTLE_MINUTES`.
|
|
62
|
+
*/
|
|
63
|
+
export declare const STORE_REBUILD_SETTLE_MS: number;
|
|
64
|
+
interface StoreFleetRebuildDeps {
|
|
65
|
+
admin: HostAdmin;
|
|
66
|
+
actor: PlatformActorId;
|
|
67
|
+
drivers: readonly StoreDriverRegistration[];
|
|
68
|
+
/** What the platform builds every script from now (`storePlatformFingerprint`). */
|
|
69
|
+
fingerprint: string;
|
|
70
|
+
bytes: StoreReleaseBytes;
|
|
71
|
+
/** Rebuild one vertical's scripts of a driver at the release each runs, existing scripts only. */
|
|
72
|
+
ensure: (input: {
|
|
73
|
+
vertical: string;
|
|
74
|
+
stores: readonly ScopeStoreNeed[];
|
|
75
|
+
existingOnly: true;
|
|
76
|
+
loadRelease: LoadRelease;
|
|
77
|
+
}) => Promise<void | {
|
|
78
|
+
uploaded: number;
|
|
79
|
+
}>;
|
|
80
|
+
/** Rebuild the driver's canary script the same way. */
|
|
81
|
+
ensureCanary: (input: {
|
|
82
|
+
driver: string;
|
|
83
|
+
existingOnly: true;
|
|
84
|
+
loadRelease: LoadRelease;
|
|
85
|
+
}) => Promise<{
|
|
86
|
+
uploaded: boolean;
|
|
87
|
+
}>;
|
|
88
|
+
/** The most scripts this pass walks, across drivers. */
|
|
89
|
+
budget: number;
|
|
90
|
+
/**
|
|
91
|
+
* When a `done` rebuild is walked again: `always` (a person asked for this pass), or once it has
|
|
92
|
+
* stood {@link STORE_REBUILD_REVERIFY_MS} (the scheduled pass).
|
|
93
|
+
*/
|
|
94
|
+
reverify: 'always' | 'when-due';
|
|
95
|
+
/** For a test: the clock the reverification is judged on. */
|
|
96
|
+
now?: () => number;
|
|
97
|
+
/** The settle window; {@link STORE_REBUILD_SETTLE_MS} by default. */
|
|
98
|
+
settleMs?: number;
|
|
99
|
+
/**
|
|
100
|
+
* A person's attestation that no control-plane deploy is rolling out: the walk starts over from
|
|
101
|
+
* its first script, and once done proves every script current whatever the settle window says.
|
|
102
|
+
* The actor attesting. Only for one driver at a time, from a staff request.
|
|
103
|
+
*/
|
|
104
|
+
attestedBy?: string;
|
|
105
|
+
}
|
|
106
|
+
export interface StoreDriverRebuildPass {
|
|
107
|
+
driver: string;
|
|
108
|
+
/**
|
|
109
|
+
* `current`: done at this fingerprint, nothing walked. `busy`: another pass holds the lease.
|
|
110
|
+
* `held`: a rollout or rollback holds the driver; the next pass continues. `paused`: the budget ran
|
|
111
|
+
* out with scripts left. `done`: every script walked, none failed. `failing`: every script walked,
|
|
112
|
+
* some failed; they are retried on the next pass. `error`: the pass could not walk the driver.
|
|
113
|
+
*/
|
|
114
|
+
outcome: 'current' | 'busy' | 'held' | 'paused' | 'done' | 'failing' | 'error';
|
|
115
|
+
/** The scripts walked this pass: a vertical's slug, or the canary's marker. */
|
|
116
|
+
walked: string[];
|
|
117
|
+
/** The ones of those that were uploaded. */
|
|
118
|
+
uploaded: string[];
|
|
119
|
+
rebuild?: StoreDriverRebuildRecord;
|
|
120
|
+
error?: string;
|
|
121
|
+
}
|
|
122
|
+
/** One pass of the walk over every driver, within `budget` scripts. */
|
|
123
|
+
export declare function runStoreFleetRebuild(deps: StoreFleetRebuildDeps): Promise<StoreDriverRebuildPass[]>;
|
|
124
|
+
/**
|
|
125
|
+
* Whether every script of a driver is built from what the platform builds from now, and which may
|
|
126
|
+
* not be: while the rebuild is towards another fingerprint (or none ran yet), the canary and every
|
|
127
|
+
* vertical that declared the driver; while it runs, the ones ahead of its cursor and the ones that
|
|
128
|
+
* failed. A push or serve may have rebuilt some of them since, and the walk then finds them
|
|
129
|
+
* current, so `pending` may over-count, never under-count. A walk that is done but not settled (see
|
|
130
|
+
* {@link STORE_REBUILD_SETTLE_MS}) is not current: `settling` says when it is walked again. `nextWalk`
|
|
131
|
+
* is when the scheduled pass walks a done rebuild again. A walk under way at lists an earlier walk
|
|
132
|
+
* already proved is `current` and `reverifying` until a script it reaches fails.
|
|
133
|
+
*/
|
|
134
|
+
export declare function storeRebuildStatus(rebuild: StoreDriverRebuildRecord | undefined, fingerprint: string, declared: readonly string[], settleMs?: number): {
|
|
135
|
+
current: boolean;
|
|
136
|
+
pending: string[];
|
|
137
|
+
settling?: string;
|
|
138
|
+
nextWalk?: string;
|
|
139
|
+
reverifying?: boolean;
|
|
140
|
+
};
|
|
141
|
+
export {};
|
|
142
|
+
//# sourceMappingURL=store-rebuild.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-rebuild.d.ts","sourceRoot":"","sources":["../src/store-rebuild.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { SCOPE_STORE_CANARY } from '@substrat-run/contracts';
|
|
2
|
+
import { ControlPlaneError } from '@substrat-run/control-plane-client';
|
|
3
|
+
import { ulid } from '@substrat-run/kernel';
|
|
4
|
+
import { PUSH_HOLD_TTL_MS, storedReleaseLoader } from './store-releases.js';
|
|
5
|
+
/**
|
|
6
|
+
* What one script of the walk costs in subrequests: the hold renewal, the script's settings read,
|
|
7
|
+
* the release's bytes (read once per release a pass meets, counted for every script to stay on the
|
|
8
|
+
* safe side), at most one upload, and the progress write.
|
|
9
|
+
*/
|
|
10
|
+
const STORE_REBUILD_SUBREQUESTS_PER_SCRIPT = 5;
|
|
11
|
+
/**
|
|
12
|
+
* The subrequests a pass of the walk may spend by default. A Worker invocation gets 1000 on the
|
|
13
|
+
* paid plan; the scheduled pass shares its invocation with every other phase, so it takes half.
|
|
14
|
+
* A staff request runs alone and may take {@link STORE_REBUILD_REQUEST_SUBREQUESTS}.
|
|
15
|
+
*/
|
|
16
|
+
export const STORE_REBUILD_PASS_SUBREQUESTS = 500;
|
|
17
|
+
export const STORE_REBUILD_REQUEST_SUBREQUESTS = 900;
|
|
18
|
+
/** The scripts a pass with `subrequests` to spend may walk: {@link STORE_REBUILD_SUBREQUESTS_PER_SCRIPT} each. */
|
|
19
|
+
export const storeRebuildBudget = (subrequests) => Math.max(1, Math.floor(subrequests / STORE_REBUILD_SUBREQUESTS_PER_SCRIPT));
|
|
20
|
+
/**
|
|
21
|
+
* How long a `done` rebuild stands before a scheduled pass walks it again. A walk that is done
|
|
22
|
+
* proves every script was current when it read it; a control plane still serving the older inputs
|
|
23
|
+
* (a deploy rolling out gradually) can upload a script after that. Walking it again reads each
|
|
24
|
+
* script's settings and uploads only a script that is not current.
|
|
25
|
+
*/
|
|
26
|
+
export const STORE_REBUILD_REVERIFY_MS = 24 * 60 * 60_000;
|
|
27
|
+
/**
|
|
28
|
+
* How long after a fingerprint first appears a walk is not yet proof (#2309 review). While a
|
|
29
|
+
* control-plane deploy rolls out, the version still building from the older inputs can push a
|
|
30
|
+
* script after the walk read it. Only a walk that STARTED this long after its fingerprint was first
|
|
31
|
+
* walked towards proves every script current: a walk that spans passes reads its first scripts when
|
|
32
|
+
* it starts, so when it finishes says nothing about them. A done walk that started inside the window
|
|
33
|
+
* reads as settling, and the scheduled pass walks it again once the window has passed. A deploy that
|
|
34
|
+
* takes longer to roll out is followed by `store-driver rebuild`, or by a person's attestation that
|
|
35
|
+
* it has finished. The default; the control plane reads `STORE_REBUILD_SETTLE_MINUTES`.
|
|
36
|
+
*/
|
|
37
|
+
export const STORE_REBUILD_SETTLE_MS = 60 * 60_000;
|
|
38
|
+
/**
|
|
39
|
+
* Whether a walk proves every script current once done: it started after the settle window, or a
|
|
40
|
+
* person attested, when it started, that no control-plane deploy was rolling out.
|
|
41
|
+
*/
|
|
42
|
+
const settled = (rebuild, settleMs) => rebuild.attestedBy !== null || Date.parse(rebuild.startedAt) - Date.parse(rebuild.fingerprintSince) >= settleMs;
|
|
43
|
+
const finishedMs = (rebuild) => Date.parse(rebuild.finishedAt ?? rebuild.updatedAt);
|
|
44
|
+
/** How long a pass's lease on a driver's rebuild lives between progress writes. */
|
|
45
|
+
const STORE_REBUILD_LEASE_TTL_MS = 10 * 60_000;
|
|
46
|
+
/**
|
|
47
|
+
* The binding an unreadable vertical's store is walked under. A script's name and build take the
|
|
48
|
+
* vertical and the driver only, so the binding names nothing the upload uses.
|
|
49
|
+
*/
|
|
50
|
+
const UNNAMED_BINDING = 'UNNAMED';
|
|
51
|
+
/** The cursor once the canary is walked: before every slug, after "not started" (null). */
|
|
52
|
+
const CANARY_WALKED = '';
|
|
53
|
+
const message = (e) => (e instanceof Error ? e.message : String(e));
|
|
54
|
+
/** One pass of the walk over every driver, within `budget` scripts. */
|
|
55
|
+
export async function runStoreFleetRebuild(deps) {
|
|
56
|
+
// One loader for the pass: a release's bytes are read once, however many scripts run it.
|
|
57
|
+
const read = storedReleaseLoader({ admin: deps.admin, actor: deps.actor, bytes: deps.bytes });
|
|
58
|
+
const cache = new Map();
|
|
59
|
+
const loadRelease = (input) => {
|
|
60
|
+
const key = `${input.driver}/${input.sha256 ?? ''}`;
|
|
61
|
+
let hit = cache.get(key);
|
|
62
|
+
if (!hit)
|
|
63
|
+
cache.set(key, (hit = read(input)));
|
|
64
|
+
return hit;
|
|
65
|
+
};
|
|
66
|
+
let budget = deps.budget;
|
|
67
|
+
const passes = [];
|
|
68
|
+
for (const registration of deps.drivers) {
|
|
69
|
+
// One driver's failure (its directory read, its lease write) never stops the others.
|
|
70
|
+
const pass = await rebuildDriver(deps, registration, loadRelease, budget).catch((e) => ({ driver: registration.driver, outcome: 'error', walked: [], uploaded: [], error: message(e) }));
|
|
71
|
+
budget -= pass.walked.length;
|
|
72
|
+
passes.push(pass);
|
|
73
|
+
}
|
|
74
|
+
return passes;
|
|
75
|
+
}
|
|
76
|
+
async function rebuildDriver(deps, registration, loadRelease, budget) {
|
|
77
|
+
const { admin, actor, fingerprint } = deps;
|
|
78
|
+
const driver = registration.driver;
|
|
79
|
+
const walked = [];
|
|
80
|
+
const uploaded = [];
|
|
81
|
+
const result = (outcome, rebuild) => ({ driver, outcome, walked, uploaded, ...(rebuild ? { rebuild } : {}) });
|
|
82
|
+
const stood = await admin.storeDriverRebuild(actor, driver);
|
|
83
|
+
const doneHere = stood?.fingerprint === fingerprint && stood.state === 'done';
|
|
84
|
+
const now = (deps.now ?? Date.now)();
|
|
85
|
+
const settleMs = deps.settleMs ?? STORE_REBUILD_SETTLE_MS;
|
|
86
|
+
const restart = doneHere && (deps.reverify === 'always' || now >= nextAutomaticWalk(stood, settleMs));
|
|
87
|
+
if (doneHere && !restart && deps.attestedBy === undefined)
|
|
88
|
+
return result('current', stood);
|
|
89
|
+
if (budget <= 0)
|
|
90
|
+
return result('paused', stood);
|
|
91
|
+
const holder = ulid();
|
|
92
|
+
const claimed = await admin.claimStoreDriverRebuild(actor, {
|
|
93
|
+
driver,
|
|
94
|
+
fingerprint,
|
|
95
|
+
holder,
|
|
96
|
+
ttlMs: STORE_REBUILD_LEASE_TTL_MS,
|
|
97
|
+
restart,
|
|
98
|
+
...(deps.attestedBy !== undefined ? { attestedBy: deps.attestedBy } : {}),
|
|
99
|
+
});
|
|
100
|
+
if (!claimed)
|
|
101
|
+
return result('busy', stood);
|
|
102
|
+
let rebuild = claimed;
|
|
103
|
+
let cursor = claimed.cursor;
|
|
104
|
+
const failures = new Map(claimed.failures.map((f) => [f.vertical, f.detail]));
|
|
105
|
+
const advance = async (done, release = false) => {
|
|
106
|
+
const list = [...failures].map(([vertical, detail]) => ({ vertical, detail }));
|
|
107
|
+
// A done walk that started after the settle window (or was attested) proves every script current.
|
|
108
|
+
const verified = done && settled(rebuild, settleMs);
|
|
109
|
+
rebuild = await admin.advanceStoreDriverRebuild(actor, { driver, fingerprint, holder, cursor, failures: list, done, verified, ttlMs: STORE_REBUILD_LEASE_TTL_MS, release });
|
|
110
|
+
};
|
|
111
|
+
// The lease is dropped once, however the walk ends; the end of a whole walk drops it itself.
|
|
112
|
+
let leaseDropped = false;
|
|
113
|
+
let held = false;
|
|
114
|
+
try {
|
|
115
|
+
held = await admin.holdStoreDriver(actor, { driver, holder, mode: 'shared', ttlMs: PUSH_HOLD_TTL_MS });
|
|
116
|
+
if (!held)
|
|
117
|
+
return result('held', rebuild);
|
|
118
|
+
const declared = await admin.storeDriverDeclarations(actor, driver);
|
|
119
|
+
const byVertical = new Map(declared.verticals.map((v) => [v.vertical, v.stores.map((s) => ({ binding: s.binding, driver }))]));
|
|
120
|
+
// A vertical whose stores cannot be named may still run a script of this driver. Its name is the
|
|
121
|
+
// vertical's and the driver's alone, so it is walked by name: rebuilt if it exists, and left
|
|
122
|
+
// alone if not (no script, nothing that accepts a key). Only a failure to do that is a failure.
|
|
123
|
+
for (const vertical of declared.unreadable) {
|
|
124
|
+
if (!byVertical.has(vertical))
|
|
125
|
+
byVertical.set(vertical, [{ binding: UNNAMED_BINDING, driver }]);
|
|
126
|
+
}
|
|
127
|
+
// A failure no longer to be had: the vertical declares the driver no more, and is readable.
|
|
128
|
+
for (const vertical of [...failures.keys()]) {
|
|
129
|
+
if (vertical !== SCOPE_STORE_CANARY && !byVertical.has(vertical))
|
|
130
|
+
failures.delete(vertical);
|
|
131
|
+
}
|
|
132
|
+
const ahead = aheadOf(cursor, [...byVertical.keys()].sort());
|
|
133
|
+
const walking = new Set(ahead);
|
|
134
|
+
const steps = [
|
|
135
|
+
...ahead.map((key) => ({ key, walk: true })),
|
|
136
|
+
// The retries: a failure behind the cursor that can be rebuilt now.
|
|
137
|
+
...[...failures.keys()]
|
|
138
|
+
.filter((key) => !walking.has(key) && (key === SCOPE_STORE_CANARY || byVertical.has(key)))
|
|
139
|
+
.map((key) => ({ key, walk: false })),
|
|
140
|
+
];
|
|
141
|
+
for (const step of steps) {
|
|
142
|
+
if (walked.length >= budget)
|
|
143
|
+
break;
|
|
144
|
+
if (!(await admin.holdStoreDriver(actor, { driver, holder, mode: 'shared', ttlMs: PUSH_HOLD_TTL_MS, renew: true }))) {
|
|
145
|
+
// The hold lapsed, and a rollout may hold the driver now: walk nothing more. The lease may
|
|
146
|
+
// have lapsed with it, and then another pass owns the row; what was walked is recorded.
|
|
147
|
+
return result('held', rebuild);
|
|
148
|
+
}
|
|
149
|
+
walked.push(step.key);
|
|
150
|
+
try {
|
|
151
|
+
const up = step.key === SCOPE_STORE_CANARY
|
|
152
|
+
? (await deps.ensureCanary({ driver, existingOnly: true, loadRelease })).uploaded
|
|
153
|
+
: await deps.ensure({ vertical: step.key, stores: byVertical.get(step.key), existingOnly: true, loadRelease }).then((r) => (r ? r.uploaded > 0 : true));
|
|
154
|
+
if (up)
|
|
155
|
+
uploaded.push(step.key);
|
|
156
|
+
failures.delete(step.key);
|
|
157
|
+
}
|
|
158
|
+
catch (e) {
|
|
159
|
+
failures.set(step.key, message(e));
|
|
160
|
+
await admin
|
|
161
|
+
.recordOpsFailure({
|
|
162
|
+
actor,
|
|
163
|
+
operation: 'store-rebuild',
|
|
164
|
+
stage: 'store-upload',
|
|
165
|
+
vertical: step.key === SCOPE_STORE_CANARY ? null : step.key,
|
|
166
|
+
status: e instanceof ControlPlaneError ? e.status : 502,
|
|
167
|
+
message: `store script rebuild of '${driver}' for ${step.key === SCOPE_STORE_CANARY ? 'its canary' : step.key}: ${message(e)}`,
|
|
168
|
+
})
|
|
169
|
+
.catch(() => undefined);
|
|
170
|
+
}
|
|
171
|
+
if (step.walk)
|
|
172
|
+
cursor = step.key === SCOPE_STORE_CANARY ? CANARY_WALKED : step.key;
|
|
173
|
+
await advance(false);
|
|
174
|
+
}
|
|
175
|
+
const left = steps.length - walked.length;
|
|
176
|
+
const done = left === 0 && failures.size === 0;
|
|
177
|
+
leaseDropped = true;
|
|
178
|
+
await advance(done, true);
|
|
179
|
+
return result(left > 0 ? 'paused' : done ? 'done' : 'failing', rebuild);
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
if (held)
|
|
183
|
+
await admin.releaseStoreDriverHold(actor, { driver, holder }).catch(() => undefined);
|
|
184
|
+
if (!leaseDropped)
|
|
185
|
+
await advance(false, true).catch(() => undefined);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/** The scripts ahead of a walk's cursor: the canary before any vertical, then each slug after it. */
|
|
189
|
+
function aheadOf(cursor, verticals) {
|
|
190
|
+
return [...(cursor === null ? [SCOPE_STORE_CANARY] : []), ...verticals.filter((v) => cursor === null || v > cursor)];
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* When the scheduled pass walks a done rebuild again: once its settle window has passed, for a walk
|
|
194
|
+
* that finished inside it; else a day after it finished.
|
|
195
|
+
*/
|
|
196
|
+
function nextAutomaticWalk(rebuild, settleMs) {
|
|
197
|
+
return settled(rebuild, settleMs) ? finishedMs(rebuild) + STORE_REBUILD_REVERIFY_MS : Date.parse(rebuild.fingerprintSince) + settleMs;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Whether every script of a driver is built from what the platform builds from now, and which may
|
|
201
|
+
* not be: while the rebuild is towards another fingerprint (or none ran yet), the canary and every
|
|
202
|
+
* vertical that declared the driver; while it runs, the ones ahead of its cursor and the ones that
|
|
203
|
+
* failed. A push or serve may have rebuilt some of them since, and the walk then finds them
|
|
204
|
+
* current, so `pending` may over-count, never under-count. A walk that is done but not settled (see
|
|
205
|
+
* {@link STORE_REBUILD_SETTLE_MS}) is not current: `settling` says when it is walked again. `nextWalk`
|
|
206
|
+
* is when the scheduled pass walks a done rebuild again. A walk under way at lists an earlier walk
|
|
207
|
+
* already proved is `current` and `reverifying` until a script it reaches fails.
|
|
208
|
+
*/
|
|
209
|
+
export function storeRebuildStatus(rebuild, fingerprint, declared, settleMs = STORE_REBUILD_SETTLE_MS) {
|
|
210
|
+
if (!rebuild || rebuild.fingerprint !== fingerprint)
|
|
211
|
+
return { current: false, pending: [SCOPE_STORE_CANARY, ...declared] };
|
|
212
|
+
if (rebuild.state === 'done') {
|
|
213
|
+
const nextWalk = new Date(nextAutomaticWalk(rebuild, settleMs)).toISOString();
|
|
214
|
+
return settled(rebuild, settleMs) ? { current: true, pending: [], nextWalk } : { current: false, pending: [], settling: nextWalk, nextWalk };
|
|
215
|
+
}
|
|
216
|
+
// A walk under way that re-checks a fleet a walk at these lists already proved current: still
|
|
217
|
+
// current, unless a script it reached is known to have failed.
|
|
218
|
+
if (rebuild.verifiedAt !== null && rebuild.failures.length === 0)
|
|
219
|
+
return { current: true, pending: [], reverifying: true };
|
|
220
|
+
const pending = new Set([...aheadOf(rebuild.cursor, declared), ...rebuild.failures.map((f) => f.vertical)]);
|
|
221
|
+
return { current: false, pending: [...pending] };
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=store-rebuild.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-rebuild.js","sourceRoot":"","sources":["../src/store-rebuild.ts"],"names":[],"mappings":"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"}
|
package/dist/store-releases.d.ts
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A store
|
|
2
|
+
* A store driver's releases: stored, canaried, rolled out and rolled back (D-63, #2300).
|
|
3
3
|
*
|
|
4
|
-
* The bytes live outside the directory, content-addressed under `<
|
|
5
|
-
* sha256 is `
|
|
4
|
+
* The bytes live outside the directory, content-addressed under `<driver>/<sha256>`, where the
|
|
5
|
+
* sha256 is `storeDriverReleaseDigest` of the bundle, computed here when it arrives and again by
|
|
6
6
|
* the ensurer before every upload of it, restore and rollback included. The directory holds who
|
|
7
7
|
* uploaded which release from which commit, every rollout, and the current good release
|
|
8
|
-
* (`store-
|
|
8
|
+
* (`store-driver-releases.ts` in the kernel).
|
|
9
9
|
*
|
|
10
|
-
* A rollout is one request across a fleet. It holds the
|
|
10
|
+
* A rollout is one request across a fleet. It holds the driver exclusively for its whole length,
|
|
11
11
|
* renewing the hold before every upload, so no push or serve rebuilds a script between the
|
|
12
12
|
* rollout's read and its upload, and two rollouts never interleave. It canaries the release on the
|
|
13
13
|
* platform's own object first, and no vertical's script moves unless every reserved operation
|
|
14
|
-
* answered there. Then it moves each vertical that ever declared the
|
|
15
|
-
* {@link ROLLOUT_VERTICALS_PER_REQUEST} uploads
|
|
16
|
-
* `paused`, and posting the same rollout (or
|
|
17
|
-
*
|
|
18
|
-
*
|
|
14
|
+
* answered there. Then it moves each vertical that ever declared the driver, at most
|
|
15
|
+
* {@link ROLLOUT_VERTICALS_PER_REQUEST} uploads and {@link ROLLOUT_WALKS_PER_REQUEST} verticals
|
|
16
|
+
* walked per request. A bigger fleet ends the request `paused`, and posting the same rollout (or
|
|
17
|
+
* rollback) again continues it from the attempt's walk ledger (#2312), so a fleet of any size
|
|
18
|
+
* converges, a rollback included. A request that stops on a failure ends `failed` or `diverged`.
|
|
19
19
|
*/
|
|
20
|
-
import { type PlatformActorId, type ReservedStoreOperation, type ScopeStoreNeed, type
|
|
21
|
-
import { type HostAdmin, type
|
|
22
|
-
import type { ScopeStoreEnsurerOptions,
|
|
23
|
-
/** Where a release's bytes are kept: an object store keyed by
|
|
20
|
+
import { type PlatformActorId, type ReservedStoreOperation, type ScopeStoreNeed, type StoreDriverRegistration } from '@substrat-run/contracts';
|
|
21
|
+
import { type HostAdmin, type StoreDriverRolloutAction, type StoreDriverRolloutRecord } from '@substrat-run/kernel';
|
|
22
|
+
import type { ScopeStoreEnsurerOptions, StoreDriverReleaseArtifact } from './store-script.js';
|
|
23
|
+
/** Where a release's bytes are kept: an object store keyed by driver and sha256. */
|
|
24
24
|
export interface StoreReleaseBytes {
|
|
25
25
|
get(key: string): Promise<Uint8Array | undefined>;
|
|
26
26
|
put(key: string, bytes: Uint8Array): Promise<void>;
|
|
27
27
|
}
|
|
28
28
|
/** The key a release's bytes are stored under. */
|
|
29
|
-
export declare const storeReleaseKey: (
|
|
29
|
+
export declare const storeReleaseKey: (driver: string, sha256: string) => string;
|
|
30
30
|
/** How long a rollout's exclusive hold lives between renewals. */
|
|
31
31
|
export declare const ROLLOUT_HOLD_TTL_MS: number;
|
|
32
32
|
/**
|
|
33
|
-
* How long a push's or a serve's shared hold lives. It is renewed before each
|
|
34
|
-
*
|
|
35
|
-
* rollout could take the
|
|
33
|
+
* How long a push's or a serve's shared hold lives. It is renewed before each driver's upload; one
|
|
34
|
+
* driver's upload (a settings read and at most one upload per script) must fit inside it, or a
|
|
35
|
+
* rollout could take the driver before that upload lands. The same lease as a rollout's.
|
|
36
36
|
*/
|
|
37
37
|
export declare const PUSH_HOLD_TTL_MS: number;
|
|
38
38
|
/**
|
|
@@ -42,32 +42,33 @@ export declare const PUSH_HOLD_TTL_MS: number;
|
|
|
42
42
|
*/
|
|
43
43
|
export declare const ROLLOUT_VERTICALS_PER_REQUEST = 100;
|
|
44
44
|
/**
|
|
45
|
-
* The
|
|
46
|
-
* when it is already at the release, so a
|
|
47
|
-
*
|
|
48
|
-
*
|
|
45
|
+
* The verticals one rollout request walks. Every one costs a settings read and a hold renewal even
|
|
46
|
+
* when it is already at the release, so a request that reaches this many ends `paused` and the
|
|
47
|
+
* next continues from the walk ledger (#2312). It also bounds what a failure returns: an attempt
|
|
48
|
+
* that reached more ends `diverged` without returning any, and a rollback, paged the same way,
|
|
49
|
+
* converges them.
|
|
49
50
|
*/
|
|
50
|
-
export declare const
|
|
51
|
+
export declare const ROLLOUT_WALKS_PER_REQUEST = 300;
|
|
51
52
|
type LoadRelease = ScopeStoreEnsurerOptions['loadRelease'];
|
|
52
53
|
/**
|
|
53
54
|
* A release bundle as uploaded or as stored, decoded and judged: the upload body's shape, the
|
|
54
|
-
* decoded size cap, and the Python
|
|
55
|
+
* decoded size cap, and the Python driver's module rule. Refusals are 422 (413 for the size).
|
|
55
56
|
*/
|
|
56
|
-
export declare function
|
|
57
|
+
export declare function decodeStoreDriverRelease(raw: unknown): Omit<StoreDriverReleaseArtifact, 'sha256'>;
|
|
57
58
|
/**
|
|
58
59
|
* Store a release's bytes and record them (D-63: bytes may be published before the pin lands).
|
|
59
60
|
* The bytes go first, so a recorded release always has bytes; a retry of the same bundle writes
|
|
60
61
|
* the same key and records nothing new.
|
|
61
62
|
*/
|
|
62
|
-
export declare function
|
|
63
|
+
export declare function storeDriverRelease(input: {
|
|
63
64
|
admin: HostAdmin;
|
|
64
65
|
actor: PlatformActorId;
|
|
65
66
|
bytes: StoreReleaseBytes;
|
|
66
|
-
|
|
67
|
+
driver: string;
|
|
67
68
|
body: unknown;
|
|
68
|
-
}): Promise<import("@substrat-run/kernel").
|
|
69
|
+
}): Promise<import("@substrat-run/kernel").StoreDriverReleaseRecord>;
|
|
69
70
|
/**
|
|
70
|
-
* The ensurer's loader over the stored bytes: a named release, or the
|
|
71
|
+
* The ensurer's loader over the stored bytes: a named release, or the driver's current good one.
|
|
71
72
|
* Each answer carries the sha256 it was read as, which the ensurer holds the bytes to.
|
|
72
73
|
*/
|
|
73
74
|
export declare function storedReleaseLoader(input: {
|
|
@@ -97,14 +98,14 @@ export declare function canaryStoreRelease(input: {
|
|
|
97
98
|
scriptName: string;
|
|
98
99
|
binding?: string;
|
|
99
100
|
}): Promise<void>;
|
|
100
|
-
export interface
|
|
101
|
+
export interface StoreDriverRolloutDeps {
|
|
101
102
|
admin: HostAdmin;
|
|
102
103
|
actor: PlatformActorId;
|
|
103
|
-
registration:
|
|
104
|
+
registration: StoreDriverRegistration;
|
|
104
105
|
sha256: string;
|
|
105
|
-
action:
|
|
106
|
+
action: StoreDriverRolloutAction;
|
|
106
107
|
/**
|
|
107
|
-
* Move one vertical's scripts of the
|
|
108
|
+
* Move one vertical's scripts of the driver to `to` (the push's ensurer, with `to`). Answers
|
|
108
109
|
* whether anything was uploaded: false for a script already there, built the same way.
|
|
109
110
|
*/
|
|
110
111
|
ensure: (input: {
|
|
@@ -112,36 +113,46 @@ export interface StoreKindRolloutDeps {
|
|
|
112
113
|
stores: readonly ScopeStoreNeed[];
|
|
113
114
|
to: string;
|
|
114
115
|
}) => Promise<boolean>;
|
|
115
|
-
/** Put `to` in the
|
|
116
|
+
/** Put `to` in the driver's canary script; answers its name. */
|
|
116
117
|
ensureCanary: (to: string) => Promise<{
|
|
117
118
|
scriptName: string;
|
|
118
119
|
}>;
|
|
119
120
|
callCanary: CanaryCall;
|
|
120
121
|
/** For a test: a smaller batch than {@link ROLLOUT_VERTICALS_PER_REQUEST}. */
|
|
121
122
|
perRequest?: number;
|
|
123
|
+
/** For a test: fewer verticals walked per request than {@link ROLLOUT_WALKS_PER_REQUEST}. */
|
|
124
|
+
perRequestWalks?: number;
|
|
122
125
|
}
|
|
123
|
-
export interface
|
|
124
|
-
rollout:
|
|
126
|
+
export interface StoreDriverRolloutResult {
|
|
127
|
+
rollout: StoreDriverRolloutRecord;
|
|
125
128
|
/** The verticals whose scripts this request uploaded. */
|
|
126
129
|
moved: string[];
|
|
127
130
|
/** False when verticals remain: post the same rollout again. */
|
|
128
131
|
complete: boolean;
|
|
132
|
+
/** The verticals not walked yet; 0 once complete. */
|
|
133
|
+
remaining: number;
|
|
129
134
|
}
|
|
130
135
|
/**
|
|
131
|
-
* Move every script of a
|
|
132
|
-
* vertical. A failure after a vertical moved returns every vertical
|
|
133
|
-
* the rollout started from, rehashing those bytes as it uploads them, and ends `failed`.
|
|
134
|
-
* `diverged` instead, naming what is where, when there is nothing to return to (a
|
|
135
|
-
* rollout), when returning would lower the stored schema,
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* ends.
|
|
136
|
+
* Move every script of a driver to a stored, pinned release (D-63): hold, canary, then each
|
|
137
|
+
* vertical. A failure after a vertical moved returns every vertical the attempt reached to the
|
|
138
|
+
* release the rollout started from, rehashing those bytes as it uploads them, and ends `failed`.
|
|
139
|
+
* It ends `diverged` instead, naming what is where, when there is nothing to return to (a driver's
|
|
140
|
+
* first rollout), when returning would lower the stored schema, when the attempt reached more
|
|
141
|
+
* verticals than one request returns, or when a return fails: the next rollout or rollback
|
|
142
|
+
* converges every script. The hold is renewed before every upload, the returns included, and a
|
|
143
|
+
* hold that cannot be renewed stops everything at once: another holder may be moving the same
|
|
144
|
+
* scripts, so nothing is returned either. The hold is released however it ends.
|
|
140
145
|
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
146
|
+
* A fleet bigger than one request is paged (#2312). Each request walks at most
|
|
147
|
+
* {@link ROLLOUT_WALKS_PER_REQUEST} verticals and uploads at most `perRequest` scripts; one that runs out
|
|
148
|
+
* ends `paused`, and its end records what it walked in the attempt's ledger. Posting the same
|
|
149
|
+
* rollout (or rollback) again continues the attempt and walks only declarations the ledger does
|
|
150
|
+
* not hold, in (vertical, binding) order: a vertical declared between two requests, wherever it
|
|
151
|
+
* sorts, is walked by the next one, and one walked is never walked again. A request ends `good`
|
|
152
|
+
* only when the pending list it read under its exclusive hold was the whole of it and it walked
|
|
153
|
+
* every vertical on it: no push can create a script while the hold is held, so nothing declared
|
|
154
|
+
* can be left on another release.
|
|
144
155
|
*/
|
|
145
|
-
export declare function
|
|
156
|
+
export declare function runStoreDriverRollout(deps: StoreDriverRolloutDeps): Promise<StoreDriverRolloutResult>;
|
|
146
157
|
export {};
|
|
147
158
|
//# sourceMappingURL=store-releases.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-releases.d.ts","sourceRoot":"","sources":["../src/store-releases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,
|
|
1
|
+
{"version":3,"file":"store-releases.d.ts","sourceRoot":"","sources":["../src/store-releases.ts"],"names":[],"mappings":"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"}
|