@zlink-systems/framework 0.10.0 → 0.12.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/.tsbuildinfo +1 -1
- package/dist/contracts/Configuration/EndpointNotation.d.ts +5 -4
- package/dist/contracts/Configuration/EndpointNotation.js +5 -4
- package/dist/contracts/Configuration/InternalDefaults.d.ts +0 -1
- package/dist/contracts/Configuration/InternalDefaults.js +1 -2
- package/dist/contracts/Configuration/RegistrationNormalizers.js +1 -2
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +2 -5
- package/dist/contracts/Configuration/RegistrationValidators.js +0 -1
- package/dist/contracts/Errors/ZLinkFrameworkException.d.ts +6 -7
- package/dist/contracts/Errors/ZLinkFrameworkException.js +6 -7
- package/dist/runtime/actors/actor-client.js +1 -1
- package/dist/runtime/actors/actor-mailbox.js +1 -5
- package/dist/runtime/backend/contracts/index.d.ts +2 -0
- package/dist/runtime/backend/mesh-completion-table.d.ts +1 -3
- package/dist/runtime/backend/mesh-completion-table.js +11 -15
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +11 -4
- package/dist/runtime/backend/mesh-dispatch-pump.js +201 -134
- package/dist/runtime/backend/node/node-backend-adapter-factory.d.ts +3 -4
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +51 -37
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
- package/dist/runtime/backend/node/node-backend-adapter-support.js +2 -2
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +2 -2
- package/dist/runtime/backend/node/node-event-loop-poller.d.ts +16 -0
- package/dist/runtime/backend/node/node-event-loop-poller.js +49 -0
- package/dist/runtime/backend/node/node-raw-binding-port.js +24 -41
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +8 -8
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +100 -107
- package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +3 -2
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +18 -67
- package/dist/runtime/backend/raw-binding-port.d.ts +1 -0
- package/dist/runtime/backend/runtime-values.d.ts +6 -1
- package/dist/runtime/backend/runtime-values.js +6 -0
- package/dist/runtime/channels/channel-dispatchers.js +2 -2
- package/dist/runtime/channels/channel-envelope.js +324 -121
- package/dist/runtime/channels/channel-multipart.d.ts +8 -1
- package/dist/runtime/channels/channel-outbound-operations.js +0 -2
- package/dist/runtime/channels/channel-receive-loops.d.ts +1 -3
- package/dist/runtime/channels/channel-receive-loops.js +25 -65
- package/dist/runtime/channels/channel-socket-registry.js +14 -1
- package/dist/runtime/channels/channel-transports.d.ts +2 -1
- package/dist/runtime/channels/channel-transports.js +12 -10
- package/dist/runtime/channels/client-server-location-runtime.js +15 -3
- package/dist/runtime/execution/serial-execution-queue.d.ts +5 -18
- package/dist/runtime/execution/serial-execution-queue.js +16 -80
- package/dist/runtime/foundation/event-loop-resources.d.ts +0 -3
- package/dist/runtime/foundation/event-loop-resources.js +2 -11
- package/dist/runtime/foundation/operation-registry.d.ts +2 -8
- package/dist/runtime/foundation/operation-registry.js +3 -21
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +19 -7
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +56 -10
- package/dist/runtime/foundation/service-mailbox.d.ts +1 -7
- package/dist/runtime/foundation/service-mailbox.js +3 -2
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -1
- package/dist/runtime/foundation/service-stateful-registry.d.ts +1 -1
- package/dist/runtime/foundation/service-stateful-registry.js +2 -2
- package/dist/runtime/foundation/service-stateful-runtime.js +14 -14
- package/dist/runtime/framework-errors-internal.d.ts +4 -4
- package/dist/runtime/framework-errors-internal.js +8 -10
- package/dist/runtime/host/actor-placement-coordinator.js +1 -1
- package/dist/runtime/host/index.js +1 -1
- package/dist/runtime/host/service-relocation-host-runtime.js +0 -4
- package/dist/runtime/host/spot-address-transport.js +1 -1
- package/dist/runtime/host/user-spot-creation-coordinator.js +1 -1
- package/dist/runtime/locations/location-store-repository.d.ts +1 -0
- package/dist/runtime/locations/location-store-repository.js +64 -75
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +0 -12
- package/dist/runtime/spots/spot-node-runtime-manager.js +6 -166
- package/dist/runtime/spots/spot-serial-turn-executor.js +1 -4
- package/dist/runtime/spots/spot-timer.d.ts +3 -0
- package/dist/runtime/spots/spot-timer.js +87 -18
- package/dist/runtime/streams/session-serial-executor.js +1 -3
- package/dist/runtime/streams/stream-session-runtime.d.ts +2 -2
- package/dist/runtime/streams/stream-session-runtime.js +13 -19
- package/dist/runtime/workers/index.d.ts +0 -1
- package/dist/runtime/workers/index.js +1 -9
- package/package.json +9 -3
- package/src/contracts/Configuration/EndpointNotation.ts +5 -4
- package/src/contracts/Configuration/InternalDefaults.ts +0 -1
- package/src/contracts/Configuration/RegistrationNormalizers.ts +2 -4
- package/src/contracts/Configuration/RegistrationTypes.ts +2 -5
- package/src/contracts/Configuration/RegistrationValidators.ts +0 -1
- package/src/contracts/Errors/ZLinkFrameworkException.ts +6 -7
- package/src/runtime/actors/actor-client.ts +1 -1
- package/src/runtime/actors/actor-mailbox.ts +1 -12
- package/src/runtime/backend/contracts/index.ts +2 -0
- package/src/runtime/backend/mesh-completion-table.ts +12 -23
- package/src/runtime/backend/mesh-dispatch-pump.ts +206 -138
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +66 -35
- package/src/runtime/backend/node/node-backend-adapter-support.ts +4 -4
- package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +2 -2
- package/src/runtime/backend/node/node-event-loop-poller.ts +55 -0
- package/src/runtime/backend/node/node-raw-binding-port.ts +30 -45
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +97 -110
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +23 -69
- package/src/runtime/backend/raw-binding-port.ts +1 -0
- package/src/runtime/backend/runtime-values.ts +13 -1
- package/src/runtime/channels/channel-dispatchers.ts +2 -2
- package/src/runtime/channels/channel-envelope.ts +379 -109
- package/src/runtime/channels/channel-multipart.ts +9 -1
- package/src/runtime/channels/channel-outbound-operations.ts +0 -1
- package/src/runtime/channels/channel-receive-loops.ts +24 -75
- package/src/runtime/channels/channel-socket-registry.ts +17 -1
- package/src/runtime/channels/channel-transports.ts +20 -10
- package/src/runtime/channels/client-server-location-runtime.ts +16 -2
- package/src/runtime/execution/serial-execution-queue.ts +16 -108
- package/src/runtime/foundation/event-loop-resources.ts +2 -11
- package/src/runtime/foundation/operation-registry.ts +2 -22
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +74 -19
- package/src/runtime/foundation/service-mailbox.ts +3 -13
- package/src/runtime/foundation/service-runtime-contracts.ts +2 -1
- package/src/runtime/foundation/service-stateful-registry.ts +2 -2
- package/src/runtime/foundation/service-stateful-runtime.ts +14 -14
- package/src/runtime/framework-errors-internal.ts +8 -10
- package/src/runtime/host/actor-placement-coordinator.ts +1 -1
- package/src/runtime/host/index.ts +2 -1
- package/src/runtime/host/service-relocation-host-runtime.ts +0 -4
- package/src/runtime/host/spot-address-transport.ts +1 -1
- package/src/runtime/host/user-spot-creation-coordinator.ts +1 -1
- package/src/runtime/locations/location-store-repository.ts +118 -80
- package/src/runtime/spots/spot-node-runtime-manager.ts +13 -233
- package/src/runtime/spots/spot-serial-turn-executor.ts +1 -8
- package/src/runtime/spots/spot-timer.ts +109 -18
- package/src/runtime/streams/session-serial-executor.ts +1 -7
- package/src/runtime/streams/stream-session-runtime.ts +13 -17
- package/src/runtime/workers/index.ts +2 -17
|
@@ -41,6 +41,18 @@ const systemTimerClock: ZLinkTimerClock = {
|
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
type ZLinkTimerOwnerSpot = ZLinkSpot | ZLinkEntrySpot;
|
|
44
|
+
|
|
45
|
+
interface ZLinkTimerFinalization {
|
|
46
|
+
readonly promise: Promise<void>;
|
|
47
|
+
readonly resolve: () => void;
|
|
48
|
+
readonly reject: (cause: unknown) => void;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface ZLinkTimerFinalizationStart {
|
|
52
|
+
readonly timeout: unknown;
|
|
53
|
+
readonly running: Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
|
|
44
56
|
type ZLinkTimerFailureReporter = (
|
|
45
57
|
tick: ZLinkTimerTick,
|
|
46
58
|
cause: unknown,
|
|
@@ -125,11 +137,13 @@ export class ZLinkSpotTimerRegistry {
|
|
|
125
137
|
? this.executionSerialForTimer?.(name, serial) ?? serial
|
|
126
138
|
: undefined;
|
|
127
139
|
if (this.executionBarrier !== undefined) executionSerial?.setExecutionBarrier(this.executionBarrier);
|
|
140
|
+
let callbackStarted = false;
|
|
128
141
|
const timer = startOutsideStateLane(() => new ZLinkManagedTimer(
|
|
129
142
|
name,
|
|
130
143
|
periodMs,
|
|
131
144
|
normalizeTimerOptions(options),
|
|
132
145
|
async (tick) => {
|
|
146
|
+
callbackStarted = false;
|
|
133
147
|
const timerFlow = createInboundFlow(undefined, 'Timer', this.flowCreationEnabled());
|
|
134
148
|
const operation = () => {
|
|
135
149
|
const current = this.timers.get(name);
|
|
@@ -137,6 +151,7 @@ export class ZLinkSpotTimerRegistry {
|
|
|
137
151
|
return undefined;
|
|
138
152
|
}
|
|
139
153
|
if (!this.executionAllowed()) return undefined;
|
|
154
|
+
callbackStarted = true;
|
|
140
155
|
return runWithFlow(timerFlow, () => handler.handle(spot, tick));
|
|
141
156
|
};
|
|
142
157
|
if (this.executeTimer !== undefined) {
|
|
@@ -146,9 +161,7 @@ export class ZLinkSpotTimerRegistry {
|
|
|
146
161
|
}
|
|
147
162
|
},
|
|
148
163
|
reportFailure,
|
|
149
|
-
() =>
|
|
150
|
-
? !executionSerial!.isExecuting
|
|
151
|
-
: this.isTimerExecuting?.(name) !== true,
|
|
164
|
+
() => callbackStarted,
|
|
152
165
|
this.clock
|
|
153
166
|
));
|
|
154
167
|
const registered = await this.lane.run(() => this.completeAddCore(
|
|
@@ -163,13 +176,18 @@ export class ZLinkSpotTimerRegistry {
|
|
|
163
176
|
|
|
164
177
|
async dispose(): Promise<void> {
|
|
165
178
|
const timers = await this.lane.run(() => {
|
|
166
|
-
const active = [...this.timers.
|
|
179
|
+
const active = [...this.timers.entries()].map(([name, entry]) => ({
|
|
180
|
+
name,
|
|
181
|
+
timer: entry.timer,
|
|
182
|
+
wait: this.executeTimer === undefined
|
|
183
|
+
? true
|
|
184
|
+
: this.isTimerExecuting?.(name) !== true
|
|
185
|
+
}));
|
|
167
186
|
this.timers.clear();
|
|
168
187
|
return active;
|
|
169
188
|
});
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
189
|
+
const finalizations = timers.map(({ timer }) => timer.dispose());
|
|
190
|
+
await Promise.all(finalizations.filter((_, index) => timers[index]!.wait));
|
|
173
191
|
}
|
|
174
192
|
|
|
175
193
|
async captureRelocation(): Promise<readonly ZLinkTimerRelocationState[]> {
|
|
@@ -248,6 +266,8 @@ export class ZLinkSpotTimerRegistry {
|
|
|
248
266
|
}
|
|
249
267
|
|
|
250
268
|
class ZLinkRegisteredTimer implements ZLinkTimer {
|
|
269
|
+
private finalization: Promise<void> | undefined;
|
|
270
|
+
|
|
251
271
|
constructor(
|
|
252
272
|
private readonly registry: ZLinkSpotTimerRegistry,
|
|
253
273
|
private readonly name: string,
|
|
@@ -260,7 +280,18 @@ class ZLinkRegisteredTimer implements ZLinkTimer {
|
|
|
260
280
|
}
|
|
261
281
|
|
|
262
282
|
cancel(signal?: AbortSignal): Promise<void> {
|
|
263
|
-
|
|
283
|
+
if (this.finalization !== undefined) return this.finalization;
|
|
284
|
+
try {
|
|
285
|
+
throwIfAborted(signal);
|
|
286
|
+
} catch (failure) {
|
|
287
|
+
return Promise.reject(failure);
|
|
288
|
+
}
|
|
289
|
+
this.finalization = this.registry.cancel(
|
|
290
|
+
this.name,
|
|
291
|
+
this.generation,
|
|
292
|
+
this.timer
|
|
293
|
+
);
|
|
294
|
+
return this.finalization;
|
|
264
295
|
}
|
|
265
296
|
|
|
266
297
|
dispose(): Promise<void> {
|
|
@@ -278,6 +309,8 @@ export class ZLinkManagedTimer implements ZLinkTimer {
|
|
|
278
309
|
private lastScheduledIndex = 0n;
|
|
279
310
|
private timeout: unknown;
|
|
280
311
|
private running: Promise<void> = Promise.resolve();
|
|
312
|
+
private dispatchFailure: { readonly cause: unknown } | undefined;
|
|
313
|
+
private finalization: ZLinkTimerFinalization | undefined;
|
|
281
314
|
|
|
282
315
|
constructor(
|
|
283
316
|
private readonly name: string,
|
|
@@ -297,9 +330,30 @@ export class ZLinkManagedTimer implements ZLinkTimer {
|
|
|
297
330
|
return this.disposed;
|
|
298
331
|
}
|
|
299
332
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
333
|
+
cancel(_signal?: AbortSignal): Promise<void> {
|
|
334
|
+
if (this.finalization !== undefined) return this.finalization.promise;
|
|
335
|
+
|
|
336
|
+
let resolve!: () => void;
|
|
337
|
+
let reject!: (cause: unknown) => void;
|
|
338
|
+
const promise = new Promise<void>((complete, fail) => {
|
|
339
|
+
resolve = complete;
|
|
340
|
+
reject = fail;
|
|
341
|
+
});
|
|
342
|
+
const finalization = { promise, resolve, reject };
|
|
343
|
+
this.finalization = finalization;
|
|
344
|
+
|
|
345
|
+
try {
|
|
346
|
+
const preparation = this.lane.run(() => this.cancelCore());
|
|
347
|
+
void preparation.then(
|
|
348
|
+
start => {
|
|
349
|
+
void this.completeFinalization(start, finalization).then(undefined, reject);
|
|
350
|
+
},
|
|
351
|
+
reject
|
|
352
|
+
);
|
|
353
|
+
} catch (failure) {
|
|
354
|
+
reject(failure);
|
|
355
|
+
}
|
|
356
|
+
return promise;
|
|
303
357
|
}
|
|
304
358
|
|
|
305
359
|
dispose(): Promise<void> {
|
|
@@ -363,7 +417,13 @@ export class ZLinkManagedTimer implements ZLinkTimer {
|
|
|
363
417
|
: Math.max(0, Number(this.lastScheduledIndex + 1n) * this.periodMs - this.elapsedMs());
|
|
364
418
|
this.timeout = this.clock.setTimeout(() => {
|
|
365
419
|
this.timeout = undefined;
|
|
366
|
-
|
|
420
|
+
const execution = startOutsideStateLane(() => this.fire());
|
|
421
|
+
this.running = execution.then(
|
|
422
|
+
() => undefined,
|
|
423
|
+
cause => this.lane.run(() => {
|
|
424
|
+
this.dispatchFailure ??= { cause };
|
|
425
|
+
})
|
|
426
|
+
);
|
|
367
427
|
}, delayMs);
|
|
368
428
|
}
|
|
369
429
|
|
|
@@ -388,14 +448,45 @@ export class ZLinkManagedTimer implements ZLinkTimer {
|
|
|
388
448
|
await this.lane.run(() => this.completeFireCore(prepared.scheduledIndex, shouldContinue));
|
|
389
449
|
}
|
|
390
450
|
|
|
391
|
-
private cancelCore():
|
|
392
|
-
if (this.disposed) return { running: Promise.resolve() };
|
|
451
|
+
private cancelCore(): ZLinkTimerFinalizationStart {
|
|
393
452
|
this.disposed = true;
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
453
|
+
const timeout = this.timeout;
|
|
454
|
+
this.timeout = undefined;
|
|
455
|
+
return {
|
|
456
|
+
timeout,
|
|
457
|
+
running: this.shouldWaitForRunningOnCancel()
|
|
458
|
+
? this.running
|
|
459
|
+
: Promise.resolve()
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
private async completeFinalization(
|
|
464
|
+
start: ZLinkTimerFinalizationStart,
|
|
465
|
+
finalization: ZLinkTimerFinalization
|
|
466
|
+
): Promise<void> {
|
|
467
|
+
const failures: unknown[] = [];
|
|
468
|
+
if (start.timeout !== undefined) {
|
|
469
|
+
try {
|
|
470
|
+
this.clock.clearTimeout(start.timeout);
|
|
471
|
+
} catch (failure) {
|
|
472
|
+
failures.push(failure);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
try {
|
|
476
|
+
await start.running;
|
|
477
|
+
} catch (failure) {
|
|
478
|
+
failures.push(failure);
|
|
479
|
+
}
|
|
480
|
+
const dispatchFailure = await this.lane.run(() => this.dispatchFailure);
|
|
481
|
+
if (dispatchFailure !== undefined) failures.push(dispatchFailure.cause);
|
|
482
|
+
|
|
483
|
+
if (failures.length === 0) {
|
|
484
|
+
finalization.resolve();
|
|
485
|
+
} else if (failures.length === 1) {
|
|
486
|
+
finalization.reject(failures[0]);
|
|
487
|
+
} else {
|
|
488
|
+
finalization.reject(new AggregateError(failures, `Timer '${this.name}' cleanup failed.`));
|
|
397
489
|
}
|
|
398
|
-
return { running: this.shouldWaitForRunningOnCancel() ? this.running : Promise.resolve() };
|
|
399
490
|
}
|
|
400
491
|
|
|
401
492
|
private prepareCaptureCore(): { readonly running: Promise<void> } {
|
|
@@ -16,13 +16,7 @@ import {
|
|
|
16
16
|
export class ZLinkSessionSerialExecutor {
|
|
17
17
|
private readonly scheduler = new ZLinkSerialExecutionQueue(
|
|
18
18
|
async (record) => this.execute(record),
|
|
19
|
-
{
|
|
20
|
-
capacityError: (lane) => createInternalFrameworkException(
|
|
21
|
-
ZLinkFrameworkInternalErrorKind.WorkerQueueFull,
|
|
22
|
-
`Stream Session ${lane} execution capacity is full.`,
|
|
23
|
-
true
|
|
24
|
-
)
|
|
25
|
-
}
|
|
19
|
+
{}
|
|
26
20
|
);
|
|
27
21
|
private closed = false;
|
|
28
22
|
|
|
@@ -92,29 +92,21 @@ const systemLivenessClock: ZLinkStreamLivenessClock = {
|
|
|
92
92
|
clearTimer: (timer) => clearTimeout(timer as ReturnType<typeof setTimeout>)
|
|
93
93
|
};
|
|
94
94
|
|
|
95
|
-
class
|
|
95
|
+
class ZLinkStreamReceiveWake {
|
|
96
96
|
private pending?: Promise<void>;
|
|
97
97
|
private resolvePending?: () => void;
|
|
98
|
-
private timer?: ReturnType<typeof setTimeout>;
|
|
99
98
|
private readonly finish = (): void => {
|
|
100
|
-
if (this.timer !== undefined) {
|
|
101
|
-
clearTimeout(this.timer);
|
|
102
|
-
this.timer = undefined;
|
|
103
|
-
}
|
|
104
99
|
const resolve = this.resolvePending;
|
|
105
100
|
this.pending = undefined;
|
|
106
101
|
this.resolvePending = undefined;
|
|
107
102
|
resolve?.();
|
|
108
103
|
};
|
|
109
104
|
|
|
110
|
-
constructor(private readonly delayMs: number) {}
|
|
111
|
-
|
|
112
105
|
wait(): Promise<void> {
|
|
113
106
|
if (this.pending !== undefined) return this.pending;
|
|
114
107
|
this.pending = new Promise<void>((resolve) => {
|
|
115
108
|
this.resolvePending = resolve;
|
|
116
109
|
});
|
|
117
|
-
this.timer = setTimeout(this.finish, this.delayMs);
|
|
118
110
|
return this.pending;
|
|
119
111
|
}
|
|
120
112
|
|
|
@@ -892,7 +884,7 @@ export class ZLinkStreamSessionNodeRuntime {
|
|
|
892
884
|
private stopped = false;
|
|
893
885
|
private readonly receiveAbortController = new AbortController();
|
|
894
886
|
private receiveLoop: Promise<void> | undefined;
|
|
895
|
-
private readonly
|
|
887
|
+
private readonly receiveWake = new ZLinkStreamReceiveWake();
|
|
896
888
|
private receiveWorkSinceYield = 0;
|
|
897
889
|
constructor(
|
|
898
890
|
private readonly options: ZLinkStreamSessionNodeRuntimeOptions & ZLinkStreamLivenessOptions
|
|
@@ -967,14 +959,15 @@ export class ZLinkStreamSessionNodeRuntime {
|
|
|
967
959
|
}
|
|
968
960
|
if (!this.options.readablePoller.wait(0)) {
|
|
969
961
|
permit.releaseAfterInternalProcessing();
|
|
970
|
-
await this.
|
|
962
|
+
await this.waitReceiveLoopWake(signal);
|
|
971
963
|
continue;
|
|
972
964
|
}
|
|
973
965
|
packet = this.takePacket();
|
|
974
966
|
if (!this.options.socket.recvPacket(packet, ZLINK_RECV_DONT_WAIT)) {
|
|
967
|
+
this.options.readablePoller.markDrained();
|
|
975
968
|
permit.releaseAfterInternalProcessing();
|
|
976
969
|
this.recyclePacket(packet);
|
|
977
|
-
await this.
|
|
970
|
+
await this.waitReceiveLoopWake(signal);
|
|
978
971
|
continue;
|
|
979
972
|
}
|
|
980
973
|
packetTransferred = true;
|
|
@@ -987,10 +980,10 @@ export class ZLinkStreamSessionNodeRuntime {
|
|
|
987
980
|
if (!this.isReceiveStopped(signal) && !packetTransferred) {
|
|
988
981
|
this.options.onError?.(error);
|
|
989
982
|
this.receiveWorkSinceYield = 0;
|
|
990
|
-
await
|
|
983
|
+
await new Promise<void>((resolve) => setImmediate(resolve));
|
|
991
984
|
} else if (!this.isReceiveStopped(signal)) {
|
|
992
985
|
this.receiveWorkSinceYield = 0;
|
|
993
|
-
await
|
|
986
|
+
await new Promise<void>((resolve) => setImmediate(resolve));
|
|
994
987
|
}
|
|
995
988
|
continue;
|
|
996
989
|
}
|
|
@@ -1350,12 +1343,15 @@ export class ZLinkStreamSessionNodeRuntime {
|
|
|
1350
1343
|
});
|
|
1351
1344
|
}
|
|
1352
1345
|
|
|
1353
|
-
private
|
|
1354
|
-
|
|
1346
|
+
private async waitReceiveLoopWake(signal: AbortSignal): Promise<void> {
|
|
1347
|
+
await Promise.race([
|
|
1348
|
+
this.options.readablePoller.waitForReadable(signal),
|
|
1349
|
+
this.receiveWake.wait()
|
|
1350
|
+
]);
|
|
1355
1351
|
}
|
|
1356
1352
|
|
|
1357
1353
|
private wakeReceiveLoop(): void {
|
|
1358
|
-
this.
|
|
1354
|
+
this.receiveWake.wake();
|
|
1359
1355
|
}
|
|
1360
1356
|
|
|
1361
1357
|
private getOrCreateSession(routingId: unknown): ZLinkStreamSessionRuntime | undefined {
|
|
@@ -7,8 +7,7 @@ import { ZLinkConfigurationException } from '../configuration';
|
|
|
7
7
|
import {
|
|
8
8
|
defaultWorkerMaxThreads,
|
|
9
9
|
DEFAULT_WORKER_IDLE_TIMEOUT_MS,
|
|
10
|
-
DEFAULT_WORKER_MIN_THREADS
|
|
11
|
-
DEFAULT_WORKER_QUEUE_LENGTH
|
|
10
|
+
DEFAULT_WORKER_MIN_THREADS
|
|
12
11
|
} from '../../contracts/Configuration/InternalDefaults';
|
|
13
12
|
import { createAbortError } from '../abort';
|
|
14
13
|
import {
|
|
@@ -24,20 +23,17 @@ export interface ZLinkWorkerRuntimeOptions {
|
|
|
24
23
|
readonly minThreads: number;
|
|
25
24
|
readonly maxThreads: number;
|
|
26
25
|
readonly idleTimeoutMs: number;
|
|
27
|
-
readonly maxQueueLength: number;
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
export function resolveWorkerRuntimeOptions(options?: ZLinkWorkerOptions): ZLinkWorkerRuntimeOptions {
|
|
31
29
|
const resolved = {
|
|
32
30
|
minThreads: options?.minThreads ?? DEFAULT_WORKER_MIN_THREADS,
|
|
33
31
|
maxThreads: options?.maxThreads ?? defaultWorkerMaxThreads(),
|
|
34
|
-
idleTimeoutMs: options?.idleTimeoutMs ?? DEFAULT_WORKER_IDLE_TIMEOUT_MS
|
|
35
|
-
maxQueueLength: options?.maxQueueLength ?? DEFAULT_WORKER_QUEUE_LENGTH
|
|
32
|
+
idleTimeoutMs: options?.idleTimeoutMs ?? DEFAULT_WORKER_IDLE_TIMEOUT_MS
|
|
36
33
|
};
|
|
37
34
|
requireNonNegativeInteger('Worker minThreads', resolved.minThreads);
|
|
38
35
|
requirePositiveInteger('Worker maxThreads', resolved.maxThreads);
|
|
39
36
|
requireNonNegativeInteger('Worker idleTimeoutMs', resolved.idleTimeoutMs);
|
|
40
|
-
requirePositiveInteger('Worker maxQueueLength', resolved.maxQueueLength);
|
|
41
37
|
if (resolved.maxThreads < resolved.minThreads) {
|
|
42
38
|
throw new ZLinkConfigurationException('Worker maxThreads must be greater than or equal to minThreads.');
|
|
43
39
|
}
|
|
@@ -98,9 +94,6 @@ class ZLinkCpuWorkerPool {
|
|
|
98
94
|
if (signal?.aborted === true) {
|
|
99
95
|
return Promise.reject(createAbortError());
|
|
100
96
|
}
|
|
101
|
-
if (this.queueCount >= this.options.maxQueueLength) {
|
|
102
|
-
return Promise.reject(workerQueueFull(this.options.maxQueueLength));
|
|
103
|
-
}
|
|
104
97
|
return new Promise<T>((resolve, reject) => {
|
|
105
98
|
const job = {
|
|
106
99
|
source: work.toString(),
|
|
@@ -535,14 +528,6 @@ class ZLinkSerialDeliveredPromise<T> implements Promise<T> {
|
|
|
535
528
|
}
|
|
536
529
|
}
|
|
537
530
|
|
|
538
|
-
function workerQueueFull(maxQueueLength: number): ZLinkFrameworkException {
|
|
539
|
-
return createInternalFrameworkException(
|
|
540
|
-
ZLinkFrameworkInternalErrorKind.WorkerQueueFull,
|
|
541
|
-
`CPU worker queue is full (maxQueueLength=${maxQueueLength}).`,
|
|
542
|
-
true
|
|
543
|
-
);
|
|
544
|
-
}
|
|
545
|
-
|
|
546
531
|
function workerTimedOut(timeoutMs: number): ZLinkFrameworkException {
|
|
547
532
|
return createInternalFrameworkException(
|
|
548
533
|
ZLinkFrameworkInternalErrorKind.WorkerTimedOut,
|