@nimbus-sh/fabric 0.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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +487 -0
  3. package/dist/alarms.d.ts +134 -0
  4. package/dist/alarms.d.ts.map +1 -0
  5. package/dist/alarms.js +214 -0
  6. package/dist/bindings.d.ts +316 -0
  7. package/dist/bindings.d.ts.map +1 -0
  8. package/dist/bindings.js +678 -0
  9. package/dist/ctx-exports.d.ts +47 -0
  10. package/dist/ctx-exports.d.ts.map +1 -0
  11. package/dist/ctx-exports.js +54 -0
  12. package/dist/facet-image-store.d.ts +112 -0
  13. package/dist/facet-image-store.d.ts.map +1 -0
  14. package/dist/facet-image-store.js +181 -0
  15. package/dist/fanout-pool.d.ts +223 -0
  16. package/dist/fanout-pool.d.ts.map +1 -0
  17. package/dist/fanout-pool.js +368 -0
  18. package/dist/index.d.ts +26 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +25 -0
  21. package/dist/inner-do-registry.d.ts +41 -0
  22. package/dist/inner-do-registry.d.ts.map +1 -0
  23. package/dist/inner-do-registry.js +51 -0
  24. package/dist/launch-journal.d.ts +170 -0
  25. package/dist/launch-journal.d.ts.map +1 -0
  26. package/dist/launch-journal.js +154 -0
  27. package/dist/launch-pacer.d.ts +173 -0
  28. package/dist/launch-pacer.d.ts.map +1 -0
  29. package/dist/launch-pacer.js +193 -0
  30. package/dist/loader-ledger.d.ts +57 -0
  31. package/dist/loader-ledger.d.ts.map +1 -0
  32. package/dist/loader-ledger.js +91 -0
  33. package/dist/loader-pool.d.ts +315 -0
  34. package/dist/loader-pool.d.ts.map +1 -0
  35. package/dist/loader-pool.js +666 -0
  36. package/dist/process-fabric.d.ts +524 -0
  37. package/dist/process-fabric.d.ts.map +1 -0
  38. package/dist/process-fabric.js +388 -0
  39. package/dist/process-host.d.ts +132 -0
  40. package/dist/process-host.d.ts.map +1 -0
  41. package/dist/process-host.js +444 -0
  42. package/dist/vendor/errors.d.ts +24 -0
  43. package/dist/vendor/errors.d.ts.map +1 -0
  44. package/dist/vendor/errors.js +46 -0
  45. package/dist/vendor/serialize.d.ts +3 -0
  46. package/dist/vendor/serialize.d.ts.map +1 -0
  47. package/dist/vendor/serialize.js +25 -0
  48. package/dist/vendor/types.d.ts +69 -0
  49. package/dist/vendor/types.d.ts.map +1 -0
  50. package/dist/vendor/types.js +4 -0
  51. package/dist/workerd-facet-host.d.ts +207 -0
  52. package/dist/workerd-facet-host.d.ts.map +1 -0
  53. package/dist/workerd-facet-host.js +508 -0
  54. package/dist/ws-hibernation-config.d.ts +73 -0
  55. package/dist/ws-hibernation-config.d.ts.map +1 -0
  56. package/dist/ws-hibernation-config.js +93 -0
  57. package/package.json +62 -0
  58. package/src/alarms.ts +275 -0
  59. package/src/bindings.ts +871 -0
  60. package/src/ctx-exports.ts +77 -0
  61. package/src/facet-image-store.ts +196 -0
  62. package/src/fanout-pool.ts +503 -0
  63. package/src/index.ts +26 -0
  64. package/src/inner-do-registry.ts +58 -0
  65. package/src/launch-journal.ts +229 -0
  66. package/src/launch-pacer.ts +231 -0
  67. package/src/loader-ledger.ts +112 -0
  68. package/src/loader-pool.ts +984 -0
  69. package/src/process-fabric.ts +729 -0
  70. package/src/process-host.ts +566 -0
  71. package/src/vendor/errors.ts +56 -0
  72. package/src/vendor/serialize.ts +37 -0
  73. package/src/vendor/types.ts +75 -0
  74. package/src/workerd-facet-host.ts +694 -0
  75. package/src/ws-hibernation-config.ts +123 -0
