@zlink-systems/framework 0.31.0 → 0.32.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/.tsbuildinfo +1 -1
- package/dist/contracts/Actors/ZLinkActor.d.ts +2 -0
- package/dist/contracts/Actors/ZLinkSessionBindingIdentity.d.ts +6 -0
- package/dist/contracts/Actors/ZLinkSessionBindingIdentity.js +2 -0
- package/dist/contracts/Actors/index.d.ts +1 -0
- package/dist/contracts/Actors/index.js +1 -0
- package/dist/contracts/Common/payload-slab.d.ts +4 -0
- package/dist/contracts/Common/payload-slab.js +30 -0
- package/dist/contracts/Handlers/Contexts.d.ts +1 -0
- package/dist/internal.d.ts +9 -0
- package/dist/internal.js +23 -1
- package/dist/runtime/actors/actor-client.d.ts +1 -1
- package/dist/runtime/actors/actor-client.js +32 -23
- package/dist/runtime/actors/actor-context.js +1 -1
- package/dist/runtime/actors/actor-creation.js +1 -1
- package/dist/runtime/actors/actor-mailbox.d.ts +1 -1
- package/dist/runtime/actors/actor-runtime-state.d.ts +3 -2
- package/dist/runtime/actors/actor-runtime-state.js +24 -8
- package/dist/runtime/actors/index.d.ts +3 -3
- package/dist/runtime/actors/index.js +19 -32
- package/dist/runtime/actors/spot-actor-dispatch.d.ts +4 -2
- package/dist/runtime/actors/spot-actor-dispatch.js +2 -1
- package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +1 -0
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +3 -0
- package/dist/runtime/backend/contracts/index.d.ts +2 -0
- package/dist/runtime/backend/mesh-completion-table.d.ts +1 -0
- package/dist/runtime/backend/mesh-completion-table.js +1 -0
- package/dist/runtime/backend/node/node-mesh-backend-adapter.js +5 -1
- package/dist/runtime/backend/node/node-raw-binding-port.d.ts +7 -2
- package/dist/runtime/backend/node/node-raw-binding-port.js +17 -11
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +2 -2
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +15 -8
- package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +7 -6
- package/dist/runtime/channels/channel-dispatch-pipeline.js +1 -0
- package/dist/runtime/channels/channel-dispatchers.d.ts +7 -3
- package/dist/runtime/channels/channel-dispatchers.js +27 -19
- package/dist/runtime/channels/channel-envelope.js +543 -23
- package/dist/runtime/channels/channel-receive-loops.d.ts +9 -6
- package/dist/runtime/channels/channel-receive-loops.js +59 -18
- package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +22 -3
- package/dist/runtime/channels/channel-socket-registry.d.ts +22 -4
- package/dist/runtime/diagnostics/runtime-metrics.d.ts +1 -1
- package/dist/runtime/diagnostics/runtime-metrics.js +2 -1
- package/dist/runtime/execution/serial-execution-queue.d.ts +26 -13
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +27 -11
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +29 -25
- package/dist/runtime/foundation/service-liveness-registry.d.ts +1 -1
- package/dist/runtime/foundation/service-mailbox.d.ts +3 -1
- package/dist/runtime/foundation/service-mailbox.js +4 -1
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +3 -1
- package/dist/runtime/foundation/service-stateful-registry.d.ts +2 -0
- package/dist/runtime/foundation/service-stateful-registry.js +28 -12
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +51 -19
- package/dist/runtime/foundation/service-stateful-runtime.js +54 -5
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +3 -0
- package/dist/runtime/foundation/service-stateful-wire-codec.js +15 -0
- package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
- package/dist/runtime/foundation/service-wire-constants.generated.js +12 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +2 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.js +17 -7
- package/dist/runtime/host/actor-placement-coordinator.d.ts +1 -1
- package/dist/runtime/host/actor-transfer-runtime.d.ts +3 -3
- package/dist/runtime/host/application-job-queue.d.ts +1 -1
- package/dist/runtime/host/index.d.ts +89 -36
- package/dist/runtime/host/index.js +101 -7
- package/dist/runtime/host/location-runtime-owner.d.ts +2 -2
- package/dist/runtime/host/service-relocation-host-runtime.d.ts +181 -44
- package/dist/runtime/host/service-relocation-host-runtime.js +47 -13
- package/dist/runtime/host/spot-address-transport.js +50 -42
- package/dist/runtime/locations/actor-location-claims.js +9 -10
- package/dist/runtime/locations/auto-connect-loop.d.ts +0 -1
- package/dist/runtime/locations/auto-connect-loop.js +25 -19
- package/dist/runtime/locations/auto-connect-planner.js +2 -5
- package/dist/runtime/locations/auto-connect-reconciler.d.ts +1 -0
- package/dist/runtime/locations/auto-connect-reconciler.js +35 -23
- package/dist/runtime/locations/in-memory-location-store.d.ts +0 -2
- package/dist/runtime/locations/in-memory-location-store.js +1 -38
- package/dist/runtime/locations/location-store-repository.d.ts +0 -1
- package/dist/runtime/locations/location-store-repository.js +13 -115
- package/dist/runtime/locations/runtime.d.ts +3 -3
- package/dist/runtime/locations/runtime.js +12 -16
- package/dist/runtime/messaging/creation-payload-codec.js +2 -2
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +4 -0
- package/dist/runtime/protocol/service_wire_codec.generated.js +17 -7
- package/dist/runtime/spots/index.d.ts +20 -5
- package/dist/runtime/spots/index.js +14 -0
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +3 -3
- package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +1 -0
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +13 -7
- package/dist/runtime/spots/spot-actor-packet-drain.d.ts +1 -0
- package/dist/runtime/spots/spot-actor-packet-drain.js +12 -5
- package/dist/runtime/spots/spot-entry-activation.d.ts +2 -1
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +8 -6
- package/dist/runtime/spots/spot-node-runtime-manager.js +2 -0
- package/dist/runtime/spots/spot-route-packet-dispatch.js +7 -4
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +3 -1
- package/dist/runtime/spots/spot-serial-executor.d.ts +2 -1
- package/dist/runtime/spots/spot-subscription-dispatch.js +3 -1
- package/dist/runtime/spots/spot-timer.d.ts +1 -1
- package/dist/runtime/streams/actor-session-binding-registry.d.ts +9 -3
- package/dist/runtime/streams/actor-session-binding-registry.js +17 -0
- package/dist/runtime/streams/index.d.ts +3 -3
- package/dist/runtime/streams/index.js +22 -2
- package/dist/runtime/streams/managed-stream.js +2 -1
- package/dist/runtime/streams/session-calls.d.ts +1 -1
- package/dist/runtime/streams/session-calls.js +3 -9
- package/dist/runtime/streams/session-context.d.ts +2 -2
- package/dist/runtime/streams/session-context.js +2 -2
- package/dist/runtime/streams/stream-session-runtime.d.ts +1 -0
- package/dist/runtime/streams/stream-session-runtime.js +37 -12
- package/package.json +3 -3
- package/src/contracts/Actors/ZLinkActor.ts +6 -0
- package/src/contracts/Actors/ZLinkSessionBindingIdentity.ts +7 -0
- package/src/contracts/Actors/index.ts +1 -0
- package/src/contracts/Common/payload-slab.ts +29 -0
- package/src/contracts/Handlers/Contexts.ts +1 -0
- package/src/internal.ts +17 -0
- package/src/runtime/actors/actor-client.ts +48 -23
- package/src/runtime/actors/actor-context.ts +1 -1
- package/src/runtime/actors/actor-creation.ts +1 -1
- package/src/runtime/actors/actor-mailbox.ts +1 -1
- package/src/runtime/actors/actor-runtime-state.ts +28 -10
- package/src/runtime/actors/index.ts +30 -35
- package/src/runtime/actors/spot-actor-dispatch.ts +4 -3
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +4 -0
- package/src/runtime/backend/contracts/index.ts +2 -0
- package/src/runtime/backend/mesh-completion-table.ts +2 -0
- package/src/runtime/backend/node/node-mesh-backend-adapter.ts +5 -1
- package/src/runtime/backend/node/node-raw-binding-port.ts +20 -7
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +18 -10
- package/src/runtime/channels/channel-dispatch-pipeline.ts +6 -5
- package/src/runtime/channels/channel-dispatchers.ts +39 -19
- package/src/runtime/channels/channel-envelope.ts +547 -20
- package/src/runtime/channels/channel-receive-loops.ts +93 -36
- package/src/runtime/channels/channel-runtime-lifecycle.ts +2 -2
- package/src/runtime/channels/channel-socket-registry.ts +3 -3
- package/src/runtime/diagnostics/runtime-metrics.ts +3 -1
- package/src/runtime/execution/serial-execution-queue.ts +13 -13
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +40 -39
- package/src/runtime/foundation/service-liveness-registry.ts +1 -1
- package/src/runtime/foundation/service-mailbox.ts +6 -1
- package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
- package/src/runtime/foundation/service-stateful-registry.ts +39 -14
- package/src/runtime/foundation/service-stateful-runtime.ts +87 -21
- package/src/runtime/foundation/service-stateful-wire-codec.ts +18 -0
- package/src/runtime/foundation/service-wire-constants.generated.ts +10 -0
- package/src/runtime/foundation/service-wire-m6a-codec.ts +29 -7
- package/src/runtime/host/actor-placement-coordinator.ts +1 -1
- package/src/runtime/host/actor-transfer-runtime.ts +3 -3
- package/src/runtime/host/application-job-queue.ts +1 -1
- package/src/runtime/host/index.ts +183 -44
- package/src/runtime/host/location-runtime-owner.ts +2 -2
- package/src/runtime/host/service-relocation-host-runtime.ts +101 -65
- package/src/runtime/host/spot-address-transport.ts +67 -61
- package/src/runtime/locations/actor-location-claims.ts +14 -14
- package/src/runtime/locations/auto-connect-loop.ts +24 -16
- package/src/runtime/locations/auto-connect-planner.ts +2 -5
- package/src/runtime/locations/auto-connect-reconciler.ts +37 -24
- package/src/runtime/locations/in-memory-location-store.ts +1 -74
- package/src/runtime/locations/location-store-repository.ts +32 -153
- package/src/runtime/locations/runtime.ts +16 -28
- package/src/runtime/messaging/creation-payload-codec.ts +3 -3
- package/src/runtime/protocol/service_wire_codec.generated.ts +18 -8
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
- package/src/runtime/spots/index.ts +28 -4
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +1 -1
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +16 -6
- package/src/runtime/spots/spot-actor-packet-drain.ts +21 -6
- package/src/runtime/spots/spot-entry-activation.ts +1 -1
- package/src/runtime/spots/spot-node-runtime-manager.ts +8 -6
- package/src/runtime/spots/spot-route-packet-dispatch.ts +8 -4
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +3 -1
- package/src/runtime/spots/spot-serial-executor.ts +1 -1
- package/src/runtime/spots/spot-subscription-dispatch.ts +3 -1
- package/src/runtime/spots/spot-timer.ts +1 -1
- package/src/runtime/streams/actor-session-binding-registry.ts +30 -3
- package/src/runtime/streams/index.ts +30 -4
- package/src/runtime/streams/managed-stream.ts +2 -1
- package/src/runtime/streams/session-calls.ts +9 -14
- package/src/runtime/streams/session-context.ts +6 -11
- package/src/runtime/streams/stream-session-runtime.ts +49 -20
|
@@ -19,8 +19,9 @@ import {
|
|
|
19
19
|
} from './channel-receive-task-tracker';
|
|
20
20
|
import { ApplicationJobQueue, type ApplicationJobQueuePermit } from '../host/application-job-queue';
|
|
21
21
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
enterApplicationJobPermitScope,
|
|
23
|
+
leaveApplicationJobPermitScope,
|
|
24
|
+
releaseApplicationJobPermitTurn
|
|
24
25
|
} from '../application-jobs/application-job-queue-scope';
|
|
25
26
|
import {
|
|
26
27
|
ZLinkSerialExecutionQueue,
|
|
@@ -29,20 +30,45 @@ import {
|
|
|
29
30
|
|
|
30
31
|
export function createChannelApplicationDispatchQueue(): ZLinkSerialExecutionQueue {
|
|
31
32
|
return new ZLinkSerialExecutionQueue(async (record: ZLinkSerialWorkRecord<unknown>) => {
|
|
33
|
+
const permit = record.context as ApplicationJobQueuePermit;
|
|
34
|
+
const previousPermit = enterApplicationJobPermitScope(permit);
|
|
32
35
|
try {
|
|
33
36
|
void Promise.resolve(record.operation()).then(
|
|
34
37
|
(value) => {
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
try {
|
|
39
|
+
record.resolve(value);
|
|
40
|
+
} finally {
|
|
41
|
+
try {
|
|
42
|
+
record.release();
|
|
43
|
+
} finally {
|
|
44
|
+
releaseApplicationJobPermitTurn(permit);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
37
47
|
},
|
|
38
48
|
(error) => {
|
|
39
|
-
|
|
40
|
-
|
|
49
|
+
try {
|
|
50
|
+
record.reject(error);
|
|
51
|
+
} finally {
|
|
52
|
+
try {
|
|
53
|
+
record.release();
|
|
54
|
+
} finally {
|
|
55
|
+
releaseApplicationJobPermitTurn(permit);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
41
58
|
}
|
|
42
59
|
);
|
|
43
60
|
} catch (error) {
|
|
44
|
-
|
|
45
|
-
|
|
61
|
+
try {
|
|
62
|
+
record.reject(error);
|
|
63
|
+
} finally {
|
|
64
|
+
try {
|
|
65
|
+
record.release();
|
|
66
|
+
} finally {
|
|
67
|
+
releaseApplicationJobPermitTurn(permit);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
} finally {
|
|
71
|
+
leaveApplicationJobPermitScope(previousPermit);
|
|
46
72
|
}
|
|
47
73
|
});
|
|
48
74
|
}
|
|
@@ -79,7 +105,8 @@ interface ZLinkChannelRequestDispatchLoop {
|
|
|
79
105
|
reply(routingId: unknown, replyToken: unknown): ZLinkMultipartReplyOperation;
|
|
80
106
|
},
|
|
81
107
|
signal?: AbortSignal,
|
|
82
|
-
decodedHeader?: ZLinkChannelEnvelopeHeader
|
|
108
|
+
decodedHeader?: ZLinkChannelEnvelopeHeader,
|
|
109
|
+
receivedAt?: Date
|
|
83
110
|
): Promise<boolean | void>;
|
|
84
111
|
}
|
|
85
112
|
|
|
@@ -87,7 +114,8 @@ interface ZLinkChannelPublishDispatchLoop {
|
|
|
87
114
|
dispatch(
|
|
88
115
|
topicMessage: { readonly topic: string; readonly parts: readonly Message[] },
|
|
89
116
|
signal?: AbortSignal,
|
|
90
|
-
decodedHeader?: ZLinkChannelEnvelopeHeader
|
|
117
|
+
decodedHeader?: ZLinkChannelEnvelopeHeader,
|
|
118
|
+
receivedAt?: Date
|
|
91
119
|
): Promise<void>;
|
|
92
120
|
}
|
|
93
121
|
|
|
@@ -118,7 +146,8 @@ interface ZLinkRoutePacketDispatchLoop {
|
|
|
118
146
|
},
|
|
119
147
|
signal?: AbortSignal,
|
|
120
148
|
decodedHeader?: ZLinkChannelEnvelopeHeader,
|
|
121
|
-
infrastructureChecked?: boolean
|
|
149
|
+
infrastructureChecked?: boolean,
|
|
150
|
+
receivedAt?: Date
|
|
122
151
|
): Promise<boolean | void>;
|
|
123
152
|
}
|
|
124
153
|
|
|
@@ -240,7 +269,8 @@ export class ZLinkChannelReceiveLoop {
|
|
|
240
269
|
private readonly applicationJobQueue: ApplicationJobQueue,
|
|
241
270
|
reportError?: ZLinkReceiveTaskErrorReporter,
|
|
242
271
|
private readonly roundRobin?: ZLinkReceiveRoundRobinCoordinator,
|
|
243
|
-
private readonly applicationDispatchQueue = createChannelApplicationDispatchQueue()
|
|
272
|
+
private readonly applicationDispatchQueue = createChannelApplicationDispatchQueue(),
|
|
273
|
+
private readonly receivedAtClock: () => Date = () => new Date()
|
|
244
274
|
) {
|
|
245
275
|
this.inFlight = new ZLinkReceiveTaskTracker(reportError);
|
|
246
276
|
this.receiveOwner = roundRobin?.register() ?? Symbol('channel-receive-owner');
|
|
@@ -304,6 +334,7 @@ export class ZLinkChannelReceiveLoop {
|
|
|
304
334
|
this.roundRobin?.setReady(this.receiveOwner, false);
|
|
305
335
|
break;
|
|
306
336
|
}
|
|
337
|
+
const receivedAt = this.receivedAtClock();
|
|
307
338
|
const receivedBytes = messageBytes(received.parts);
|
|
308
339
|
let classification: ReturnType<ZLinkChannelReceiveLoop['classify']>;
|
|
309
340
|
try {
|
|
@@ -322,12 +353,18 @@ export class ZLinkChannelReceiveLoop {
|
|
|
322
353
|
break;
|
|
323
354
|
} else {
|
|
324
355
|
applicationJobPermit.markApplicationQueued();
|
|
325
|
-
const task =
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
356
|
+
const task = this.applicationDispatchQueue.submitPreAdmitted(
|
|
357
|
+
() =>
|
|
358
|
+
this.dispatchAndClose(
|
|
359
|
+
received,
|
|
360
|
+
signal,
|
|
361
|
+
classification.decodedHeader,
|
|
362
|
+
true,
|
|
363
|
+
undefined,
|
|
364
|
+
receivedAt
|
|
365
|
+
),
|
|
366
|
+
undefined,
|
|
367
|
+
applicationJobPermit
|
|
331
368
|
);
|
|
332
369
|
this.inFlight.track(task);
|
|
333
370
|
}
|
|
@@ -374,7 +411,8 @@ export class ZLinkChannelReceiveLoop {
|
|
|
374
411
|
signal?: AbortSignal,
|
|
375
412
|
decodedHeader?: ZLinkChannelEnvelopeHeader,
|
|
376
413
|
infrastructureChecked = false,
|
|
377
|
-
releaseRawReceive?: () => void
|
|
414
|
+
releaseRawReceive?: () => void,
|
|
415
|
+
receivedAt: Date = this.receivedAtClock()
|
|
378
416
|
): Promise<void> {
|
|
379
417
|
let closeReceived = true;
|
|
380
418
|
try {
|
|
@@ -386,7 +424,13 @@ export class ZLinkChannelReceiveLoop {
|
|
|
386
424
|
}
|
|
387
425
|
decodedHeader = classification.decodedHeader;
|
|
388
426
|
}
|
|
389
|
-
const consumed = await this.dispatcher.dispatch(
|
|
427
|
+
const consumed = await this.dispatcher.dispatch(
|
|
428
|
+
received,
|
|
429
|
+
this.router,
|
|
430
|
+
signal,
|
|
431
|
+
decodedHeader,
|
|
432
|
+
receivedAt
|
|
433
|
+
);
|
|
390
434
|
if (consumed === true) {
|
|
391
435
|
closeReceived = false;
|
|
392
436
|
}
|
|
@@ -452,7 +496,8 @@ export class ZLinkSubscriberReceiveLoop {
|
|
|
452
496
|
) => boolean | ZLinkSubscriberInfrastructureResult,
|
|
453
497
|
private readonly roundRobin?: ZLinkReceiveRoundRobinCoordinator,
|
|
454
498
|
reportError?: ZLinkReceiveTaskErrorReporter,
|
|
455
|
-
private readonly applicationDispatchQueue = createChannelApplicationDispatchQueue()
|
|
499
|
+
private readonly applicationDispatchQueue = createChannelApplicationDispatchQueue(),
|
|
500
|
+
private readonly receivedAtClock: () => Date = () => new Date()
|
|
456
501
|
) {
|
|
457
502
|
this.inFlight = new ZLinkReceiveTaskTracker(reportError);
|
|
458
503
|
this.poller = adapter.createReadablePoller(subscriber);
|
|
@@ -523,6 +568,7 @@ export class ZLinkSubscriberReceiveLoop {
|
|
|
523
568
|
if (!(await this.poller.waitForReadable(capacitySignal))) break;
|
|
524
569
|
continue;
|
|
525
570
|
}
|
|
571
|
+
const receivedAt = this.receivedAtClock();
|
|
526
572
|
const receivedBytes = messageBytes(topicMessage.parts as readonly Message[]);
|
|
527
573
|
let classification: ReturnType<ZLinkSubscriberReceiveLoop['classify']>;
|
|
528
574
|
try {
|
|
@@ -551,12 +597,18 @@ export class ZLinkSubscriberReceiveLoop {
|
|
|
551
597
|
break;
|
|
552
598
|
}
|
|
553
599
|
applicationJobPermit.markApplicationQueued();
|
|
554
|
-
const task =
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
600
|
+
const task = this.applicationDispatchQueue.submitPreAdmitted(
|
|
601
|
+
() =>
|
|
602
|
+
this.dispatchAndClose(
|
|
603
|
+
topicMessage,
|
|
604
|
+
signal,
|
|
605
|
+
classification.decodedHeader,
|
|
606
|
+
true,
|
|
607
|
+
undefined,
|
|
608
|
+
receivedAt
|
|
609
|
+
),
|
|
610
|
+
undefined,
|
|
611
|
+
applicationJobPermit
|
|
560
612
|
);
|
|
561
613
|
releaseRawReceive();
|
|
562
614
|
this.inFlight.track(task);
|
|
@@ -593,7 +645,8 @@ export class ZLinkSubscriberReceiveLoop {
|
|
|
593
645
|
signal?: AbortSignal,
|
|
594
646
|
decodedHeader?: ZLinkChannelEnvelopeHeader,
|
|
595
647
|
infrastructureChecked = false,
|
|
596
|
-
releaseRawReceive?: () => void
|
|
648
|
+
releaseRawReceive?: () => void,
|
|
649
|
+
receivedAt: Date = this.receivedAtClock()
|
|
597
650
|
): Promise<void> {
|
|
598
651
|
try {
|
|
599
652
|
if (!infrastructureChecked) {
|
|
@@ -601,7 +654,7 @@ export class ZLinkSubscriberReceiveLoop {
|
|
|
601
654
|
if (classification.kind === 'consumed') return;
|
|
602
655
|
decodedHeader = classification.decodedHeader;
|
|
603
656
|
}
|
|
604
|
-
await this.dispatcher.dispatch(topicMessage, signal, decodedHeader);
|
|
657
|
+
await this.dispatcher.dispatch(topicMessage, signal, decodedHeader, receivedAt);
|
|
605
658
|
} finally {
|
|
606
659
|
releaseRawReceive?.();
|
|
607
660
|
closeMessages(topicMessage.parts as readonly Message[]);
|
|
@@ -650,7 +703,8 @@ export class ZLinkRouteReceiveLoop {
|
|
|
650
703
|
private readonly applicationJobQueue: ApplicationJobQueue,
|
|
651
704
|
private readonly roundRobin?: ZLinkReceiveRoundRobinCoordinator,
|
|
652
705
|
reportError?: ZLinkReceiveTaskErrorReporter,
|
|
653
|
-
private readonly applicationDispatchQueue = createChannelApplicationDispatchQueue()
|
|
706
|
+
private readonly applicationDispatchQueue = createChannelApplicationDispatchQueue(),
|
|
707
|
+
private readonly receivedAtClock: () => Date = () => new Date()
|
|
654
708
|
) {
|
|
655
709
|
this.inFlight = new ZLinkReceiveTaskTracker(reportError);
|
|
656
710
|
this.receiveOwner = roundRobin?.register() ?? Symbol('route-receive-owner');
|
|
@@ -712,6 +766,7 @@ export class ZLinkRouteReceiveLoop {
|
|
|
712
766
|
if (!(await this.poller.waitForReadable(capacitySignal))) break;
|
|
713
767
|
continue;
|
|
714
768
|
}
|
|
769
|
+
const receivedAt = this.receivedAtClock();
|
|
715
770
|
const receivedBytes = messageBytes(received.parts);
|
|
716
771
|
let infrastructure: boolean | Promise<void> | undefined;
|
|
717
772
|
try {
|
|
@@ -763,10 +818,10 @@ export class ZLinkRouteReceiveLoop {
|
|
|
763
818
|
break;
|
|
764
819
|
}
|
|
765
820
|
applicationJobPermit.markApplicationQueued();
|
|
766
|
-
const task =
|
|
767
|
-
this.
|
|
768
|
-
|
|
769
|
-
|
|
821
|
+
const task = this.applicationDispatchQueue.submitPreAdmitted(
|
|
822
|
+
() => this.dispatchAndClose(received, signal, true, undefined, receivedAt),
|
|
823
|
+
undefined,
|
|
824
|
+
applicationJobPermit
|
|
770
825
|
);
|
|
771
826
|
releaseRawReceive();
|
|
772
827
|
this.inFlight.track(task);
|
|
@@ -808,7 +863,8 @@ export class ZLinkRouteReceiveLoop {
|
|
|
808
863
|
},
|
|
809
864
|
signal?: AbortSignal,
|
|
810
865
|
infrastructureChecked = false,
|
|
811
|
-
releaseRawReceive?: () => void
|
|
866
|
+
releaseRawReceive?: () => void,
|
|
867
|
+
receivedAt: Date = this.receivedAtClock()
|
|
812
868
|
): Promise<void> {
|
|
813
869
|
let closeReceived = true;
|
|
814
870
|
try {
|
|
@@ -817,7 +873,8 @@ export class ZLinkRouteReceiveLoop {
|
|
|
817
873
|
this.router,
|
|
818
874
|
signal,
|
|
819
875
|
tryDecodeChannelHeader(received.parts, this.dispatcher.flowEnabled?.() ?? true),
|
|
820
|
-
infrastructureChecked
|
|
876
|
+
infrastructureChecked,
|
|
877
|
+
receivedAt
|
|
821
878
|
);
|
|
822
879
|
if (consumed === true) {
|
|
823
880
|
closeReceived = false;
|
|
@@ -104,7 +104,7 @@ export class ZLinkChannelRuntimeLifecycle {
|
|
|
104
104
|
private readonly receiveRoundRobin = new ZLinkReceiveRoundRobinCoordinator();
|
|
105
105
|
private readonly channelReceiveLoops: ZLinkChannelReceiveLoop[] = [];
|
|
106
106
|
private readonly subscriberReceiveLoops: ZLinkSubscriberReceiveLoop[] = [];
|
|
107
|
-
|
|
107
|
+
readonly manualFanoutSubscribers = new Map<string, ManualFanoutSubscriberState>();
|
|
108
108
|
private readonly manualFanoutSubscriberOwners = new Set<object>();
|
|
109
109
|
private readonly routeReceiveLoops: Array<{ stop(): Promise<void> }> = [];
|
|
110
110
|
private readonly meshChannelDispatchers = new Map<string, ZLinkChannelRequestDispatcher>();
|
|
@@ -664,7 +664,7 @@ export class ZLinkChannelRuntimeLifecycle {
|
|
|
664
664
|
return state;
|
|
665
665
|
}
|
|
666
666
|
|
|
667
|
-
|
|
667
|
+
requestManualFanoutConnect(
|
|
668
668
|
channelName: string,
|
|
669
669
|
endpoint: string,
|
|
670
670
|
taskRunner: ZLinkRuntimeTaskRunner,
|
|
@@ -156,7 +156,7 @@ export class ZLinkChannelSocketRegistry {
|
|
|
156
156
|
readonly lifecycleGeneration: bigint;
|
|
157
157
|
}
|
|
158
158
|
>();
|
|
159
|
-
|
|
159
|
+
readonly clientServerConnections = new Map<string, ClientServerPhysicalConnection>();
|
|
160
160
|
private readonly clientServerDiscovery = new ServiceDiscoveryRegistry();
|
|
161
161
|
private readonly clientServerReadyIdentities = new Map<
|
|
162
162
|
string,
|
|
@@ -1455,7 +1455,7 @@ export class ZLinkChannelSocketRegistry {
|
|
|
1455
1455
|
}
|
|
1456
1456
|
}
|
|
1457
1457
|
|
|
1458
|
-
|
|
1458
|
+
applyClientServerDescriptorUpdate(
|
|
1459
1459
|
connectionId: string,
|
|
1460
1460
|
connection: { readonly channelName: string; readonly physicalConnectionId: symbol },
|
|
1461
1461
|
admission: ZLinkClientServerAdmission
|
|
@@ -1518,7 +1518,7 @@ export class ZLinkChannelSocketRegistry {
|
|
|
1518
1518
|
this.clientServerLivenessTimer.unref();
|
|
1519
1519
|
}
|
|
1520
1520
|
|
|
1521
|
-
|
|
1521
|
+
drainSocketMonitors(): void {
|
|
1522
1522
|
for (const monitor of this.ownedResources) if ('drain' in monitor) monitor.drain();
|
|
1523
1523
|
}
|
|
1524
1524
|
|
|
@@ -574,7 +574,8 @@ export class ZLinkRuntimeMetrics {
|
|
|
574
574
|
startRelocation(
|
|
575
575
|
meshName: string,
|
|
576
576
|
objectKind: 'actor' | 'user_spot' | 'instance_spot',
|
|
577
|
-
policy: 'recreate' | 'snapshot'
|
|
577
|
+
policy: 'recreate' | 'snapshot',
|
|
578
|
+
onComplete?: (outcome: string) => void
|
|
578
579
|
): ZLinkRelocationMetricOperation {
|
|
579
580
|
const started = process.hrtime.bigint();
|
|
580
581
|
const startAttributes = { mesh_name: meshName, object_kind: objectKind, policy };
|
|
@@ -595,6 +596,7 @@ export class ZLinkRuntimeMetrics {
|
|
|
595
596
|
Number(process.hrtime.bigint() - started) / NANOSECONDS_PER_SECOND,
|
|
596
597
|
terminal
|
|
597
598
|
);
|
|
599
|
+
onComplete?.(outcome);
|
|
598
600
|
}
|
|
599
601
|
};
|
|
600
602
|
}
|
|
@@ -72,9 +72,9 @@ interface ZLinkSerialAdmissionLane {
|
|
|
72
72
|
* Application work carries the host permit through the queue until the handler starts.
|
|
73
73
|
*/
|
|
74
74
|
export class ZLinkSerialExecutionQueue {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
readonly application: ZLinkSerialAdmissionLane;
|
|
76
|
+
readonly lifecycle: ZLinkSerialAdmissionLane;
|
|
77
|
+
activeLifecycle?: ZLinkSerialWorkRecord<unknown>;
|
|
78
78
|
private activeRecord?: ZLinkSerialWorkRecord<unknown>;
|
|
79
79
|
/** The admitted node itself owns ready membership; no second readiness flag. */
|
|
80
80
|
private ownerMembership?: SerialWorkRecord<unknown>;
|
|
@@ -86,10 +86,10 @@ export class ZLinkSerialExecutionQueue {
|
|
|
86
86
|
private lifecycleDebt = false;
|
|
87
87
|
private claimStartedAt?: number;
|
|
88
88
|
private closed = false;
|
|
89
|
-
|
|
89
|
+
readonly idleWaiters: Array<() => void> = [];
|
|
90
90
|
|
|
91
91
|
constructor(
|
|
92
|
-
|
|
92
|
+
readonly executeRecord: (record: ZLinkSerialWorkRecord<unknown>) => Promise<void>,
|
|
93
93
|
options: ZLinkSerialSchedulerOptions = {},
|
|
94
94
|
private readonly sharedOwner?: ZLinkSerialExecutionQueue
|
|
95
95
|
) {
|
|
@@ -217,7 +217,7 @@ export class ZLinkSerialExecutionQueue {
|
|
|
217
217
|
return this.closed;
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
|
|
220
|
+
admit<T>(
|
|
221
221
|
operation: () => Promise<T> | T,
|
|
222
222
|
options: ZLinkSerialWorkOptions | undefined,
|
|
223
223
|
context?: unknown,
|
|
@@ -291,7 +291,7 @@ export class ZLinkSerialExecutionQueue {
|
|
|
291
291
|
return result;
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
-
|
|
294
|
+
scheduleDrain(): void {
|
|
295
295
|
if (this.sharedOwner !== undefined) {
|
|
296
296
|
if (this.activeRecord !== undefined) return;
|
|
297
297
|
// Ready membership in the existing owner queue is the only notification state.
|
|
@@ -320,7 +320,7 @@ export class ZLinkSerialExecutionQueue {
|
|
|
320
320
|
}
|
|
321
321
|
|
|
322
322
|
/** Notifications carry no payload, admission sequence, result Promise, or host permit. */
|
|
323
|
-
|
|
323
|
+
enqueueMailboxTurn(operation: () => void): void {
|
|
324
324
|
const entry: SerialWorkRecord<unknown> = {
|
|
325
325
|
acceptedSequence: 0n,
|
|
326
326
|
lane: 'application',
|
|
@@ -384,7 +384,7 @@ export class ZLinkSerialExecutionQueue {
|
|
|
384
384
|
});
|
|
385
385
|
}
|
|
386
386
|
|
|
387
|
-
|
|
387
|
+
async drain(): Promise<void> {
|
|
388
388
|
const consumer = this.consumer!;
|
|
389
389
|
if (consumer.running) return;
|
|
390
390
|
consumer.running = true;
|
|
@@ -461,7 +461,7 @@ export class ZLinkSerialExecutionQueue {
|
|
|
461
461
|
return record.preparationState !== 'pending' && record.preparationState !== 'canceling';
|
|
462
462
|
}
|
|
463
463
|
|
|
464
|
-
|
|
464
|
+
selectNext(): SerialWorkRecord<unknown> | undefined {
|
|
465
465
|
const lifecycleOwner = this.activeLifecycle?.context as ZLinkSerialLifecycleContext | undefined;
|
|
466
466
|
let applicationRecord: SerialWorkRecord<unknown> | undefined;
|
|
467
467
|
if (lifecycleOwner === undefined) {
|
|
@@ -488,7 +488,7 @@ export class ZLinkSerialExecutionQueue {
|
|
|
488
488
|
return applicationRecord!;
|
|
489
489
|
}
|
|
490
490
|
|
|
491
|
-
|
|
491
|
+
takeSelected(selected: SerialWorkRecord<unknown>): ZLinkSerialWorkRecord<unknown> {
|
|
492
492
|
const record =
|
|
493
493
|
selected.lane === 'lifecycle' ? this.takeLifecycle() : this.takeApplication(selected);
|
|
494
494
|
if (record !== selected) {
|
|
@@ -508,7 +508,7 @@ export class ZLinkSerialExecutionQueue {
|
|
|
508
508
|
return record;
|
|
509
509
|
}
|
|
510
510
|
|
|
511
|
-
|
|
511
|
+
takeApplication(selected: SerialWorkRecord<unknown>): ZLinkSerialWorkRecord<unknown> {
|
|
512
512
|
this.lifecycleStreak = 0;
|
|
513
513
|
this.lifecycleDebt = false;
|
|
514
514
|
if (this.application.records[0] === selected) return this.application.records.shift()!;
|
|
@@ -577,7 +577,7 @@ export class ZLinkSerialExecutionQueue {
|
|
|
577
577
|
return performance.now() - (this.claimStartedAt ?? performance.now()) >= this.ownerTimeBudget;
|
|
578
578
|
}
|
|
579
579
|
|
|
580
|
-
|
|
580
|
+
resolveIdleWaiters(): void {
|
|
581
581
|
for (let index = 0; index < this.idleWaiters.length; index++) this.idleWaiters[index]!();
|
|
582
582
|
this.idleWaiters.length = 0;
|
|
583
583
|
}
|
|
@@ -22,6 +22,7 @@ import type {
|
|
|
22
22
|
ZLinkRawRouterPort
|
|
23
23
|
} from '../backend/raw-binding-port';
|
|
24
24
|
import { submitToRequestResult } from '../messaging/submission-result';
|
|
25
|
+
import { copyPayloadBytes } from '../../contracts/Common/payload-slab';
|
|
25
26
|
import { RequestResult, SubmitResult, isZLinkBackendResultError } from '../backend/runtime-values';
|
|
26
27
|
import { enumWireRejectReason } from '../protocol/service_wire_codec.generated';
|
|
27
28
|
import { SERVICE_WIRE_PREFIX_SIZE } from './service-wire-binary-primitives';
|
|
@@ -46,9 +47,11 @@ import {
|
|
|
46
47
|
SERVICE_WIRE_MAGIC,
|
|
47
48
|
SERVICE_WIRE_MAJOR,
|
|
48
49
|
ServiceWireCommand,
|
|
49
|
-
ServiceWireFrameworkErrorCode
|
|
50
|
+
ServiceWireFrameworkErrorCode,
|
|
51
|
+
recoverRequestCorrelation
|
|
50
52
|
} from './service-wire-constants.generated';
|
|
51
53
|
import {
|
|
54
|
+
decodeApplicationPayload,
|
|
52
55
|
decodeApplicationPayloadView,
|
|
53
56
|
decodeChannelRequestHeader,
|
|
54
57
|
decodeChannelSendHeader,
|
|
@@ -204,7 +207,7 @@ export class RawServiceMeshRuntime {
|
|
|
204
207
|
private readonly releaseOperations: () => void;
|
|
205
208
|
|
|
206
209
|
private readonly operations: OperationRegistry<RawServiceRequestResult, number>;
|
|
207
|
-
|
|
210
|
+
readonly expectedPeers = new Map<
|
|
208
211
|
string,
|
|
209
212
|
{
|
|
210
213
|
readonly meshName: string;
|
|
@@ -221,7 +224,7 @@ export class RawServiceMeshRuntime {
|
|
|
221
224
|
* The last observed Core selected route of each RID (Core ROUTER §10.1):
|
|
222
225
|
* RID -> route generation. Only `observeSelectedRoutes` replaces it.
|
|
223
226
|
*/
|
|
224
|
-
|
|
227
|
+
selectedRoutes = new Map<string, bigint>();
|
|
225
228
|
private connectionAttempts: readonly ConnectionAttempt[] = [];
|
|
226
229
|
private readonly bindingPort: ZLinkRawBindingPort;
|
|
227
230
|
private readonly applicationJobQueue: ApplicationJobQueuePort;
|
|
@@ -231,7 +234,7 @@ export class RawServiceMeshRuntime {
|
|
|
231
234
|
private receiveAcquisition?: Promise<ApplicationJobPermitPort>;
|
|
232
235
|
private receivePermit?: ApplicationJobPermitPort;
|
|
233
236
|
private receiveRotation?: ApplicationJobReceiveRotationPort;
|
|
234
|
-
|
|
237
|
+
readonly controlSends = new Map<string, ControlSendState>();
|
|
235
238
|
private infrastructureFailure?: { readonly error: unknown };
|
|
236
239
|
private readonly onReceiveReady?: () => void;
|
|
237
240
|
private readonly infrastructureTaskRunner?: RawServiceMeshRuntimeOptions['infrastructureTaskRunner'];
|
|
@@ -242,7 +245,7 @@ export class RawServiceMeshRuntime {
|
|
|
242
245
|
private readonly resolveAdvertisedEndpoint?: RawServiceMeshRuntimeOptions['resolveAdvertisedEndpoint'];
|
|
243
246
|
private descriptor: ServiceNodeDescriptor;
|
|
244
247
|
private host?: ZLinkRawHostPort;
|
|
245
|
-
|
|
248
|
+
router?: ZLinkRawRouterPort;
|
|
246
249
|
private nextCorrelation = 1n;
|
|
247
250
|
private serviceIngress?: RawServiceIngressHandler;
|
|
248
251
|
private serviceIngressAccepts?: (command: number) => boolean;
|
|
@@ -1189,7 +1192,7 @@ export class RawServiceMeshRuntime {
|
|
|
1189
1192
|
}
|
|
1190
1193
|
}
|
|
1191
1194
|
|
|
1192
|
-
|
|
1195
|
+
reportProtocolError(
|
|
1193
1196
|
received: import('../backend/node/node-raw-binding-port').ZLinkRawReceivedRecord
|
|
1194
1197
|
): void {
|
|
1195
1198
|
const request = received.requestSeq !== undefined;
|
|
@@ -1206,32 +1209,19 @@ export class RawServiceMeshRuntime {
|
|
|
1206
1209
|
received: import('../backend/node/node-raw-binding-port').ZLinkRawReceivedRecord
|
|
1207
1210
|
): boolean {
|
|
1208
1211
|
if (received.requestSeq === undefined || received.parts.length === 0) return false;
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
encodeReplyHeader(
|
|
1220
|
-
correlation,
|
|
1221
|
-
RequestResult.ProtocolError,
|
|
1222
|
-
ServiceWireFrameworkErrorCode.requestProtocolError
|
|
1223
|
-
)
|
|
1224
|
-
];
|
|
1225
|
-
if (received.reply === undefined) return false;
|
|
1226
|
-
received.reply(reply);
|
|
1227
|
-
return true;
|
|
1228
|
-
} catch (error) {
|
|
1229
|
-
if (error instanceof ServiceWireProtocolError) return false;
|
|
1230
|
-
throw error;
|
|
1231
|
-
}
|
|
1212
|
+
const correlation = recoverRequestCorrelation(received.parts[0]!);
|
|
1213
|
+
if (correlation === undefined || received.reply === undefined) return false;
|
|
1214
|
+
received.reply([
|
|
1215
|
+
encodeReplyHeader(
|
|
1216
|
+
correlation,
|
|
1217
|
+
RequestResult.ProtocolError,
|
|
1218
|
+
ServiceWireFrameworkErrorCode.requestProtocolError
|
|
1219
|
+
)
|
|
1220
|
+
]);
|
|
1221
|
+
return true;
|
|
1232
1222
|
}
|
|
1233
1223
|
|
|
1234
|
-
|
|
1224
|
+
processReceived(
|
|
1235
1225
|
received: ZLinkRawReceivedRecord,
|
|
1236
1226
|
nowMs: number,
|
|
1237
1227
|
applicationJobOwner: ApplicationIngressRecordOwner
|
|
@@ -1604,11 +1594,24 @@ export class RawServiceMeshRuntime {
|
|
|
1604
1594
|
this.submitControl(probe.nodeRoutingId, parts)
|
|
1605
1595
|
);
|
|
1606
1596
|
}
|
|
1597
|
+
const failures: unknown[] = [];
|
|
1607
1598
|
for (const nodeRoutingId of result.timedOutNodes) {
|
|
1608
1599
|
const peer = this.topology.peer(nodeRoutingId);
|
|
1609
1600
|
if (peer === undefined) continue;
|
|
1610
|
-
|
|
1601
|
+
try {
|
|
1602
|
+
this.removePeer(peer, () => {
|
|
1603
|
+
try {
|
|
1604
|
+
this.requireStarted().disconnectRid!(nodeRoutingId);
|
|
1605
|
+
} catch (error) {
|
|
1606
|
+
failures.push(error);
|
|
1607
|
+
}
|
|
1608
|
+
});
|
|
1609
|
+
} catch (error) {
|
|
1610
|
+
failures.push(error);
|
|
1611
|
+
}
|
|
1611
1612
|
}
|
|
1613
|
+
if (failures.length === 1) throw failures[0];
|
|
1614
|
+
if (failures.length > 1) throw new AggregateError(failures, 'Liveness peer cleanup failed.');
|
|
1612
1615
|
return result;
|
|
1613
1616
|
}
|
|
1614
1617
|
|
|
@@ -1698,7 +1701,7 @@ export class RawServiceMeshRuntime {
|
|
|
1698
1701
|
channelName === undefined
|
|
1699
1702
|
? encodeNodeRequestHeader(correlation)
|
|
1700
1703
|
: encodeChannelRequestHeader(correlation, channelName);
|
|
1701
|
-
|
|
1704
|
+
let encodedPayload = this.applicationFrame(payload);
|
|
1702
1705
|
let selectedTargetNodeRoutingId = targetNodeRoutingId;
|
|
1703
1706
|
if (
|
|
1704
1707
|
selectedTargetNodeRoutingId !== this.descriptor.nodeRoutingId &&
|
|
@@ -1726,6 +1729,7 @@ export class RawServiceMeshRuntime {
|
|
|
1726
1729
|
}
|
|
1727
1730
|
}
|
|
1728
1731
|
if (selectedTargetNodeRoutingId === this.descriptor.nodeRoutingId) {
|
|
1732
|
+
encodedPayload = copyPayloadBytes(encodedPayload);
|
|
1729
1733
|
// The local admission path aborts its capacity wait on the terminal
|
|
1730
1734
|
// Promise, so a local request always keeps the Promise entry.
|
|
1731
1735
|
const pending =
|
|
@@ -1916,10 +1920,10 @@ export class RawServiceMeshRuntime {
|
|
|
1916
1920
|
}
|
|
1917
1921
|
|
|
1918
1922
|
private applicationPayload(payload: ServiceApplicationPayloadInput): ServiceApplicationPayload {
|
|
1919
|
-
return Buffer.isBuffer(payload) ?
|
|
1923
|
+
return Buffer.isBuffer(payload) ? decodeApplicationPayload(payload) : payload;
|
|
1920
1924
|
}
|
|
1921
1925
|
|
|
1922
|
-
|
|
1926
|
+
admitPeer(
|
|
1923
1927
|
descriptor: ServiceNodeDescriptor,
|
|
1924
1928
|
connectionId: string | bigint,
|
|
1925
1929
|
nowMs: number,
|
|
@@ -2021,10 +2025,7 @@ export class RawServiceMeshRuntime {
|
|
|
2021
2025
|
return this.router;
|
|
2022
2026
|
}
|
|
2023
2027
|
|
|
2024
|
-
|
|
2025
|
-
targetNodeRoutingId: string,
|
|
2026
|
-
parts: readonly Uint8Array[]
|
|
2027
|
-
): Promise<boolean> {
|
|
2028
|
+
async sendControl(targetNodeRoutingId: string, parts: readonly Uint8Array[]): Promise<boolean> {
|
|
2028
2029
|
return this.startControlSend(targetNodeRoutingId, decodeHeader(parts[0]!).command, () =>
|
|
2029
2030
|
this.submitControl(targetNodeRoutingId, parts)
|
|
2030
2031
|
);
|
|
@@ -2044,7 +2045,7 @@ export class RawServiceMeshRuntime {
|
|
|
2044
2045
|
);
|
|
2045
2046
|
}
|
|
2046
2047
|
|
|
2047
|
-
|
|
2048
|
+
startControlSend(
|
|
2048
2049
|
target: string,
|
|
2049
2050
|
command: number,
|
|
2050
2051
|
attempt: () => boolean | Promise<boolean>,
|
|
@@ -60,7 +60,7 @@ const NO_LIVENESS_WORK: ServiceLivenessTick = Object.freeze({
|
|
|
60
60
|
});
|
|
61
61
|
|
|
62
62
|
export class ServiceLivenessRegistry {
|
|
63
|
-
|
|
63
|
+
readonly peers = new Map<string, ServiceLivenessConnection>();
|
|
64
64
|
private nextProbeId = 1n;
|
|
65
65
|
/**
|
|
66
66
|
* The earliest probe or timeout among admitted peers. Received traffic only
|
|
@@ -9,6 +9,7 @@ export interface ServiceMailboxDispatchOwner {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export interface ServiceMailboxRecord {
|
|
12
|
+
receivedAt?: Date;
|
|
12
13
|
readonly sourcePreparationOwner?: ServiceMailboxDispatchOwner;
|
|
13
14
|
readonly ingress?: RawServiceIngressRecord;
|
|
14
15
|
readonly owner: string;
|
|
@@ -82,7 +83,10 @@ export class ServiceMailbox {
|
|
|
82
83
|
private nextRelocationSerial = 1n;
|
|
83
84
|
private closed = false;
|
|
84
85
|
|
|
85
|
-
constructor(
|
|
86
|
+
constructor(
|
|
87
|
+
private readonly onReady?: (domain: ServiceMailboxDomain) => void,
|
|
88
|
+
private readonly receivedAtClock: () => Date = () => new Date()
|
|
89
|
+
) {
|
|
86
90
|
// Host ApplicationJobQueue permits own ordinary-record admission. The
|
|
87
91
|
// Framework-owned payload lifetime does not retain Core HWM credit. A
|
|
88
92
|
// second mailbox cap would reject already-admitted work before the shared
|
|
@@ -105,6 +109,7 @@ export class ServiceMailbox {
|
|
|
105
109
|
const target = this.domain(record.domain);
|
|
106
110
|
const bytes = retainedBytes(record);
|
|
107
111
|
if (this.closed) return false;
|
|
112
|
+
record.receivedAt ??= this.receivedAtClock();
|
|
108
113
|
if (record.domain === 'application') {
|
|
109
114
|
if (this.relocatedOwners.has(record.owner)) return false;
|
|
110
115
|
const relocation = this.relocationSeals.get(record.owner);
|
|
@@ -253,6 +253,7 @@ export interface ZLinkMessageFollowOrigin {
|
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
export interface ReceiveRecord {
|
|
256
|
+
readonly receivedAt?: Date;
|
|
256
257
|
/** Resolve record prerequisites in owner order, outside an application handler turn. */
|
|
257
258
|
readonly prepareDispatch?: (
|
|
258
259
|
this: ReceiveRecord,
|
|
@@ -276,6 +277,7 @@ export interface ReceiveRecord {
|
|
|
276
277
|
readonly kindData: ReceiveKindData | null;
|
|
277
278
|
readonly terminalResult: number;
|
|
278
279
|
readonly failureErrno: number;
|
|
280
|
+
readonly failureMessage?: string;
|
|
279
281
|
readonly parts: Message[];
|
|
280
282
|
/** Returns whether the local operation can still accept a lifecycle reply. */
|
|
281
283
|
readonly isPending?: () => boolean;
|
|
@@ -299,7 +301,11 @@ export interface ReceiveRecord {
|
|
|
299
301
|
replyContentType?: string
|
|
300
302
|
): SubmitResult;
|
|
301
303
|
/** Emits a typed command-20 terminal for a lifecycle request before admission. */
|
|
302
|
-
replyFailure?(
|
|
304
|
+
replyFailure?(
|
|
305
|
+
terminalResult: number,
|
|
306
|
+
failureCode: number,
|
|
307
|
+
tail?: import('./service-stateful-wire-codec').ServiceStatefulReplyTail
|
|
308
|
+
): SubmitResult;
|
|
303
309
|
}
|
|
304
310
|
|
|
305
311
|
export interface ClaimReceiveResult {
|