@substrat-run/control-plane-api 0.147.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/api.d.ts +67 -4
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +1068 -418
- package/dist/api.js.map +1 -1
- package/dist/attachment-sweep.d.ts +29 -0
- package/dist/attachment-sweep.d.ts.map +1 -0
- package/dist/attachment-sweep.js +66 -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 +26 -11
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +33 -18
- package/dist/deploy.js.map +1 -1
- package/dist/errors.d.ts +19 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +18 -4
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +15 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/lake-gateway.d.ts +54 -0
- package/dist/lake-gateway.d.ts.map +1 -0
- package/dist/lake-gateway.js +158 -0
- package/dist/lake-gateway.js.map +1 -0
- 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 +65 -12
- package/dist/platform-scope-stores.d.ts.map +1 -1
- package/dist/platform-scope-stores.js +121 -20
- package/dist/platform-scope-stores.js.map +1 -1
- package/dist/r2-sql-engine.d.ts +50 -0
- package/dist/r2-sql-engine.d.ts.map +1 -0
- package/dist/r2-sql-engine.js +126 -0
- package/dist/r2-sql-engine.js.map +1 -0
- package/dist/scope-copy-cleanup.d.ts +13 -1
- package/dist/scope-copy-cleanup.d.ts.map +1 -1
- package/dist/scope-copy-cleanup.js +14 -3
- 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 +90 -0
- package/dist/store-entry.d.ts.map +1 -0
- package/dist/store-entry.generated.d.ts +60 -0
- package/dist/store-entry.generated.d.ts.map +1 -0
- package/dist/store-entry.generated.js +62 -0
- package/dist/store-entry.generated.js.map +1 -0
- package/dist/store-entry.js +178 -0
- package/dist/store-entry.js.map +1 -0
- 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 +158 -0
- package/dist/store-releases.d.ts.map +1 -0
- package/dist/store-releases.js +332 -0
- package/dist/store-releases.js.map +1 -0
- package/dist/store-script.d.ts +98 -0
- package/dist/store-script.d.ts.map +1 -0
- package/dist/store-script.js +188 -0
- package/dist/store-script.js.map +1 -0
- package/dist/vertical-client.d.ts +33 -2
- package/dist/vertical-client.d.ts.map +1 -1
- package/dist/vertical-client.js +58 -3
- package/dist/vertical-client.js.map +1 -1
- package/package.json +7 -7
|
@@ -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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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A store driver's releases: stored, canaried, rolled out and rolled back (D-63, #2300).
|
|
3
|
+
*
|
|
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
|
+
* the ensurer before every upload of it, restore and rollback included. The directory holds who
|
|
7
|
+
* uploaded which release from which commit, every rollout, and the current good release
|
|
8
|
+
* (`store-driver-releases.ts` in the kernel).
|
|
9
|
+
*
|
|
10
|
+
* A rollout is one request across a fleet. It holds the driver exclusively for its whole length,
|
|
11
|
+
* renewing the hold before every upload, so no push or serve rebuilds a script between the
|
|
12
|
+
* rollout's read and its upload, and two rollouts never interleave. It canaries the release on the
|
|
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 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
|
+
*/
|
|
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
|
+
export interface StoreReleaseBytes {
|
|
25
|
+
get(key: string): Promise<Uint8Array | undefined>;
|
|
26
|
+
put(key: string, bytes: Uint8Array): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
/** The key a release's bytes are stored under. */
|
|
29
|
+
export declare const storeReleaseKey: (driver: string, sha256: string) => string;
|
|
30
|
+
/** How long a rollout's exclusive hold lives between renewals. */
|
|
31
|
+
export declare const ROLLOUT_HOLD_TTL_MS: number;
|
|
32
|
+
/**
|
|
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
|
+
*/
|
|
37
|
+
export declare const PUSH_HOLD_TTL_MS: number;
|
|
38
|
+
/**
|
|
39
|
+
* The verticals one rollout request moves. Each costs a settings read and at most one upload,
|
|
40
|
+
* plus a hold renewal, so a request stays well inside a Worker invocation's subrequest budget.
|
|
41
|
+
* A fleet bigger than this is moved over several requests (the rollout answers `complete: false`).
|
|
42
|
+
*/
|
|
43
|
+
export declare const ROLLOUT_VERTICALS_PER_REQUEST = 100;
|
|
44
|
+
/**
|
|
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.
|
|
50
|
+
*/
|
|
51
|
+
export declare const ROLLOUT_WALKS_PER_REQUEST = 300;
|
|
52
|
+
type LoadRelease = ScopeStoreEnsurerOptions['loadRelease'];
|
|
53
|
+
/**
|
|
54
|
+
* A release bundle as uploaded or as stored, decoded and judged: the upload body's shape, the
|
|
55
|
+
* decoded size cap, and the Python driver's module rule. Refusals are 422 (413 for the size).
|
|
56
|
+
*/
|
|
57
|
+
export declare function decodeStoreDriverRelease(raw: unknown): Omit<StoreDriverReleaseArtifact, 'sha256'>;
|
|
58
|
+
/**
|
|
59
|
+
* Store a release's bytes and record them (D-63: bytes may be published before the pin lands).
|
|
60
|
+
* The bytes go first, so a recorded release always has bytes; a retry of the same bundle writes
|
|
61
|
+
* the same key and records nothing new.
|
|
62
|
+
*/
|
|
63
|
+
export declare function storeDriverRelease(input: {
|
|
64
|
+
admin: HostAdmin;
|
|
65
|
+
actor: PlatformActorId;
|
|
66
|
+
bytes: StoreReleaseBytes;
|
|
67
|
+
driver: string;
|
|
68
|
+
body: unknown;
|
|
69
|
+
}): Promise<import("@substrat-run/kernel").StoreDriverReleaseRecord>;
|
|
70
|
+
/**
|
|
71
|
+
* The ensurer's loader over the stored bytes: a named release, or the driver's current good one.
|
|
72
|
+
* Each answer carries the sha256 it was read as, which the ensurer holds the bytes to.
|
|
73
|
+
*/
|
|
74
|
+
export declare function storedReleaseLoader(input: {
|
|
75
|
+
admin: HostAdmin;
|
|
76
|
+
actor: PlatformActorId;
|
|
77
|
+
bytes: StoreReleaseBytes;
|
|
78
|
+
}): LoadRelease;
|
|
79
|
+
/** The reserved calls a canary makes, at the canary script. */
|
|
80
|
+
export type CanaryCall = (target: {
|
|
81
|
+
scriptName: string;
|
|
82
|
+
objectName: string;
|
|
83
|
+
}, operation: ReservedStoreOperation, input?: unknown) => Promise<unknown>;
|
|
84
|
+
/**
|
|
85
|
+
* A canary object's name. Each id comes from a mint of its own, so its 80 random bits are fresh
|
|
86
|
+
* from `crypto.getRandomValues`: the shared mint would make the second id the first plus one
|
|
87
|
+
* within a millisecond, and either id would then give the other away.
|
|
88
|
+
*/
|
|
89
|
+
export declare const canaryObjectName: (binding: string) => string;
|
|
90
|
+
/**
|
|
91
|
+
* Every reserved operation, on a fresh object of the platform's own (D-63): its tenant and scope
|
|
92
|
+
* ids are new ulids, from the runtime's CSPRNG, never in the directory, and its vertical segment
|
|
93
|
+
* is no vertical's. Each answer is parsed by the call and asserted here; the first that is not
|
|
94
|
+
* what an object holding no data answers fails the canary. The object is wiped at the end.
|
|
95
|
+
*/
|
|
96
|
+
export declare function canaryStoreRelease(input: {
|
|
97
|
+
call: CanaryCall;
|
|
98
|
+
scriptName: string;
|
|
99
|
+
binding?: string;
|
|
100
|
+
}): Promise<void>;
|
|
101
|
+
export interface StoreDriverRolloutDeps {
|
|
102
|
+
admin: HostAdmin;
|
|
103
|
+
actor: PlatformActorId;
|
|
104
|
+
registration: StoreDriverRegistration;
|
|
105
|
+
sha256: string;
|
|
106
|
+
action: StoreDriverRolloutAction;
|
|
107
|
+
/**
|
|
108
|
+
* Move one vertical's scripts of the driver to `to` (the push's ensurer, with `to`). Answers
|
|
109
|
+
* whether anything was uploaded: false for a script already there, built the same way.
|
|
110
|
+
*/
|
|
111
|
+
ensure: (input: {
|
|
112
|
+
vertical: string;
|
|
113
|
+
stores: readonly ScopeStoreNeed[];
|
|
114
|
+
to: string;
|
|
115
|
+
}) => Promise<boolean>;
|
|
116
|
+
/** Put `to` in the driver's canary script; answers its name. */
|
|
117
|
+
ensureCanary: (to: string) => Promise<{
|
|
118
|
+
scriptName: string;
|
|
119
|
+
}>;
|
|
120
|
+
callCanary: CanaryCall;
|
|
121
|
+
/** For a test: a smaller batch than {@link ROLLOUT_VERTICALS_PER_REQUEST}. */
|
|
122
|
+
perRequest?: number;
|
|
123
|
+
/** For a test: fewer verticals walked per request than {@link ROLLOUT_WALKS_PER_REQUEST}. */
|
|
124
|
+
perRequestWalks?: number;
|
|
125
|
+
}
|
|
126
|
+
export interface StoreDriverRolloutResult {
|
|
127
|
+
rollout: StoreDriverRolloutRecord;
|
|
128
|
+
/** The verticals whose scripts this request uploaded. */
|
|
129
|
+
moved: string[];
|
|
130
|
+
/** False when verticals remain: post the same rollout again. */
|
|
131
|
+
complete: boolean;
|
|
132
|
+
/** The verticals not walked yet; 0 once complete. */
|
|
133
|
+
remaining: number;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
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.
|
|
145
|
+
*
|
|
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.
|
|
155
|
+
*/
|
|
156
|
+
export declare function runStoreDriverRollout(deps: StoreDriverRolloutDeps): Promise<StoreDriverRolloutResult>;
|
|
157
|
+
export {};
|
|
158
|
+
//# sourceMappingURL=store-releases.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-releases.d.ts","sourceRoot":"","sources":["../src/store-releases.ts"],"names":[],"mappings":"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"}
|