@@ -0,0 +1,123 @@
1
+ /**
2
+ * ws-hibernation-config.ts — W9 (CF research §C.3 + §C.4) configuration
3
+ * for setWebSocketAutoResponse + setHibernatableWebSocketEventTimeout.
4
+ *
5
+ * Why a dedicated module:
6
+ * - NimbusSession's constructor is already crowded; the calls have
7
+ * specific failure modes (workerd version dependence, optional
8
+ * globals) that deserve isolation.
9
+ * - Unit-testable in Node by passing a mock ctx — the constructor
10
+ * itself can't be (it pulls cloudflare:workers).
11
+ *
12
+ * What this does, in order:
13
+ * 1. setWebSocketAutoResponse(WebSocketRequestResponsePair('ping','pong'))
14
+ * — vite HMR clients ping every 30s and idle xterm tabs ping per
15
+ * minute. Without auto-response, every ping wakes the actor from
16
+ * hibernation: ~2880 wakes/day per idle tab. After this, zero
17
+ * billable wakes for matched ping/pong frames. Auto-response config
18
+ * survives hibernation per the STOR/Durable Objects WebSocket
19
+ * Primer (wiki page id 1372566651).
20
+ * 2. setHibernatableWebSocketEventTimeout(5000) — bound a single
21
+ * hibernation message handler. Long-running work runs in facets
22
+ * with their own CPU budget; the supervisor's WS handlers should
23
+ * enqueue then return. 5 s recommended in CF research §C.3.
24
+ *
25
+ * Both calls are gated on try/catch:
26
+ * - workerd builds before mid-2024 don't expose either method.
27
+ * - WebSocketRequestResponsePair is a workerd global; absent in Node.
28
+ * Failure is reported honestly via the return value so /api/_diag/memory
29
+ * can show whether the runtime supported the configuration.
30
+ */
31
+
32
+ import { errorText } from '@nimbus-sh/core/_shared/error-text.js';
33
+
34
+ /**
35
+ * Recommended hibernation event timeout (ms). 5 s per CF research §C.3
36
+ * — long enough for the heaviest non-facet WS message handler observed
37
+ * in W5 telemetry (~120 ms p99 for a heavy autocomplete request), short
38
+ * enough to bound a runaway handler before it pins the actor.
39
+ */
40
+ export const NIMBUS_HIBERNATION_EVENT_TIMEOUT_MS = 5000;
41
+
42
+ /** Public ping/pong contract — clients send `ping`, receive `pong`. */
43
+ export const WS_AUTO_RESPONSE_REQUEST = 'ping';
44
+ export const WS_AUTO_RESPONSE_RESPONSE = 'pong';
45
+
46
+ /**
47
+ * The hibernation controls this module configures. Both are optional because
48
+ * both are version-dependent: a workerd that predates one may still expose the
49
+ * other, and neither exists in Node.
50
+ */
51
+ export interface WsHibernationHost {
52
+ setWebSocketAutoResponse?(pair: WebSocketRequestResponsePair): void;
53
+ setHibernatableWebSocketEventTimeout?(timeoutMs: number): void;
54
+ }
55
+
56
+ export interface WsHibernationConfigResult {
57
+ /** True iff `setWebSocketAutoResponse` ran without throwing. */
58
+ autoResponseConfigured: boolean;
59
+ /**
60
+ * The timeout (in ms) we successfully set, or null if the call wasn't
61
+ * available / threw. Reported separately from autoResponseConfigured
62
+ * so a partial-support workerd shows the partial truth.
63
+ */
64
+ timeoutSetMs: number | null;
65
+ /** Optional error message — human-readable, never thrown. */
66
+ autoResponseError?: string;
67
+ timeoutError?: string;
68
+ }
69
+
70
+ /**
71
+ * Configure WS hibernation behaviours on a DurableObjectState. Idempotent
72
+ * — safe to call multiple times. Returns a result that NimbusSession
73
+ * surfaces via /api/_diag/memory under the `hib` key.
74
+ *
75
+ * The `ctx` parameter is structurally typed (anything with the right
76
+ * methods works) so this module stays Node-testable. In production the
77
+ * caller passes the real `this.ctx` from NimbusSession's constructor.
78
+ */
79
+ export function configureWsHibernation(
80
+ ctx: WsHibernationHost,
81
+ ): WsHibernationConfigResult {
82
+ const result: WsHibernationConfigResult = {
83
+ autoResponseConfigured: false,
84
+ timeoutSetMs: null,
85
+ };
86
+
87
+ // Step 1: auto-response. The constructor is a `declare class` in
88
+ // @cloudflare/workers-types, so it is in scope as a type but not on
89
+ // `typeof globalThis`, and a bare reference would throw in Node.
90
+ const workerdGlobals = globalThis as {
91
+ WebSocketRequestResponsePair?: typeof WebSocketRequestResponsePair;
92
+ };
93
+ const Pair = workerdGlobals.WebSocketRequestResponsePair;
94
+ if (typeof ctx?.setWebSocketAutoResponse === 'function' && typeof Pair === 'function') {
95
+ try {
96
+ const pair = new Pair(WS_AUTO_RESPONSE_REQUEST, WS_AUTO_RESPONSE_RESPONSE);
97
+ ctx.setWebSocketAutoResponse(pair);
98
+ result.autoResponseConfigured = true;
99
+ } catch (e) {
100
+ result.autoResponseError = errorText(e);
101
+ }
102
+ } else if (typeof Pair !== 'function') {
103
+ result.autoResponseError = 'WebSocketRequestResponsePair global not available';
104
+ } else {
105
+ result.autoResponseError = 'ctx.setWebSocketAutoResponse not available';
106
+ }
107
+
108
+ // Step 2: hibernation event timeout. Independent of auto-response —
109
+ // a workerd that lacks the global may still support the timeout
110
+ // method, and vice versa.
111
+ if (typeof ctx?.setHibernatableWebSocketEventTimeout === 'function') {
112
+ try {
113
+ ctx.setHibernatableWebSocketEventTimeout(NIMBUS_HIBERNATION_EVENT_TIMEOUT_MS);
114
+ result.timeoutSetMs = NIMBUS_HIBERNATION_EVENT_TIMEOUT_MS;
115
+ } catch (e) {
116
+ result.timeoutError = errorText(e);
117
+ }
118
+ } else {
119
+ result.timeoutError = 'ctx.setHibernatableWebSocketEventTimeout not available';
120
+ }
121
+
122
+ return result;
123
+ }