@molecule/api-deploy-rollout 0.0.0-stage → 1.1.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.
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Accessors for the bonded deploy-rollout provider.
3
+ *
4
+ * A provider bond (e.g. `@molecule/api-deploy-rollout-default`) calls
5
+ * `setProvider()` during application startup. Application code uses the
6
+ * convenience accessors (`runRollout`, `runInPlaceRollout`), which delegate to the
7
+ * bonded provider, so the hosting-specific algorithm is a wiring decision rather
8
+ * than an import.
9
+ *
10
+ * @module
11
+ */
12
+ import { bond, isBonded, require as bondRequire } from '@molecule/api-bond';
13
+ const BOND_TYPE = 'deploy-rollout';
14
+ /**
15
+ * Registers a deploy-rollout provider as the active singleton. Called by a bond
16
+ * package during application startup.
17
+ *
18
+ * @param provider - The provider implementation to bond.
19
+ */
20
+ export const setProvider = (provider) => {
21
+ bond(BOND_TYPE, provider);
22
+ };
23
+ /**
24
+ * Retrieves the bonded deploy-rollout provider, throwing if none is wired.
25
+ *
26
+ * @returns The bonded provider.
27
+ * @throws {Error} If no deploy-rollout provider has been bonded.
28
+ */
29
+ export const getProvider = () => {
30
+ try {
31
+ return bondRequire(BOND_TYPE);
32
+ }
33
+ catch (error) {
34
+ throw new Error('No deploy-rollout provider set. Bond one (e.g. @molecule/api-deploy-rollout-default) at startup.', { cause: error });
35
+ }
36
+ };
37
+ /**
38
+ * Checks whether a deploy-rollout provider is currently bonded.
39
+ *
40
+ * @returns `true` if a provider is bonded.
41
+ */
42
+ export const hasProvider = () => {
43
+ return isBonded(BOND_TYPE);
44
+ };
45
+ /**
46
+ * Runs a grow-then-shrink rollout through the bonded provider.
47
+ *
48
+ * @param options - The set to build, the old set, and the instance provider.
49
+ * @returns What the rollout did.
50
+ */
51
+ export const runRollout = (options) => {
52
+ return getProvider().run(options);
53
+ };
54
+ /**
55
+ * Runs an in-place rollout (the same instances changed one at a time) through the
56
+ * bonded provider.
57
+ *
58
+ * @param options - The instances to roll and the provider or callbacks.
59
+ * @returns What the rollout did.
60
+ */
61
+ export const runInPlaceRollout = (options) => {
62
+ return getProvider().runInPlace(options);
63
+ };
64
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAW3E,MAAM,SAAS,GAAG,gBAAgB,CAAA;AAElC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAA+B,EAAQ,EAAE;IACnE,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAA0B,EAAE;IACrD,IAAI,CAAC;QACH,OAAO,WAAW,CAAwB,SAAS,CAAC,CAAA;IACtD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,kGAAkG,EAClG,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAA;IACH,CAAC;AACH,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAY,EAAE;IACvC,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAA;AAC5B,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,OAA0B,EACE,EAAE;IAC9B,OAAO,WAAW,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;AACnC,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,OAAiC,EACE,EAAE;IACrC,OAAO,WAAW,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;AAC1C,CAAC,CAAA"}
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Type definitions for the deploy-rollout core interface.
3
+ *
4
+ * A rollout replaces the running instances of a deployment with new ones without
5
+ * taking the deployment down. Two topologies exist and both are first-class here:
6
+ *
7
+ * - **grow-then-shrink** — new instances are created beside the current set, each
8
+ * gated ready and joined to the routable set; then the old instances leave,
9
+ * drain and are destroyed one at a time. This is how a deployment changes its
10
+ * instance count and how a stateless app is redeployed with no dropped request.
11
+ * - **in-place** — the same instances are changed (restarted onto a new build)
12
+ * one at a time, with a restore path for every instance already changed. This is
13
+ * the only topology an instance provider without a "create a replacement" call
14
+ * supports (a Fly Machine patch, for example).
15
+ *
16
+ * The types here describe both, plus the policy that bounds either one. The
17
+ * algorithm lives in a bond (`@molecule/api-deploy-rollout-default`); this
18
+ * package carries no implementation.
19
+ *
20
+ * @module
21
+ */
22
+ /**
23
+ * One instance a rollout can act on.
24
+ *
25
+ * `id` is the provider's stable handle. `upstreamUrl` is the routable address the
26
+ * deployment's edge dials, when the provider has one — a rollout that only
27
+ * restarts instances in place does not need it.
28
+ */
29
+ export interface RolloutInstance {
30
+ /** Provider instance id. */
31
+ id: string;
32
+ /** The routable upstream URL, when the provider exposes one. */
33
+ upstreamUrl?: string;
34
+ }
35
+ /**
36
+ * What a grow-then-shrink rollout needs from whatever hosts the instances.
37
+ *
38
+ * The caller implements this over its hosting provider; the `-sandbox` bond does it
39
+ * over `@molecule/api-code-sandbox`, and tests drive it with a fake that records the
40
+ * order and can fail any step.
41
+ */
42
+ export interface InstanceProvider<I extends RolloutInstance = RolloutInstance> {
43
+ /** A human-readable provider name, for progress lines. */
44
+ readonly name?: string;
45
+ /**
46
+ * Every instance the deployment currently owns, when the provider can enumerate
47
+ * them. Used to resume an interrupted rollout idempotently: an instance already
48
+ * ready and joined is not created twice.
49
+ */
50
+ list?(): Promise<I[]>;
51
+ /**
52
+ * Create the instance at `index` (0-based, above any primary the caller created
53
+ * itself). It must not be routable until {@link InstanceProvider.join}.
54
+ *
55
+ * @param index - Which instance this is.
56
+ * @returns The created instance.
57
+ */
58
+ create(index: number): Promise<I>;
59
+ /**
60
+ * Resolve once the instance may take traffic.
61
+ *
62
+ * @param instance - The instance to gate.
63
+ * @param timeoutMs - The policy's readiness budget, for providers whose probe
64
+ * accepts one.
65
+ * @returns `false` when it never became ready (the rollout aborts).
66
+ */
67
+ waitReady(instance: I, timeoutMs?: number): Promise<boolean>;
68
+ /**
69
+ * A single, fast readiness probe, for the soak window. Optional: a caller that
70
+ * sets `soakMs` must provide it, because a blocking readiness wait cannot tell a
71
+ * warm instance from a recovering one.
72
+ *
73
+ * @param instance - The instance to probe.
74
+ * @returns Whether it is serving right now.
75
+ */
76
+ isServing?(instance: I): Promise<boolean>;
77
+ /**
78
+ * Add the instance to the routable set, so the edge may send it new requests.
79
+ *
80
+ * @param instance - A ready instance.
81
+ */
82
+ join(instance: I): Promise<void>;
83
+ /**
84
+ * Remove the instance from the routable set, so no NEW request is routed to it.
85
+ * Requests already in flight are untouched.
86
+ *
87
+ * @param instance - The instance being retired.
88
+ */
89
+ leave(instance: I): Promise<void>;
90
+ /**
91
+ * Tell the instance to drain: finish in-flight work and stop accepting new
92
+ * connections. Resolve when it may be destroyed, and never later than `drainMs`.
93
+ *
94
+ * @param instance - The retired instance.
95
+ * @param drainMs - The bounded wait.
96
+ */
97
+ drain(instance: I, drainMs: number): Promise<void>;
98
+ /**
99
+ * Destroy the instance, releasing whatever it costs.
100
+ *
101
+ * @param instance - The instance to remove.
102
+ */
103
+ destroy(instance: I): Promise<void>;
104
+ }
105
+ /**
106
+ * What an in-place rollout needs from whatever hosts the instances.
107
+ *
108
+ * Every instance keeps its identity; `replace` changes it to the new build and
109
+ * `restore` puts it back on the old one. The caller supplies {@link list} so a
110
+ * resumed rollout can see what is already there.
111
+ */
112
+ export interface InPlaceInstanceProvider<I extends RolloutInstance = RolloutInstance> {
113
+ /** A human-readable provider name, for progress lines. */
114
+ readonly name?: string;
115
+ /**
116
+ * Every instance the rollout may act on, in roll order.
117
+ *
118
+ * @returns The instances.
119
+ */
120
+ list(): Promise<I[]>;
121
+ /**
122
+ * Whether the instance is serving requests right now.
123
+ *
124
+ * @param instance - The instance to probe.
125
+ * @returns `true` while it answers its readiness probe.
126
+ */
127
+ isServing(instance: I): Promise<boolean>;
128
+ /**
129
+ * Change the instance to the new build and leave it serving.
130
+ *
131
+ * @param instance - The instance to change.
132
+ */
133
+ replace(instance: I): Promise<void>;
134
+ /**
135
+ * Put the instance back on the old build. Called only for instances this run
136
+ * already replaced.
137
+ *
138
+ * @param instance - The instance to restore.
139
+ */
140
+ restore(instance: I): Promise<void>;
141
+ }
142
+ /**
143
+ * How a rollout bounds itself.
144
+ *
145
+ * Every field is optional on the caller's side; the bond fills in the defaults
146
+ * documented here.
147
+ */
148
+ export interface RolloutPolicy {
149
+ /**
150
+ * How many instances the NEW set holds, for a grow-then-shrink rollout. The
151
+ * caller's own primary instance is not created here, so the bond creates
152
+ * `replicas - 1`. Defaults to `current.length` (a like-for-like replacement).
153
+ */
154
+ replicas?: number;
155
+ /**
156
+ * The most instances that may be unavailable at once. When set, the bond derives
157
+ * `minHealthy = max(1, instances - maxUnavailable)` and refuses a step that would
158
+ * go below it. Default: `minHealthy` is 1 — never blank the deployment.
159
+ */
160
+ maxUnavailable?: number;
161
+ /**
162
+ * An absolute floor on healthy instances. Overrides the value derived from
163
+ * {@link RolloutPolicy.maxUnavailable}. Defaults to 1.
164
+ */
165
+ minHealthy?: number;
166
+ /**
167
+ * How long a changed instance must keep answering without a gap before the next
168
+ * step starts. Passing one probe is not proof of a warm instance; a gap restarts
169
+ * the window. Defaults to 0 (no soak).
170
+ */
171
+ soakMs?: number;
172
+ /** Probe cadence during the soak. Defaults to 2000 ms. */
173
+ soakProbeMs?: number;
174
+ /**
175
+ * How long the soak may keep retrying before the rollout aborts. Defaults to
176
+ * `soakMs + 60 s`.
177
+ */
178
+ soakGraceMs?: number;
179
+ /** How long a retired instance may take to drain. Defaults to 25 s. */
180
+ drainMs?: number;
181
+ /** The readiness budget handed to `waitReady`. Defaults to 120 s. */
182
+ readinessTimeoutMs?: number;
183
+ /**
184
+ * What an abort does to instances this run already changed: `reverse` restores
185
+ * them newest first (the default), `none` leaves them as they are.
186
+ */
187
+ rollback?: 'reverse' | 'none';
188
+ /**
189
+ * Whether a rollout reconciles against the provider's current instances instead
190
+ * of starting from the caller's list. Defaults to true; a provider without
191
+ * `list()` falls back to the caller's list.
192
+ */
193
+ resume?: boolean;
194
+ }
195
+ /** The step of a rollout that produced a result or a failure. */
196
+ export type RolloutStep = 'create' | 'ready' | 'join' | 'leave' | 'drain' | 'destroy' | 'replace' | 'restore' | 'capacity' | 'cancelled';
197
+ /** A step that failed but did not stop the rollout (a retirement or rollback step). */
198
+ export interface RolloutFailure<I extends RolloutInstance = RolloutInstance> {
199
+ /** The instance the step addressed. */
200
+ instance: I;
201
+ /** The step that failed. */
202
+ step: RolloutStep;
203
+ /** Whatever was thrown, for the caller's log. */
204
+ error: unknown;
205
+ }
206
+ /** What a completed or aborted rollout did. */
207
+ export interface RolloutOutcome<I extends RolloutInstance = RolloutInstance> {
208
+ /** `completed` when the target set is serving; `aborted` otherwise. */
209
+ status: 'completed' | 'aborted';
210
+ /** Every instance this run created and joined, in creation order. */
211
+ created: I[];
212
+ /** Every new instance that is healthy and joined. */
213
+ upstreams: I[];
214
+ /** Old instances this run removed from the set and destroyed. */
215
+ retired: I[];
216
+ /** Steps that failed but did not stop the rollout. */
217
+ failures: RolloutFailure<I>[];
218
+ /** Instances this run restored, newest first (an in-place abort). */
219
+ rolledBack: string[];
220
+ /** Restores that themselves failed. */
221
+ rollbackFailures: RolloutFailure<I>[];
222
+ }
223
+ /** What an in-place rollout did. */
224
+ export interface InPlaceRolloutOutcome<I extends RolloutInstance = RolloutInstance> {
225
+ /** The instances changed successfully, in roll order. */
226
+ applied: string[];
227
+ /** Every instance that passed its gate. */
228
+ instances: I[];
229
+ }
230
+ /** What {@link InstanceProvider} needs for one grow-then-shrink rollout. */
231
+ export interface RolloutOptions<I extends RolloutInstance = RolloutInstance> {
232
+ /** The instance provider. */
233
+ provider: InstanceProvider<I>;
234
+ /** The instances serving right now (empty on a first deploy). */
235
+ current?: readonly I[];
236
+ /** Rollout bounds; the bond fills the defaults. */
237
+ policy?: RolloutPolicy;
238
+ /** Optional progress sink — plain sentences. */
239
+ log?: (line: string) => Promise<void> | void;
240
+ /** Consulted between steps; `true` aborts and keeps the old set serving. */
241
+ isCancelled?: () => Promise<boolean> | boolean;
242
+ /**
243
+ * Set when the caller has already created and joined ONE instance of the new
244
+ * set (the primary), outside this rollout. It counts toward healthy capacity.
245
+ */
246
+ primaryServing?: boolean;
247
+ /** Injectable clock, for tests. Defaults to `Date.now`. */
248
+ now?: () => number;
249
+ /** Injectable sleep, for tests. Defaults to a real timer. */
250
+ sleep?: (ms: number) => Promise<void>;
251
+ }
252
+ /**
253
+ * The contract every deploy-rollout bond implements.
254
+ *
255
+ * The two methods are the two real deployment topologies; a bond that supports
256
+ * only one rejects the other with a clear error rather than silently doing
257
+ * nothing.
258
+ */
259
+ export interface DeployRolloutProvider {
260
+ /** A human-readable provider name, for diagnostics. */
261
+ readonly name: string;
262
+ /**
263
+ * Run a grow-then-shrink replacement of a deployment's instances.
264
+ *
265
+ * @param options - The set to build, the old set, and the instance provider.
266
+ * @returns What the rollout did.
267
+ */
268
+ run<I extends RolloutInstance>(options: RolloutOptions<I>): Promise<RolloutOutcome<I>>;
269
+ /**
270
+ * Run an in-place replacement (the same instances changed one at a time).
271
+ *
272
+ * @param options - The instances to roll and the provider or callbacks.
273
+ * @returns What the rollout did.
274
+ */
275
+ runInPlace<I extends RolloutInstance>(options: InPlaceRolloutOptions<I>): Promise<InPlaceRolloutOutcome<I>>;
276
+ }
277
+ /** What an in-place rollout needs. */
278
+ export interface InPlaceRolloutOptions<I extends RolloutInstance = RolloutInstance> {
279
+ /**
280
+ * The instances to roll. When absent, the provider's own list is used.
281
+ */
282
+ machines?: readonly I[];
283
+ /**
284
+ * A provider that owns the operations. Alternatively pass `apply`/`rollback`/
285
+ * `probeServing` directly; the provider is a convenience for callers that
286
+ * already model their hosting this way.
287
+ */
288
+ provider?: InPlaceInstanceProvider<I>;
289
+ /** Change one instance and leave it serving on the NEW build. */
290
+ apply?: (instance: I) => Promise<void>;
291
+ /** Put one instance back on the OLD build. */
292
+ rollback?: (instance: I) => Promise<void>;
293
+ /** Whether an instance is serving right now. */
294
+ probeServing?: (instanceId: string) => Promise<boolean>;
295
+ /** Rollout bounds; the bond fills the defaults. */
296
+ policy?: RolloutPolicy;
297
+ /** Pause between instances. Defaults to 0. */
298
+ betweenMs?: number;
299
+ /** Optional progress sink — plain sentences. */
300
+ log?: (line: string) => Promise<void> | void;
301
+ /** Consulted before each instance; `true` aborts and rolls back. */
302
+ isCancelled?: () => Promise<boolean> | boolean;
303
+ /** Injectable clock, for tests. Defaults to `Date.now`. */
304
+ now?: () => number;
305
+ /** Injectable sleep, for tests. Defaults to a real timer. */
306
+ sleep?: (ms: number) => Promise<void>;
307
+ }
308
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Type definitions for the deploy-rollout core interface.
3
+ *
4
+ * A rollout replaces the running instances of a deployment with new ones without
5
+ * taking the deployment down. Two topologies exist and both are first-class here:
6
+ *
7
+ * - **grow-then-shrink** — new instances are created beside the current set, each
8
+ * gated ready and joined to the routable set; then the old instances leave,
9
+ * drain and are destroyed one at a time. This is how a deployment changes its
10
+ * instance count and how a stateless app is redeployed with no dropped request.
11
+ * - **in-place** — the same instances are changed (restarted onto a new build)
12
+ * one at a time, with a restore path for every instance already changed. This is
13
+ * the only topology an instance provider without a "create a replacement" call
14
+ * supports (a Fly Machine patch, for example).
15
+ *
16
+ * The types here describe both, plus the policy that bounds either one. The
17
+ * algorithm lives in a bond (`@molecule/api-deploy-rollout-default`); this
18
+ * package carries no implementation.
19
+ *
20
+ * @module
21
+ */
22
+ export {};
23
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG"}
package/package.json CHANGED
@@ -1,6 +1,57 @@
1
1
  {
2
2
  "name": "@molecule/api-deploy-rollout",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.1.0",
4
+ "description": "Deploy-rollout core interface for molecule.dev: replace a deployment's running instances without downtime, grow-then-shrink or in place, with a capacity floor, soak, reverse rollback and idempotent resume.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "dev": "tsc --watch",
21
+ "test": "vitest run",
22
+ "test:watch": "vitest",
23
+ "test:coverage": "vitest run --coverage"
24
+ },
25
+ "keywords": [
26
+ "molecule",
27
+ "deploy",
28
+ "rollout",
29
+ "rolling deploy",
30
+ "zero downtime",
31
+ "replicas"
32
+ ],
33
+ "author": "Molecule Dev, Inc. (https://molecule.dev)",
34
+ "license": "Apache-2.0",
35
+ "engines": {
36
+ "node": ">=20"
37
+ },
38
+ "peerDependencies": {
39
+ "@molecule/api-bond": "^1.0.1"
40
+ },
41
+ "devDependencies": {
42
+ "@molecule/api-bond": "1.0.2",
43
+ "@types/node": "26.1.2",
44
+ "typescript": "6.0.3",
45
+ "vitest": "4.1.11"
46
+ },
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "https://github.com/molecule-dev/molecule.git",
50
+ "directory": "packages/api/core/deploy-rollout"
51
+ },
52
+ "homepage": "https://www.molecule.dev/packages/api-deploy-rollout",
53
+ "bugs": "https://github.com/molecule-dev/molecule/issues",
54
+ "publishConfig": {
55
+ "access": "public"
56
+ }
57
+ }