@effectionx/worker 0.4.1 → 0.5.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/README.md CHANGED
@@ -17,6 +17,7 @@ thread.
17
17
  - Gracefully shutdowns the worker from the main thread
18
18
  - Propagates errors from the worker to the main thread
19
19
  - Type-safe message handling with TypeScript
20
+ - Supports worker-initiated requests handled by the host
20
21
 
21
22
  ## Usage: Get worker's return value
22
23
 
@@ -84,6 +85,135 @@ try {
84
85
  }
85
86
  ```
86
87
 
88
+ ## Usage: Worker-initiated requests
89
+
90
+ Workers can initiate requests to the host using the `send` function provided to
91
+ `workerMain`. The host handles these requests with `worker.forEach`, returning a
92
+ response for each request.
93
+
94
+ ### Worker Thread
95
+
96
+ ```ts
97
+ import { workerMain } from "@effectionx/worker";
98
+
99
+ await workerMain<never, never, string, void, string, string>(
100
+ function* ({ send }) {
101
+ const response = yield* send("hello");
102
+ return `received: ${response}`;
103
+ },
104
+ );
105
+ ```
106
+
107
+ ### Main Thread
108
+
109
+ ```ts
110
+ import { run } from "effection";
111
+ import { useWorker } from "@effectionx/worker";
112
+
113
+ await run(function* () {
114
+ const worker = yield* useWorker<never, never, string, void>(
115
+ "./worker.ts",
116
+ { type: "module" },
117
+ );
118
+
119
+ const result = yield* worker.forEach<string, string>(function* (request) {
120
+ return `echo: ${request}`;
121
+ });
122
+
123
+ console.log(result); // Output: received: echo: hello
124
+ });
125
+ ```
126
+
127
+ ### Notes
128
+
129
+ - Only one `forEach` can be active at a time; concurrent calls throw.
130
+ - Requests are queued until `forEach` is called.
131
+ - Errors are serialized and rethrown on the caller side.
132
+
133
+ ## Usage: Progress streaming
134
+
135
+ The host can send progress updates back to the worker during request processing.
136
+ This enables real-time feedback for long-running operations.
137
+
138
+ ### Worker Thread
139
+
140
+ Use `send.stream<TProgress>()` to receive a subscription that yields progress
141
+ values before the final response:
142
+
143
+ ```ts
144
+ import { workerMain } from "@effectionx/worker";
145
+
146
+ interface Progress {
147
+ percent: number;
148
+ message: string;
149
+ }
150
+
151
+ await workerMain<never, never, string, void, string, string>(
152
+ function* ({ send }) {
153
+ // Request with progress streaming
154
+ const subscription = yield* send.stream<Progress>("process-data");
155
+
156
+ let next = yield* subscription.next();
157
+ while (!next.done) {
158
+ const progress = next.value;
159
+ console.log(`${progress.percent}%: ${progress.message}`);
160
+ next = yield* subscription.next();
161
+ }
162
+
163
+ // Final response
164
+ return `completed: ${next.value}`;
165
+ },
166
+ );
167
+ ```
168
+
169
+ ### Main Thread
170
+
171
+ The `forEach` handler receives a context object with a `progress()` method:
172
+
173
+ ```ts
174
+ import { run } from "effection";
175
+ import { useWorker } from "@effectionx/worker";
176
+
177
+ interface Progress {
178
+ percent: number;
179
+ message: string;
180
+ }
181
+
182
+ await run(function* () {
183
+ const worker = yield* useWorker<never, never, string, void>(
184
+ "./worker.ts",
185
+ { type: "module" },
186
+ );
187
+
188
+ const result = yield* worker.forEach<string, string, Progress>(
189
+ function* (request, ctx) {
190
+ yield* ctx.progress({ percent: 25, message: "Loading..." });
191
+ yield* ctx.progress({ percent: 50, message: "Processing..." });
192
+ yield* ctx.progress({ percent: 75, message: "Finalizing..." });
193
+ return "done";
194
+ },
195
+ );
196
+
197
+ console.log(result); // Output: completed: done
198
+ });
199
+ ```
200
+
201
+ ### Backpressure
202
+
203
+ The `progress()` method implements true backpressure:
204
+
205
+ - **`ctx.progress()` blocks** until the worker calls `subscription.next()`
206
+ - The host cannot send progress faster than the worker can receive it
207
+ - If the worker does async work between `next()` calls, the host remains blocked
208
+
209
+ This ensures the worker is never overwhelmed with progress updates.
210
+
211
+ ### Notes
212
+
213
+ - `send(request)` still works for simple request/response (ignores any progress)
214
+ - Progress type is the third type parameter on `forEach<TRequest, TResponse, TProgress>`
215
+ - The subscription's final `next()` returns `{ done: true, value: TResponse }`
216
+
87
217
  ## Usage: Sending messages to the worker
88
218
 
89
219
  The worker can respond to incoming messages using `forEach` function provided by