lopata 0.18.4 → 0.19.1
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/types/api/dispatch.d.ts +2 -2
- package/dist/types/api/handlers/workflows.d.ts +2 -2
- package/dist/types/bindings/container-cleanup.d.ts +43 -0
- package/dist/types/bindings/container-docker.d.ts +24 -0
- package/dist/types/bindings/container.d.ts +4 -2
- package/dist/types/bindings/do-executor-worker.d.ts +73 -89
- package/dist/types/bindings/do-executor.d.ts +22 -1
- package/dist/types/bindings/do-worker-entry.d.ts +1 -1
- package/dist/types/bindings/do-worker-env.d.ts +16 -7
- package/dist/types/bindings/durable-object.d.ts +66 -4
- package/dist/types/bindings/queue.d.ts +4 -1
- package/dist/types/bindings/rpc-stub.d.ts +23 -1
- package/dist/types/bindings/scheduled.d.ts +13 -3
- package/dist/types/bindings/service-binding.d.ts +13 -4
- package/dist/types/bindings/static-assets.d.ts +1 -1
- package/dist/types/bindings/websocket-pair.d.ts +12 -3
- package/dist/types/bindings/workflow.d.ts +29 -0
- package/dist/types/config.d.ts +2 -0
- package/dist/types/env.d.ts +6 -0
- package/dist/types/error-page-render.d.ts +6 -0
- package/dist/types/execution-context.d.ts +8 -0
- package/dist/types/generation-manager.d.ts +21 -2
- package/dist/types/generation.d.ts +16 -21
- package/dist/types/import-graph.d.ts +28 -0
- package/dist/types/lopata-config.d.ts +3 -3
- package/dist/types/plugin.d.ts +4 -1
- package/dist/types/rpc-validate.d.ts +9 -0
- package/dist/types/setup-globals.d.ts +5 -1
- package/dist/types/tracing/context.d.ts +12 -0
- package/dist/types/tracing/span.d.ts +21 -3
- package/dist/types/tracing/store.d.ts +17 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dist/types/vite-plugin/index.d.ts +8 -1
- package/dist/types/worker-registry.d.ts +11 -4
- package/dist/types/worker-thread/do-protocol.d.ts +256 -0
- package/dist/types/worker-thread/entry.d.ts +2 -0
- package/dist/types/worker-thread/execution-context.d.ts +22 -0
- package/dist/types/worker-thread/executor.d.ts +123 -0
- package/dist/types/worker-thread/protocol.d.ts +553 -0
- package/dist/types/worker-thread/remote-trace-store.d.ts +27 -0
- package/dist/types/worker-thread/request-clone-fix.d.ts +24 -0
- package/dist/types/worker-thread/rpc-client.d.ts +4 -0
- package/dist/types/worker-thread/rpc-shared.d.ts +138 -0
- package/dist/types/worker-thread/serialize.d.ts +12 -0
- package/dist/types/worker-thread/stream-shared.d.ts +147 -0
- package/dist/types/worker-thread/thread-env.d.ts +42 -0
- package/dist/types/worker-thread/wire-handlers.d.ts +16 -0
- package/dist/types/worker-thread/ws-bridge-shared.d.ts +163 -0
- package/package.json +1 -1
- package/src/api/handlers/containers.ts +2 -1
- package/src/api/handlers/workflows.ts +39 -34
- package/src/bindings/container-cleanup.ts +125 -0
- package/src/bindings/container-docker.ts +49 -34
- package/src/bindings/container.ts +24 -9
- package/src/bindings/do-executor-inprocess.ts +9 -5
- package/src/bindings/do-executor-worker.ts +386 -158
- package/src/bindings/do-executor.ts +23 -1
- package/src/bindings/do-worker-entry.ts +243 -60
- package/src/bindings/do-worker-env.ts +296 -11
- package/src/bindings/durable-object.ts +231 -27
- package/src/bindings/email.ts +6 -0
- package/src/bindings/queue.ts +11 -1
- package/src/bindings/rpc-stub.ts +79 -10
- package/src/bindings/scheduled.ts +37 -30
- package/src/bindings/service-binding.ts +87 -33
- package/src/bindings/static-assets.ts +3 -2
- package/src/bindings/websocket-pair.ts +19 -3
- package/src/bindings/workflow.ts +91 -0
- package/src/cli/dev.ts +106 -41
- package/src/config.ts +6 -3
- package/src/db.ts +1 -0
- package/src/env.ts +40 -21
- package/src/error-page-render.ts +21 -0
- package/src/execution-context.ts +13 -3
- package/src/generation-manager.ts +144 -143
- package/src/generation.ts +150 -306
- package/src/import-graph.ts +140 -0
- package/src/lopata-config.ts +3 -3
- package/src/plugin.ts +7 -0
- package/src/rpc-validate.ts +29 -0
- package/src/setup-globals.ts +6 -17
- package/src/testing/durable-object.ts +5 -3
- package/src/testing/index.ts +8 -4
- package/src/tracing/context.ts +18 -0
- package/src/tracing/span.ts +83 -57
- package/src/tracing/store.ts +41 -3
- package/src/virtual-modules.ts +2 -0
- package/src/vite-plugin/dev-server-plugin.ts +4 -0
- package/src/vite-plugin/index.ts +8 -1
- package/src/worker-registry.ts +15 -2
- package/src/worker-thread/do-protocol.ts +237 -0
- package/src/worker-thread/entry.ts +454 -0
- package/src/worker-thread/execution-context.ts +53 -0
- package/src/worker-thread/executor.ts +595 -0
- package/src/worker-thread/protocol.ts +552 -0
- package/src/worker-thread/remote-trace-store.ts +90 -0
- package/src/worker-thread/request-clone-fix.ts +69 -0
- package/src/worker-thread/rpc-client.ts +5 -0
- package/src/worker-thread/rpc-shared.ts +503 -0
- package/src/worker-thread/serialize.ts +37 -0
- package/src/worker-thread/stream-shared.ts +414 -0
- package/src/worker-thread/thread-env.ts +350 -0
- package/src/worker-thread/wire-handlers.ts +80 -0
- package/src/worker-thread/ws-bridge-shared.ts +482 -0
- package/dist/types/bindings/do-websocket-bridge.d.ts +0 -60
- package/dist/types/module-cache.d.ts +0 -23
- package/src/bindings/do-websocket-bridge.ts +0 -79
- package/src/module-cache.ts +0 -58
- package/src/tracing/global.d.ts +0 -50
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import type { GenerationManager } from './generation-manager';
|
|
2
|
+
import type { WorkerThreadExecutor } from './worker-thread/executor';
|
|
3
|
+
export type ResolvedTarget = {
|
|
4
|
+
kind: 'thread';
|
|
5
|
+
env: Record<string, unknown>;
|
|
6
|
+
executor: WorkerThreadExecutor;
|
|
7
|
+
} | {
|
|
8
|
+
kind: 'in-process';
|
|
9
|
+
env: Record<string, unknown>;
|
|
10
|
+
workerModule: Record<string, unknown>;
|
|
11
|
+
};
|
|
2
12
|
/**
|
|
3
13
|
* Central registry holding all worker GenerationManagers, keyed by worker name.
|
|
4
14
|
* Used to resolve cross-worker service bindings.
|
|
@@ -16,10 +26,7 @@ export declare class WorkerRegistry {
|
|
|
16
26
|
* Lazily resolve a target worker's module and env from its active generation.
|
|
17
27
|
* Called on each service binding invocation so hot-reloaded workers are picked up.
|
|
18
28
|
*/
|
|
19
|
-
resolveTarget(workerName: string):
|
|
20
|
-
workerModule: Record<string, unknown>;
|
|
21
|
-
env: Record<string, unknown>;
|
|
22
|
-
};
|
|
29
|
+
resolveTarget(workerName: string): ResolvedTarget;
|
|
23
30
|
/** List all registered managers (for dashboard) */
|
|
24
31
|
listManagers(): Map<string, GenerationManager>;
|
|
25
32
|
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message protocol for the main ↔ DO-instance-worker channel.
|
|
3
|
+
*
|
|
4
|
+
* Sibling of `protocol.ts` (the main ↔ user-worker channel). The two channels
|
|
5
|
+
* are structurally parallel — same concepts under channel-specific names
|
|
6
|
+
* (`do-stream-chunk` here vs `stream-chunk` there, `do-req-stream-*` vs
|
|
7
|
+
* `req-stream-*`) — and both reuse the unified cross-thread RPC frames
|
|
8
|
+
* (`RpcCallRequest`, `RpcReply`, …) defined in `protocol.ts`. Keeping the DO
|
|
9
|
+
* channel's message types here (rather than inline in `do-executor-worker.ts`)
|
|
10
|
+
* lets the two channels be lined up and cross-referenced in one place; the
|
|
11
|
+
* executor/entry implementation logic stays in the bindings layer.
|
|
12
|
+
*/
|
|
13
|
+
import type { RpcCallRequest, RpcFetchRequest, RpcGetRequest, RpcReply, RpcReqStreamChunk, RpcReqStreamEnd, RpcReqStreamError, RpcStreamAck, RpcStreamCancel, SerializedError } from './protocol';
|
|
14
|
+
/**
|
|
15
|
+
* DO worker → main: the instance's lifecycle state changed. Main mirrors these
|
|
16
|
+
* flags onto the executor so the idle reaper behaves correctly:
|
|
17
|
+
* - `aborted` — `state.abort()` was called; the executor must be evicted and
|
|
18
|
+
* recreated fresh on next access (otherwise every command keeps throwing).
|
|
19
|
+
* - `blocked` — `blockConcurrencyWhile` is running; the executor must not be
|
|
20
|
+
* evicted mid-block.
|
|
21
|
+
*/
|
|
22
|
+
export interface DoStateSignal {
|
|
23
|
+
type: 'do-state';
|
|
24
|
+
aborted: boolean;
|
|
25
|
+
blocked: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** Commands sent from main thread to worker */
|
|
28
|
+
export type DOCommand = {
|
|
29
|
+
type: 'fetch';
|
|
30
|
+
url: string;
|
|
31
|
+
method: string;
|
|
32
|
+
headers: [string, string][];
|
|
33
|
+
body: ArrayBuffer | null;
|
|
34
|
+
/**
|
|
35
|
+
* When set, the request body is streamed: `body` is `null` and main pumps
|
|
36
|
+
* `do-req-stream-*` for this id so the DO worker reconstructs a
|
|
37
|
+
* `ReadableStream` for the rebuilt `Request`. Allows large uploads /
|
|
38
|
+
* streaming proxies to reach `instance.fetch()` incrementally.
|
|
39
|
+
*/
|
|
40
|
+
streamId?: number;
|
|
41
|
+
} | {
|
|
42
|
+
type: 'rpc-call';
|
|
43
|
+
method: string;
|
|
44
|
+
args: unknown[];
|
|
45
|
+
} | {
|
|
46
|
+
type: 'rpc-get';
|
|
47
|
+
prop: string;
|
|
48
|
+
} | {
|
|
49
|
+
type: 'alarm';
|
|
50
|
+
retryCount: number;
|
|
51
|
+
} | {
|
|
52
|
+
type: 'cleanup';
|
|
53
|
+
};
|
|
54
|
+
/** Results returned from worker to main thread */
|
|
55
|
+
export type DOResult = {
|
|
56
|
+
type: 'fetch';
|
|
57
|
+
status: number;
|
|
58
|
+
statusText: string;
|
|
59
|
+
headers: [string, string][];
|
|
60
|
+
body: ArrayBuffer | null;
|
|
61
|
+
/** Set when the DO's fetch handler returned a `Response{status:101, webSocket}`. */
|
|
62
|
+
fetchWebSocketId?: string;
|
|
63
|
+
/**
|
|
64
|
+
* When set, the body is streamed: `body` is `null` and the DO worker pumps
|
|
65
|
+
* `do-stream-chunk` / `do-stream-end` / `do-stream-error` for this id so
|
|
66
|
+
* main can reconstruct a `ReadableStream` and ship headers immediately.
|
|
67
|
+
* Mutually exclusive with `fetchWebSocketId`.
|
|
68
|
+
*/
|
|
69
|
+
streamId?: number;
|
|
70
|
+
} | {
|
|
71
|
+
type: 'rpc-call';
|
|
72
|
+
value: unknown;
|
|
73
|
+
} | {
|
|
74
|
+
type: 'rpc-get';
|
|
75
|
+
kind: 'value';
|
|
76
|
+
value: unknown;
|
|
77
|
+
} | {
|
|
78
|
+
type: 'rpc-get';
|
|
79
|
+
kind: 'function';
|
|
80
|
+
} | {
|
|
81
|
+
type: 'alarm';
|
|
82
|
+
} | {
|
|
83
|
+
type: 'cleanup';
|
|
84
|
+
} | {
|
|
85
|
+
type: 'error';
|
|
86
|
+
error: SerializedError;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Reverse-streaming for DO instance fetch responses (DO worker → main). When a
|
|
90
|
+
* DO `fetch()` returns a `Response` with a body, the worker ships the `result`
|
|
91
|
+
* with `streamId` set and pumps the body via these messages so SSE / chunked
|
|
92
|
+
* responses reach main (and onward to the caller) incrementally.
|
|
93
|
+
*
|
|
94
|
+
* Id space: per-`WorkerExecutor`. Independent of the `RpcStreamRegistry` used
|
|
95
|
+
* by env-binding fetches (those flow main → DO worker over the same channel).
|
|
96
|
+
*/
|
|
97
|
+
export interface DoStreamChunk {
|
|
98
|
+
type: 'do-stream-chunk';
|
|
99
|
+
streamId: number;
|
|
100
|
+
chunk: Uint8Array;
|
|
101
|
+
}
|
|
102
|
+
export interface DoStreamEnd {
|
|
103
|
+
type: 'do-stream-end';
|
|
104
|
+
streamId: number;
|
|
105
|
+
}
|
|
106
|
+
export interface DoStreamError {
|
|
107
|
+
type: 'do-stream-error';
|
|
108
|
+
streamId: number;
|
|
109
|
+
error: SerializedError;
|
|
110
|
+
}
|
|
111
|
+
/** main → DO worker: caller dropped the reconstructed body — stop the pump. */
|
|
112
|
+
export interface DoStreamCancel {
|
|
113
|
+
type: 'do-stream-cancel';
|
|
114
|
+
streamId: number;
|
|
115
|
+
}
|
|
116
|
+
/** main → DO worker: main consumed a DO-fetch response-body chunk and grants
|
|
117
|
+
* the DO worker one more credit (see `STREAM_BACKPRESSURE_WINDOW`). */
|
|
118
|
+
export interface DoStreamAck {
|
|
119
|
+
type: 'do-stream-ack';
|
|
120
|
+
streamId: number;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Forward-direction streaming for the DOCommand 'fetch' request body (main →
|
|
124
|
+
* DO worker). Main ships the 'fetch' command with `streamId` set and pumps
|
|
125
|
+
* the body via these messages so the DO worker reconstructs a
|
|
126
|
+
* `ReadableStream` for the rebuilt `Request`.
|
|
127
|
+
*
|
|
128
|
+
* Id space: per-`WorkerExecutor`, independent of the response-side `streamId`
|
|
129
|
+
* (`DoStreamChunk`) and the env-binding RPC stream registries.
|
|
130
|
+
*/
|
|
131
|
+
export interface DoReqStreamChunk {
|
|
132
|
+
type: 'do-req-stream-chunk';
|
|
133
|
+
streamId: number;
|
|
134
|
+
chunk: Uint8Array;
|
|
135
|
+
}
|
|
136
|
+
export interface DoReqStreamEnd {
|
|
137
|
+
type: 'do-req-stream-end';
|
|
138
|
+
streamId: number;
|
|
139
|
+
}
|
|
140
|
+
export interface DoReqStreamError {
|
|
141
|
+
type: 'do-req-stream-error';
|
|
142
|
+
streamId: number;
|
|
143
|
+
error: SerializedError;
|
|
144
|
+
}
|
|
145
|
+
/** DO worker → main: instance code cancelled the reconstructed request body. */
|
|
146
|
+
export interface DoReqStreamCancel {
|
|
147
|
+
type: 'do-req-stream-cancel';
|
|
148
|
+
streamId: number;
|
|
149
|
+
}
|
|
150
|
+
/** DO worker → main: instance code pulled a request-body chunk and grants main's
|
|
151
|
+
* pump one more credit (cross-thread backpressure, mirrors {@link DoStreamAck}). */
|
|
152
|
+
export interface DoReqStreamAck {
|
|
153
|
+
type: 'do-req-stream-ack';
|
|
154
|
+
streamId: number;
|
|
155
|
+
}
|
|
156
|
+
/** Messages from main thread → worker */
|
|
157
|
+
export type DOWorkerMessage = {
|
|
158
|
+
type: 'command';
|
|
159
|
+
id: number;
|
|
160
|
+
command: DOCommand;
|
|
161
|
+
}
|
|
162
|
+
/** A real client wrote bytes; deliver them to the user's `server` peer inside the DO worker. */
|
|
163
|
+
| {
|
|
164
|
+
type: 'fetch-ws-incoming';
|
|
165
|
+
wsId: string;
|
|
166
|
+
data: string | ArrayBuffer;
|
|
167
|
+
} | {
|
|
168
|
+
type: 'fetch-ws-close-in';
|
|
169
|
+
wsId: string;
|
|
170
|
+
code: number;
|
|
171
|
+
reason: string;
|
|
172
|
+
wasClean: boolean;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Env-binding fetch returned `Response{status:101, webSocket}`; main adopted
|
|
176
|
+
* the upstream `CFWebSocket` and ships its events to the DO worker, where a
|
|
177
|
+
* user-facing peer reconstructed via `WsGuestBridge.createBridgedSocket`
|
|
178
|
+
* dispatches them on user code's `.addEventListener('message')` / `.onmessage`.
|
|
179
|
+
*/
|
|
180
|
+
| {
|
|
181
|
+
type: 'env-ws-incoming';
|
|
182
|
+
wsId: string;
|
|
183
|
+
data: string | ArrayBuffer;
|
|
184
|
+
} | {
|
|
185
|
+
type: 'env-ws-close-in';
|
|
186
|
+
wsId: string;
|
|
187
|
+
code: number;
|
|
188
|
+
reason: string;
|
|
189
|
+
wasClean: boolean;
|
|
190
|
+
} | RpcReply
|
|
191
|
+
/** Caller-side cancel for a streamed DO-fetch response body. */
|
|
192
|
+
| DoStreamCancel
|
|
193
|
+
/** Caller-side credit grant for a streamed DO-fetch response body. */
|
|
194
|
+
| DoStreamAck
|
|
195
|
+
/** Body chunks for a streamed DO-fetch *request* body (main → DO worker). */
|
|
196
|
+
| DoReqStreamChunk | DoReqStreamEnd | DoReqStreamError;
|
|
197
|
+
/** Messages from worker → main thread */
|
|
198
|
+
export type DOMainMessage = {
|
|
199
|
+
type: 'need-init';
|
|
200
|
+
} | {
|
|
201
|
+
type: 'ready';
|
|
202
|
+
} | {
|
|
203
|
+
type: 'result';
|
|
204
|
+
id: number;
|
|
205
|
+
result: DOResult;
|
|
206
|
+
} | {
|
|
207
|
+
type: 'alarm-set';
|
|
208
|
+
time: number | null;
|
|
209
|
+
} | DoStateSignal
|
|
210
|
+
/** The user's `server` peer sent bytes; forward to the real client via the main-side CFWebSocket. */
|
|
211
|
+
| {
|
|
212
|
+
type: 'fetch-ws-outgoing';
|
|
213
|
+
wsId: string;
|
|
214
|
+
data: string | ArrayBuffer;
|
|
215
|
+
} | {
|
|
216
|
+
type: 'fetch-ws-close-out';
|
|
217
|
+
wsId: string;
|
|
218
|
+
code: number;
|
|
219
|
+
reason: string;
|
|
220
|
+
wasClean: boolean;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* User code (inside the DO worker) emitted bytes / closed on a CFWebSocket
|
|
224
|
+
* reconstructed from an env-binding fetch upgrade. Forward to the upstream
|
|
225
|
+
* peer adopted on main via `_envBindingWsBridge`.
|
|
226
|
+
*/
|
|
227
|
+
| {
|
|
228
|
+
type: 'env-ws-outgoing';
|
|
229
|
+
wsId: string;
|
|
230
|
+
data: string | ArrayBuffer;
|
|
231
|
+
} | {
|
|
232
|
+
type: 'env-ws-close-out';
|
|
233
|
+
wsId: string;
|
|
234
|
+
code: number;
|
|
235
|
+
reason: string;
|
|
236
|
+
wasClean: boolean;
|
|
237
|
+
} | RpcCallRequest | RpcGetRequest | RpcFetchRequest | RpcStreamCancel | RpcStreamAck | RpcReqStreamChunk | RpcReqStreamEnd | RpcReqStreamError
|
|
238
|
+
/** Body chunks for a streamed DO-fetch response (see {@link DoStreamChunk}). */
|
|
239
|
+
| DoStreamChunk | DoStreamEnd | DoStreamError
|
|
240
|
+
/** Instance-side cancel for a streamed DO-fetch request body. */
|
|
241
|
+
| DoReqStreamCancel
|
|
242
|
+
/** Instance-side credit grant for a streamed DO-fetch request body. */
|
|
243
|
+
| DoReqStreamAck
|
|
244
|
+
/**
|
|
245
|
+
* Container lifecycle notifications. Main owns the active-container Set so
|
|
246
|
+
* one centralized `exit` handler can `docker rm -f` everything, regardless
|
|
247
|
+
* of which DO worker created it. The label-based reaper handles processes
|
|
248
|
+
* that die before the handler runs.
|
|
249
|
+
*/
|
|
250
|
+
| {
|
|
251
|
+
type: 'container-registered';
|
|
252
|
+
name: string;
|
|
253
|
+
} | {
|
|
254
|
+
type: 'container-removed';
|
|
255
|
+
name: string;
|
|
256
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker-thread implementation of CF's `ExecutionContext`. Tracks
|
|
3
|
+
* `waitUntil()` promises locally (they capture worker-side closures) and
|
|
4
|
+
* notifies main of each add/settle so reload drain can wait for them.
|
|
5
|
+
*/
|
|
6
|
+
import type { WorkerMessage } from './protocol';
|
|
7
|
+
/**
|
|
8
|
+
* Register a background promise with main's reload-drain accounting (same
|
|
9
|
+
* `wait-until-add` / `wait-until-settle` protocol as `ctx.waitUntil`). Used for
|
|
10
|
+
* worker-side work that isn't tied to an `ExecutionContext` — e.g. an in-flight
|
|
11
|
+
* queue batch, so reload drain waits for it instead of terminating mid-batch.
|
|
12
|
+
*/
|
|
13
|
+
export declare function trackBackgroundWork(post: (msg: WorkerMessage) => void, promise: Promise<unknown>): void;
|
|
14
|
+
export declare class WorkerExecutionContext {
|
|
15
|
+
/** `ctx.props` — carries the calling worker's service-binding `props` for
|
|
16
|
+
* `entrypoint-rpc` / `fetch` dispatch; `{}` for top-level HTTP. */
|
|
17
|
+
readonly props: Record<string, unknown>;
|
|
18
|
+
private _post;
|
|
19
|
+
constructor(post: (msg: WorkerMessage) => void, props?: Record<string, unknown>);
|
|
20
|
+
waitUntil(promise: Promise<unknown>): void;
|
|
21
|
+
passThroughOnException(): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main-thread side of the worker-thread runtime.
|
|
3
|
+
*
|
|
4
|
+
* Spawns a Bun Worker that hosts the user module graph (see `entry.ts`)
|
|
5
|
+
* and exposes `executeFetch()` to the rest of lopata. Lifecycle is
|
|
6
|
+
* one-shot: each Generation owns its own executor and `dispose()` is
|
|
7
|
+
* called when the generation is stopped (i.e. on every reload).
|
|
8
|
+
*/
|
|
9
|
+
import type { WranglerConfig } from '../config';
|
|
10
|
+
import type { WorkflowControlOp, WorkflowControlResult } from './protocol';
|
|
11
|
+
type HandlerResult = {
|
|
12
|
+
ok: true;
|
|
13
|
+
} | {
|
|
14
|
+
ok: false;
|
|
15
|
+
noHandler: true;
|
|
16
|
+
};
|
|
17
|
+
export interface WorkerThreadExecutorOptions {
|
|
18
|
+
modulePath: string;
|
|
19
|
+
config: WranglerConfig;
|
|
20
|
+
baseDir: string;
|
|
21
|
+
workerName?: string;
|
|
22
|
+
browserConfig?: {
|
|
23
|
+
wsEndpoint?: string;
|
|
24
|
+
executablePath?: string;
|
|
25
|
+
headless?: boolean;
|
|
26
|
+
};
|
|
27
|
+
/** Main-thread env holding the stateful binding instances the worker calls into via RPC. */
|
|
28
|
+
mainEnv: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
export interface WorkerReadyInfo {
|
|
31
|
+
/** className → whether the user's DO class defines an `alarm()` handler. */
|
|
32
|
+
doAlarmHandlers: Record<string, boolean>;
|
|
33
|
+
}
|
|
34
|
+
export declare class WorkerThreadExecutor {
|
|
35
|
+
private _worker;
|
|
36
|
+
private _ready;
|
|
37
|
+
private _readyResolve;
|
|
38
|
+
private _readyReject;
|
|
39
|
+
private _pending;
|
|
40
|
+
private _pendingHandlers;
|
|
41
|
+
private _pendingRpc;
|
|
42
|
+
private _pendingRpcGet;
|
|
43
|
+
private _pendingWorkflowControl;
|
|
44
|
+
private _nextId;
|
|
45
|
+
private _disposed;
|
|
46
|
+
private _initConfig;
|
|
47
|
+
private _mainEnv;
|
|
48
|
+
private _pendingWaitUntil;
|
|
49
|
+
private _wsBridge;
|
|
50
|
+
/** Main-side bridge for upstream CFWebSockets adopted from env-binding fetches
|
|
51
|
+
* the user worker initiated (`env.DO.fetch('/ws')` returning 101). The worker
|
|
52
|
+
* side holds the user-facing peer; events flow both ways so user code can
|
|
53
|
+
* consume the socket (`.accept()`/`.send()`), not just reship it. */
|
|
54
|
+
private _envBindingWsBridge;
|
|
55
|
+
/** Reconstructed response bodies fed by `stream-chunk` from the worker
|
|
56
|
+
* (top-level fetch response → main). */
|
|
57
|
+
private _responseStreams;
|
|
58
|
+
/** Main-side host of the unified cross-thread RPC channel — binding call/get/
|
|
59
|
+
* fetch from the user's worker, with response/request-body streaming. Shared
|
|
60
|
+
* with the DO-worker executor; channel-specifics injected as hooks. */
|
|
61
|
+
private _rpcChannel;
|
|
62
|
+
/** Outbound request-body pumps for the top-level fetch path (main → worker).
|
|
63
|
+
* A `req-stream-cancel` from the worker (user code cancelled `request.body`)
|
|
64
|
+
* stops the source reader. */
|
|
65
|
+
private _topRequestStreams;
|
|
66
|
+
constructor(options: WorkerThreadExecutorOptions);
|
|
67
|
+
/** Reject every outstanding promise and tear down bridges. Shared by `onerror`
|
|
68
|
+
* (worker crashed) and `dispose()` (planned teardown). */
|
|
69
|
+
private _failAll;
|
|
70
|
+
private _send;
|
|
71
|
+
private _handleMessage;
|
|
72
|
+
/** Apply a forwarded trace-store write on main. Wrapped in try/catch because
|
|
73
|
+
* these run inside `worker.onmessage`: a write that throws (a `BigInt` /
|
|
74
|
+
* circular value `JSON.stringify` chokes on, a transient DB error) would be
|
|
75
|
+
* an uncaught exception that takes down the whole dev server. A failed trace
|
|
76
|
+
* write is diagnostic-only — never worth crashing for. */
|
|
77
|
+
private _applyTrace;
|
|
78
|
+
/** Background `waitUntil` promises still in flight on the worker side. */
|
|
79
|
+
pendingWaitUntil(): number;
|
|
80
|
+
/** In-flight scheduled/email handlers and inbound entrypoint RPC/property-get
|
|
81
|
+
* calls (another worker calling `env.THIS.method()`). Reload drain consults
|
|
82
|
+
* this so a cron/email handler or inbound RPC firing just before reload isn't
|
|
83
|
+
* force-terminated mid-execution. */
|
|
84
|
+
pendingHandlerWork(): number;
|
|
85
|
+
/** In-flight streamed bodies for the top-level fetch path: response bodies the
|
|
86
|
+
* client is still downloading (`_responseStreams`, incl. SSE) plus request-body
|
|
87
|
+
* pumps still uploading (`_topRequestStreams`). `executeFetch` resolves at the
|
|
88
|
+
* headers, so these aren't reflected by `pendingFetch()` — reload drain must
|
|
89
|
+
* consult them or it cuts off an active download/SSE with zero grace. */
|
|
90
|
+
openStreamCount(): number;
|
|
91
|
+
/** In-flight top-level `executeFetch` calls. A cross-worker service-binding
|
|
92
|
+
* fetch (`env.OTHER.fetch()`) lands here directly via the registry without
|
|
93
|
+
* touching the target `Generation.activeRequests`, so the drain must consult
|
|
94
|
+
* this too — otherwise reloading the target severs the request mid-flight. */
|
|
95
|
+
pendingFetch(): number;
|
|
96
|
+
private _resolveBinding;
|
|
97
|
+
private _pumpTopRequestBody;
|
|
98
|
+
/** Resolves when the worker has imported the user module successfully. */
|
|
99
|
+
ready(): Promise<WorkerReadyInfo>;
|
|
100
|
+
/**
|
|
101
|
+
* Allocate an id, register a pending promise, post the command. The `build`
|
|
102
|
+
* callback receives the id + active span context (so sub-spans on the worker
|
|
103
|
+
* side link to the caller) and returns the actual `WorkerCommand`.
|
|
104
|
+
*/
|
|
105
|
+
private _sendAndAwait;
|
|
106
|
+
executeFetch(request: Request, props?: Record<string, unknown>): Promise<Response>;
|
|
107
|
+
executeScheduled(cronExpr: string, scheduledTime: number): Promise<HandlerResult>;
|
|
108
|
+
executeEntrypointRpc(entrypoint: string | undefined, method: string, args: unknown[], props?: Record<string, unknown>): Promise<unknown>;
|
|
109
|
+
executeEntrypointPropertyGet(entrypoint: string | undefined, property: string, props?: Record<string, unknown>): Promise<{
|
|
110
|
+
kind: 'value';
|
|
111
|
+
value: unknown;
|
|
112
|
+
} | {
|
|
113
|
+
kind: 'function';
|
|
114
|
+
}>;
|
|
115
|
+
executeEmail(messageId: string, from: string, to: string, raw: Uint8Array): Promise<HandlerResult>;
|
|
116
|
+
/** Run a dashboard workflow control op against the live worker-side binding. */
|
|
117
|
+
executeWorkflowControl(binding: string, op: WorkflowControlOp): Promise<WorkflowControlResult>;
|
|
118
|
+
/** Tell the worker to stop its queue consumers from claiming new messages
|
|
119
|
+
* (reload drain). In-flight batches finish and are awaited via wait-until. */
|
|
120
|
+
stopQueueConsumers(): void;
|
|
121
|
+
dispose(): void;
|
|
122
|
+
}
|
|
123
|
+
export {};
|