@nimbus-sh/fabric 0.3.0 → 0.4.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/composition.d.ts +2 -2
- package/dist/composition.d.ts.map +1 -1
- package/dist/composition.js +1 -1
- package/dist/fenced-work.d.ts.map +1 -1
- package/dist/fenced-work.js +6 -0
- package/dist/turn-budget.d.ts +2 -2
- package/dist/turn-budget.d.ts.map +1 -1
- package/dist/turn-budget.js +9 -6
- package/package.json +3 -3
- package/src/composition.ts +2 -15
- package/src/fenced-work.ts +6 -0
- package/src/turn-budget.ts +10 -8
package/dist/composition.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export
|
|
2
|
-
export type
|
|
1
|
+
export * from '@nimbus-sh/platform/composition.js';
|
|
2
|
+
export type * from '@nimbus-sh/platform/composition.js';
|
|
3
3
|
//# sourceMappingURL=composition.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composition.d.ts","sourceRoot":"","sources":["../src/composition.ts"],"names":[],"mappings":"AACA,
|
|
1
|
+
{"version":3,"file":"composition.d.ts","sourceRoot":"","sources":["../src/composition.ts"],"names":[],"mappings":"AACA,cAAc,oCAAoC,CAAC;AACnD,mBAAmB,oCAAoC,CAAC"}
|
package/dist/composition.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Core and fabric share one holder without introducing a dependency cycle.
|
|
2
|
-
export
|
|
2
|
+
export * from '@nimbus-sh/platform/composition.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fenced-work.d.ts","sourceRoot":"","sources":["../src/fenced-work.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AAEzD,gFAAgF;AAChF,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAEzC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB;;4DAEwD;IACxD,KAAK,EAAE,UAAU,GAAG,SAAS,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACxE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,2DAA2D;AAC3D,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,gBAAgB;IACxD;;;;;;OAMG;IACH,cAAc,IAAI,MAAM,CAAC;IACzB;;;;;;;;OAQG;IACH,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3C;;;;;OAKG;IACH,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,mDAAmD;IACnD,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC;IAC5B,yEAAyE;IACzE,WAAW,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC;IAC9B,kCAAkC;IAClC,eAAe,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CACnD;AAED;;;;;;;GAOG;AACH,qBAAa,UAAU,CAAC,CAAC,SAAS,gBAAgB;IAc9C,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAdvB;;;;OAIG;IACH,OAAO,CAAC,cAAc,CAAqB;IAC3C;mEAC+D;IAC/D,OAAO,CAAC,MAAM,CAAuC;IACrD,gFAAgF;IAChF,OAAO,CAAC,SAAS,CAAS;gBAGP,OAAO,EAAE,iBAAiB,EAC1B,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IAG1C;;;;;;;;;;;;;;OAcG;IACG,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAUvC,8DAA8D;IAC9D,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB;;;;OAIG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzC;;;;;OAKG;IACG,UAAU,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAapE;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAIrC;;;;;;;OAOG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"fenced-work.d.ts","sourceRoot":"","sources":["../src/fenced-work.ts"],"names":[],"mappings":"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"}
|
package/dist/fenced-work.js
CHANGED
|
@@ -145,6 +145,11 @@ export class FencedWork {
|
|
|
145
145
|
let inflight = this.drives.get(key);
|
|
146
146
|
if (inflight === undefined) {
|
|
147
147
|
inflight = (async () => {
|
|
148
|
+
if (record.attempt >= FENCED_WORK_MAX_ATTEMPT) {
|
|
149
|
+
this.host.onAbandoned?.(record);
|
|
150
|
+
await this.supersede(key);
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
148
153
|
let failed = false;
|
|
149
154
|
try {
|
|
150
155
|
await this.host.redrive(record, record.attempt + 1);
|
|
@@ -235,6 +240,7 @@ export class FencedWork {
|
|
|
235
240
|
* a previous generation the terminal hook will never fire for.
|
|
236
241
|
*/
|
|
237
242
|
async supersede(key) {
|
|
243
|
+
this.journalledPids.delete(Number(key.slice(FENCED_WORK_KEY_PREFIX.length)));
|
|
238
244
|
await this.storage.delete(key);
|
|
239
245
|
await this.storage.sync();
|
|
240
246
|
}
|
package/dist/turn-budget.d.ts
CHANGED
|
@@ -114,7 +114,7 @@ export interface PacedWorkHost {
|
|
|
114
114
|
* reason. Without it the pump degrades to a same-context timer — see
|
|
115
115
|
* {@link PacedWork.nextTurn}.
|
|
116
116
|
*/
|
|
117
|
-
requestTurn?: () => void;
|
|
117
|
+
requestTurn?: (notBefore?: number) => void;
|
|
118
118
|
}
|
|
119
119
|
/**
|
|
120
120
|
* The granting side of {@link TurnScheduler}: parks suspended launches
|
|
@@ -149,7 +149,7 @@ export declare class PacedWork implements TurnScheduler {
|
|
|
149
149
|
* always performed, so a harness or a runtime without alarms loses the
|
|
150
150
|
* responsiveness but keeps the behaviour.
|
|
151
151
|
*/
|
|
152
|
-
nextTurn(chunkEnded: Promise<void
|
|
152
|
+
nextTurn(chunkEnded: Promise<void>, notBefore?: number): Promise<void>;
|
|
153
153
|
/**
|
|
154
154
|
* Run one chunk of every launch waiting for a turn.
|
|
155
155
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turn-budget.d.ts","sourceRoot":"","sources":["../src/turn-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAIH,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,UAAY,CAAC;AAE9C;;;;;;;;;GASG;AACH,qBAAa,UAAU;IAkBnB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAnB/B,qEAAqE;IACrE,MAAM,SAAK;IACX,iDAAiD;IACjD,KAAK,SAAK;IAEV,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,UAAU,CAA8D;IAEhF;;;;;;;OAOG;gBAEgB,SAAS,EAAE,aAAa,EACxB,aAAa,GAAE,MAA6B,EAC5C,WAAW,CAAC,GAAE,MAAM,IAAI,aAAA;IAG3C;;;;;;OAMG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAczC;;;;OAIG;IACH,MAAM,IAAI,IAAI;CAIf;AAED,mEAAmE;AACnE,wBAAgB,aAAa,CAAC,CAAC,GAAG,IAAI,KAAK;IAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;CAAE,CAI/G;AAED,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"turn-budget.d.ts","sourceRoot":"","sources":["../src/turn-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAIH,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,UAAY,CAAC;AAE9C;;;;;;;;;GASG;AACH,qBAAa,UAAU;IAkBnB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAnB/B,qEAAqE;IACrE,MAAM,SAAK;IACX,iDAAiD;IACjD,KAAK,SAAK;IAEV,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,UAAU,CAA8D;IAEhF;;;;;;;OAOG;gBAEgB,SAAS,EAAE,aAAa,EACxB,aAAa,GAAE,MAA6B,EAC5C,WAAW,CAAC,GAAE,MAAM,IAAI,aAAA;IAG3C;;;;;;OAMG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAczC;;;;OAIG;IACH,MAAM,IAAI,IAAI;CAIf;AAED,mEAAmE;AACnE,wBAAgB,aAAa,CAAC,CAAC,GAAG,IAAI,KAAK;IAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;CAAE,CAI/G;AAED,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED;;;GAGG;AACH,qBAAa,SAAU,YAAW,aAAa;IAkB3C,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAlBvB;;;;;;;;;OASG;IACH,OAAO,CAAC,OAAO,CAAmF;IAElG;;;OAGG;gBAEgB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,aAAa;IAGtC;;;;;;;;;OASG;IACH,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,SAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAWjE;;;;;;;OAOG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAe3B,0DAA0D;IAC1D,IAAI,UAAU,IAAI,OAAO,CAExB;CACF;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAMtD"}
|
package/dist/turn-budget.js
CHANGED
|
@@ -148,14 +148,14 @@ export class PacedWork {
|
|
|
148
148
|
* always performed, so a harness or a runtime without alarms loses the
|
|
149
149
|
* responsiveness but keeps the behaviour.
|
|
150
150
|
*/
|
|
151
|
-
nextTurn(chunkEnded) {
|
|
151
|
+
nextTurn(chunkEnded, notBefore = 0) {
|
|
152
152
|
return new Promise((resume) => {
|
|
153
|
-
this.waiters.push({ resume, chunkEnded });
|
|
153
|
+
this.waiters.push({ resume, chunkEnded, notBefore });
|
|
154
154
|
if (this.host.requestTurn) {
|
|
155
|
-
this.host.requestTurn();
|
|
155
|
+
this.host.requestTurn(notBefore);
|
|
156
156
|
return;
|
|
157
157
|
}
|
|
158
|
-
setTimeout(() => { void this.pump(); }, 0);
|
|
158
|
+
setTimeout(() => { void this.pump(); }, Math.max(0, notBefore - Date.now()));
|
|
159
159
|
});
|
|
160
160
|
}
|
|
161
161
|
/**
|
|
@@ -172,10 +172,13 @@ export class PacedWork {
|
|
|
172
172
|
// is what an alarm calls, and the first turn after a reset is the
|
|
173
173
|
// re-delivered alarm of a launch the reset interrupted.
|
|
174
174
|
await runColdStart(this.ctx);
|
|
175
|
-
const
|
|
175
|
+
const now = Date.now();
|
|
176
|
+
const waiting = this.waiters.filter((waiter) => waiter.notBefore <= now);
|
|
177
|
+
this.waiters = this.waiters.filter((waiter) => waiter.notBefore > now);
|
|
178
|
+
if (this.waiters.length > 0)
|
|
179
|
+
this.host.requestTurn?.(Math.min(...this.waiters.map((waiter) => waiter.notBefore)));
|
|
176
180
|
if (waiting.length === 0)
|
|
177
181
|
return;
|
|
178
|
-
this.waiters = [];
|
|
179
182
|
for (const waiter of waiting)
|
|
180
183
|
waiter.resume();
|
|
181
184
|
await Promise.all(waiting.map((waiter) => waiter.chunkEnded));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nimbus-sh/fabric",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "The Cloudflare half of Nimbus — Durable Object facet hosting, dynamic-worker loader pools, the resident-process fabric, and DO alarm/hibernation machinery.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"typecheck": "tsc --noEmit"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@nimbus-sh/core": "^0.
|
|
54
|
-
"@nimbus-sh/platform": "^0.
|
|
53
|
+
"@nimbus-sh/core": "^0.8.0",
|
|
54
|
+
"@nimbus-sh/platform": "^0.3.0",
|
|
55
55
|
"zod": "^4.4.3"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
package/src/composition.ts
CHANGED
|
@@ -1,16 +1,3 @@
|
|
|
1
1
|
// Core and fabric share one holder without introducing a dependency cycle.
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
composeFabric,
|
|
5
|
-
getCtxExports,
|
|
6
|
-
stagedBootAssembler,
|
|
7
|
-
supervisorEntrypoint,
|
|
8
|
-
supervisorEntrypointName,
|
|
9
|
-
} from '@nimbus-sh/platform/composition.js';
|
|
10
|
-
|
|
11
|
-
export type {
|
|
12
|
-
CtxExports,
|
|
13
|
-
EntrypointLoopbackFactory,
|
|
14
|
-
FabricComposition,
|
|
15
|
-
StagedBootAssembler,
|
|
16
|
-
} from '@nimbus-sh/platform/composition.js';
|
|
2
|
+
export * from '@nimbus-sh/platform/composition.js';
|
|
3
|
+
export type * from '@nimbus-sh/platform/composition.js';
|
package/src/fenced-work.ts
CHANGED
|
@@ -225,6 +225,11 @@ export class FencedWork<R extends FencedWorkRecord> {
|
|
|
225
225
|
let inflight = this.drives.get(key);
|
|
226
226
|
if (inflight === undefined) {
|
|
227
227
|
inflight = (async (): Promise<boolean> => {
|
|
228
|
+
if (record.attempt >= FENCED_WORK_MAX_ATTEMPT) {
|
|
229
|
+
this.host.onAbandoned?.(record);
|
|
230
|
+
await this.supersede(key);
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
228
233
|
let failed = false;
|
|
229
234
|
try {
|
|
230
235
|
await this.host.redrive(record, record.attempt + 1);
|
|
@@ -310,6 +315,7 @@ export class FencedWork<R extends FencedWorkRecord> {
|
|
|
310
315
|
* a previous generation the terminal hook will never fire for.
|
|
311
316
|
*/
|
|
312
317
|
private async supersede(key: string): Promise<void> {
|
|
318
|
+
this.journalledPids.delete(Number(key.slice(FENCED_WORK_KEY_PREFIX.length)));
|
|
313
319
|
await this.storage.delete(key);
|
|
314
320
|
await this.storage.sync();
|
|
315
321
|
}
|
package/src/turn-budget.ts
CHANGED
|
@@ -142,7 +142,7 @@ export interface PacedWorkHost {
|
|
|
142
142
|
* reason. Without it the pump degrades to a same-context timer — see
|
|
143
143
|
* {@link PacedWork.nextTurn}.
|
|
144
144
|
*/
|
|
145
|
-
requestTurn?: () => void;
|
|
145
|
+
requestTurn?: (notBefore?: number) => void;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
/**
|
|
@@ -160,7 +160,7 @@ export class PacedWork implements TurnScheduler {
|
|
|
160
160
|
* half-built work for pids that no longer exist, where re-driving a launch
|
|
161
161
|
* from its inputs is the same idempotent work again.
|
|
162
162
|
*/
|
|
163
|
-
private waiters: Array<{ resume: () => void; chunkEnded: Promise<void
|
|
163
|
+
private waiters: Array<{ resume: () => void; chunkEnded: Promise<void>; notBefore: number }> = [];
|
|
164
164
|
|
|
165
165
|
/**
|
|
166
166
|
* `ctx` keys the cold-start queue the pump drains first on every turn it
|
|
@@ -181,14 +181,14 @@ export class PacedWork implements TurnScheduler {
|
|
|
181
181
|
* always performed, so a harness or a runtime without alarms loses the
|
|
182
182
|
* responsiveness but keeps the behaviour.
|
|
183
183
|
*/
|
|
184
|
-
nextTurn(chunkEnded: Promise<void
|
|
184
|
+
nextTurn(chunkEnded: Promise<void>, notBefore = 0): Promise<void> {
|
|
185
185
|
return new Promise<void>((resume) => {
|
|
186
|
-
this.waiters.push({ resume, chunkEnded });
|
|
186
|
+
this.waiters.push({ resume, chunkEnded, notBefore });
|
|
187
187
|
if (this.host.requestTurn) {
|
|
188
|
-
this.host.requestTurn();
|
|
188
|
+
this.host.requestTurn(notBefore);
|
|
189
189
|
return;
|
|
190
190
|
}
|
|
191
|
-
setTimeout(() => { void this.pump(); }, 0);
|
|
191
|
+
setTimeout(() => { void this.pump(); }, Math.max(0, notBefore - Date.now()));
|
|
192
192
|
});
|
|
193
193
|
}
|
|
194
194
|
|
|
@@ -206,9 +206,11 @@ export class PacedWork implements TurnScheduler {
|
|
|
206
206
|
// is what an alarm calls, and the first turn after a reset is the
|
|
207
207
|
// re-delivered alarm of a launch the reset interrupted.
|
|
208
208
|
await runColdStart(this.ctx);
|
|
209
|
-
const
|
|
209
|
+
const now = Date.now();
|
|
210
|
+
const waiting = this.waiters.filter((waiter) => waiter.notBefore <= now);
|
|
211
|
+
this.waiters = this.waiters.filter((waiter) => waiter.notBefore > now);
|
|
212
|
+
if (this.waiters.length > 0) this.host.requestTurn?.(Math.min(...this.waiters.map((waiter) => waiter.notBefore)));
|
|
210
213
|
if (waiting.length === 0) return;
|
|
211
|
-
this.waiters = [];
|
|
212
214
|
for (const waiter of waiting) waiter.resume();
|
|
213
215
|
await Promise.all(waiting.map((waiter) => waiter.chunkEnded));
|
|
214
216
|
}
|