@zlink-systems/framework 0.29.0 → 0.30.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/Builders.d.ts +1 -2
- package/dist/contracts/Configuration/Configs.d.ts +0 -5
- package/dist/contracts/Configuration/RegistrationBuilders.js +6 -4
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -6
- package/dist/contracts/Configuration/RegistrationValidators.js +4 -4
- package/dist/contracts/Configuration/index.d.ts +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.js +3 -1
- package/dist/runtime/actors/actor-handoff.d.ts +3 -2
- package/dist/runtime/actors/actor-handoff.js +9 -4
- package/dist/runtime/actors/actor-runtime-contracts.d.ts +1 -0
- package/dist/runtime/actors/index.d.ts +2 -0
- package/dist/runtime/actors/index.js +21 -6
- package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +3 -1
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +6 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +3 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.js +5 -0
- package/dist/runtime/application-jobs/contracts.d.ts +5 -1
- package/dist/runtime/backend/contracts/index.d.ts +10 -19
- package/dist/runtime/backend/mesh-completion-table.d.ts +6 -4
- package/dist/runtime/backend/mesh-completion-table.js +28 -18
- package/dist/runtime/backend/mesh-dispatch-pump.js +21 -25
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +6 -1
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +3 -3
- package/dist/runtime/backend/node/node-backend-adapter-support.js +24 -29
- package/dist/runtime/backend/node/node-mesh-backend-adapter.d.ts +1 -9
- package/dist/runtime/backend/node/node-mesh-backend-adapter.js +1 -1
- package/dist/runtime/backend/node/node-raw-binding-port.js +11 -6
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +10 -12
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +64 -98
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +10 -5
- package/dist/runtime/backend/raw-binding-port.d.ts +9 -2
- package/dist/runtime/channels/channel-receive-loops.js +3 -3
- package/dist/runtime/channels/channel-runtime-lifecycle.js +2 -1
- package/dist/runtime/channels/channel-socket-registry.d.ts +10 -3
- package/dist/runtime/channels/channel-socket-registry.js +59 -82
- package/dist/runtime/diagnostics/message-flow.d.ts +1 -0
- package/dist/runtime/diagnostics/message-flow.js +3 -3
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +15 -1
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +193 -64
- package/dist/runtime/foundation/service-liveness-registry.d.ts +20 -8
- package/dist/runtime/foundation/service-liveness-registry.js +57 -44
- package/dist/runtime/foundation/service-mailbox.d.ts +3 -0
- package/dist/runtime/foundation/service-mailbox.js +2 -1
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +7 -6
- package/dist/runtime/foundation/service-stateful-runtime.js +60 -41
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +5 -2
- package/dist/runtime/foundation/service-stateful-wire-codec.js +43 -61
- package/dist/runtime/foundation/service-topology-registry.d.ts +5 -3
- package/dist/runtime/foundation/service-topology-registry.js +9 -4
- package/dist/runtime/handlers/handler-instance-scope.js +1 -1
- package/dist/runtime/host/actor-packet-relay.js +7 -7
- package/dist/runtime/host/actor-placement-coordinator.d.ts +2 -1
- package/dist/runtime/host/actor-placement-coordinator.js +2 -1
- package/dist/runtime/host/actor-runtime-options-factory.d.ts +2 -1
- package/dist/runtime/host/actor-runtime-options-factory.js +2 -1
- package/dist/runtime/host/application-job-queue.d.ts +11 -4
- package/dist/runtime/host/application-job-queue.js +66 -10
- package/dist/runtime/host/entry-actor-runtime.js +1 -1
- package/dist/runtime/host/index.d.ts +1 -1
- package/dist/runtime/host/index.js +18 -13
- package/dist/runtime/host/instance-activation-authority.d.ts +2 -1
- package/dist/runtime/host/instance-activation-authority.js +89 -25
- package/dist/runtime/host/service-relocation-host-runtime.js +2 -2
- package/dist/runtime/host/spot-address-transport.d.ts +1 -0
- package/dist/runtime/host/spot-address-transport.js +25 -12
- package/dist/runtime/host/spot-runtime-options-factory.js +2 -2
- package/dist/runtime/host/user-spot-creation-coordinator.d.ts +1 -0
- package/dist/runtime/host/user-spot-creation-coordinator.js +1 -0
- package/dist/runtime/locations/domain-store-contract.d.ts +3 -2
- package/dist/runtime/locations/in-memory-authority-store.d.ts +5 -2
- package/dist/runtime/locations/in-memory-authority-store.js +107 -14
- package/dist/runtime/locations/in-memory-location-store.d.ts +3 -3
- package/dist/runtime/locations/in-memory-location-store.js +31 -13
- package/dist/runtime/locations/internal-location-contracts.d.ts +8 -0
- package/dist/runtime/locations/location-store-repository.d.ts +4 -2
- package/dist/runtime/locations/location-store-repository.js +209 -33
- package/dist/runtime/locations/resolvers.d.ts +2 -1
- package/dist/runtime/locations/resolvers.js +10 -1
- package/dist/runtime/messaging/submission-result.d.ts +1 -1
- package/dist/runtime/messaging/submission-result.js +2 -2
- package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +2 -0
- package/dist/runtime/spots/index.d.ts +4 -3
- package/dist/runtime/spots/index.js +14 -14
- package/dist/runtime/spots/spot-activation.d.ts +2 -1
- package/dist/runtime/spots/spot-activation.js +4 -4
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +2 -1
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +11 -10
- package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +4 -1
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +7 -5
- package/dist/runtime/spots/spot-actor-packet-drain.js +2 -0
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -0
- package/dist/runtime/spots/spot-entry-activation.d.ts +1 -0
- package/dist/runtime/spots/spot-entry-activation.js +6 -1
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +3 -1
- package/dist/runtime/spots/spot-node-runtime-manager.js +10 -11
- package/dist/runtime/spots/spot-routing-internal.d.ts +6 -0
- package/dist/runtime/spots/spot-runtime-ports.d.ts +2 -1
- package/dist/runtime/spots/spot-serial-executor.d.ts +1 -0
- package/dist/runtime/spots/spot-serial-executor.js +10 -1
- package/dist/runtime/streams/stream-session-runtime.js +1 -1
- package/package.json +3 -3
- package/src/contracts/Configuration/Builders.ts +1 -2
- package/src/contracts/Configuration/Configs.ts +0 -6
- package/src/contracts/Configuration/RegistrationBuilders.ts +8 -12
- package/src/contracts/Configuration/RegistrationTypes.ts +1 -6
- package/src/contracts/Configuration/RegistrationValidators.ts +9 -10
- package/src/contracts/Configuration/index.ts +1 -6
- package/src/internal.ts +1 -0
- package/src/runtime/actors/actor-handoff.ts +13 -4
- package/src/runtime/actors/actor-runtime-contracts.ts +4 -0
- package/src/runtime/actors/index.ts +77 -42
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +12 -2
- package/src/runtime/application-jobs/application-job-queue-scope.ts +6 -1
- package/src/runtime/application-jobs/contracts.ts +14 -1
- package/src/runtime/backend/contracts/index.ts +10 -18
- package/src/runtime/backend/mesh-completion-table.ts +36 -19
- package/src/runtime/backend/mesh-dispatch-pump.ts +19 -22
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +12 -5
- package/src/runtime/backend/node/node-backend-adapter-support.ts +31 -29
- package/src/runtime/backend/node/node-mesh-backend-adapter.ts +3 -10
- package/src/runtime/backend/node/node-raw-binding-port.ts +19 -10
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +81 -111
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +12 -8
- package/src/runtime/backend/raw-binding-port.ts +12 -2
- package/src/runtime/channels/channel-receive-loops.ts +3 -3
- package/src/runtime/channels/channel-runtime-lifecycle.ts +7 -1
- package/src/runtime/channels/channel-socket-registry.ts +84 -130
- package/src/runtime/diagnostics/message-flow.ts +1 -1
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +268 -70
- package/src/runtime/foundation/service-liveness-registry.ts +68 -59
- package/src/runtime/foundation/service-mailbox.ts +7 -1
- package/src/runtime/foundation/service-stateful-runtime.ts +109 -77
- package/src/runtime/foundation/service-stateful-wire-codec.ts +55 -79
- package/src/runtime/foundation/service-topology-registry.ts +13 -7
- package/src/runtime/handlers/handler-instance-scope.ts +2 -1
- package/src/runtime/host/actor-packet-relay.ts +7 -0
- package/src/runtime/host/actor-placement-coordinator.ts +8 -2
- package/src/runtime/host/actor-runtime-options-factory.ts +7 -0
- package/src/runtime/host/application-job-queue.ts +77 -10
- package/src/runtime/host/entry-actor-runtime.ts +1 -0
- package/src/runtime/host/index.ts +30 -7
- package/src/runtime/host/instance-activation-authority.ts +132 -27
- package/src/runtime/host/service-relocation-host-runtime.ts +2 -0
- package/src/runtime/host/spot-address-transport.ts +45 -22
- package/src/runtime/host/spot-runtime-options-factory.ts +2 -0
- package/src/runtime/host/user-spot-creation-coordinator.ts +8 -0
- package/src/runtime/locations/domain-store-contract.ts +6 -2
- package/src/runtime/locations/in-memory-authority-store.ts +153 -12
- package/src/runtime/locations/in-memory-location-store.ts +39 -13
- package/src/runtime/locations/internal-location-contracts.ts +10 -0
- package/src/runtime/locations/location-store-repository.ts +295 -36
- package/src/runtime/locations/resolvers.ts +25 -2
- package/src/runtime/messaging/submission-result.ts +2 -2
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +2 -0
- package/src/runtime/spots/index.ts +16 -0
- package/src/runtime/spots/spot-activation.ts +5 -0
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +13 -0
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +10 -0
- package/src/runtime/spots/spot-actor-packet-drain.ts +2 -0
- package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +1 -0
- package/src/runtime/spots/spot-entry-activation.ts +7 -0
- package/src/runtime/spots/spot-node-runtime-manager.ts +14 -12
- package/src/runtime/spots/spot-routing-internal.ts +14 -0
- package/src/runtime/spots/spot-runtime-ports.ts +2 -0
- package/src/runtime/spots/spot-serial-executor.ts +10 -4
- package/src/runtime/streams/stream-session-runtime.ts +1 -1
package/src/internal.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** Test and companion-package integration surface. It is not exported by package.json. */
|
|
2
2
|
export * from './index';
|
|
3
|
+
export { requireValidSendTimeoutMs } from './contracts/Configuration/SendTimeoutValidation';
|
|
3
4
|
export * from './runtime/diagnostics';
|
|
4
5
|
export * from './runtime/host';
|
|
5
6
|
export * from './runtime/admission';
|
|
@@ -3,6 +3,7 @@ import { type ActorRef, type RoutingId, ZLinkFrameworkException } from '../../co
|
|
|
3
3
|
import type { Message } from '../../contracts/Common/Message';
|
|
4
4
|
import { zlinkDefaultLocationOptions } from '../../contracts/Locations/Options';
|
|
5
5
|
import { releaseApplicationJobPermitForDurableHandoff } from '../application-jobs/application-job-queue-scope';
|
|
6
|
+
import type { ApplicationJobOrigin } from '../application-jobs/contracts';
|
|
6
7
|
import { ZLinkBufferMessage as RuntimeMessage } from '../backend/runtime-message';
|
|
7
8
|
import {
|
|
8
9
|
MessageFollowSuppressionRegistry,
|
|
@@ -108,7 +109,8 @@ export interface ZLinkActorHandoffPreparedReplayAdmission {
|
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
export type ZLinkActorHandoffReplayPreparation = (
|
|
111
|
-
signal: AbortSignal
|
|
112
|
+
signal: AbortSignal,
|
|
113
|
+
origin: ApplicationJobOrigin
|
|
112
114
|
) => Promise<ZLinkActorHandoffPreparedReplayAdmission>;
|
|
113
115
|
|
|
114
116
|
export interface ZLinkActorHandoffPrefixAdmission {
|
|
@@ -137,6 +139,7 @@ export type ZLinkActorHandoffPrefixQueue = (
|
|
|
137
139
|
) => ZLinkActorHandoffPrefixAdmission;
|
|
138
140
|
|
|
139
141
|
interface PendingPacket {
|
|
142
|
+
readonly origin: ApplicationJobOrigin;
|
|
140
143
|
readonly packet: ZLinkActorHandoffPacket;
|
|
141
144
|
readonly resolve?: (value: unknown) => void;
|
|
142
145
|
readonly reject?: (reason: unknown) => void;
|
|
@@ -554,7 +557,7 @@ export class ZLinkActorHandoffCoordinator {
|
|
|
554
557
|
try {
|
|
555
558
|
await waitForHandoffReplayStart(release.start, signal);
|
|
556
559
|
if (release.preparation !== undefined) {
|
|
557
|
-
const next = await release.preparation(signal);
|
|
560
|
+
const next = await release.preparation(signal, pending.origin);
|
|
558
561
|
if (signal.aborted) {
|
|
559
562
|
next.cancel();
|
|
560
563
|
throw signal.reason;
|
|
@@ -765,6 +768,7 @@ export class ZLinkActorHandoffCoordinator {
|
|
|
765
768
|
}
|
|
766
769
|
|
|
767
770
|
capture(
|
|
771
|
+
origin: ApplicationJobOrigin,
|
|
768
772
|
actorId: string,
|
|
769
773
|
parts: readonly Message[],
|
|
770
774
|
returnResponse = false,
|
|
@@ -823,7 +827,7 @@ export class ZLinkActorHandoffCoordinator {
|
|
|
823
827
|
this.reportRequestFrame(actorId, packet);
|
|
824
828
|
}
|
|
825
829
|
if (!returnResponse) {
|
|
826
|
-
handoff.pending.push({ packet });
|
|
830
|
+
handoff.pending.push({ packet, origin });
|
|
827
831
|
// The durable handoff now owns this record. Return the ingress permit
|
|
828
832
|
// before waiting for a later replay, which must acquire its own fresh
|
|
829
833
|
// application-job permit.
|
|
@@ -859,7 +863,12 @@ export class ZLinkActorHandoffCoordinator {
|
|
|
859
863
|
}, RELOCATION_REPLY_RETENTION_MS);
|
|
860
864
|
route.deadline.unref();
|
|
861
865
|
this.replyRoutes.set(source.replyRouteId, route);
|
|
862
|
-
handoff.pending.push({
|
|
866
|
+
handoff.pending.push({
|
|
867
|
+
packet: requestPacket,
|
|
868
|
+
origin,
|
|
869
|
+
resolve,
|
|
870
|
+
reject
|
|
871
|
+
});
|
|
863
872
|
});
|
|
864
873
|
releaseApplicationJobPermitForDurableHandoff();
|
|
865
874
|
if (handoff.prefixRelease !== undefined) {
|
|
@@ -49,6 +49,10 @@ export interface ZLinkActorManagerOptions {
|
|
|
49
49
|
signal?: AbortSignal
|
|
50
50
|
) => Promise<ZLinkActorCreateResponse | undefined>;
|
|
51
51
|
readonly actorDestroyedCleanup?: (actorId: string) => void;
|
|
52
|
+
readonly terminateActorActivation?: (
|
|
53
|
+
actor: ZLinkActor,
|
|
54
|
+
terminal: () => Promise<void>
|
|
55
|
+
) => Promise<void>;
|
|
52
56
|
readonly publishActorAuthority?: (
|
|
53
57
|
actorType: string,
|
|
54
58
|
actorRef: ActorRef,
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
wireReplyFailureException
|
|
30
30
|
} from '../framework-errors-internal';
|
|
31
31
|
import { disposeLifecycleHandlers } from '../handlers/handler-instance-scope';
|
|
32
|
+
import { currentZLinkActorExecution } from './actor-execution-context';
|
|
32
33
|
import { encodeFrameworkPayloadMessage } from '../messaging/payload-codec';
|
|
33
34
|
import { ZLinkActorCreationCoordinator, type ZLinkActorCreateRequest } from './actor-creation';
|
|
34
35
|
import type { ZLinkActorManagerOptions } from './actor-runtime-contracts';
|
|
@@ -217,34 +218,43 @@ export class DefaultZLinkActorManager implements ZLinkActorManager {
|
|
|
217
218
|
const completions = this.options.nativeActorCompletionTableProvider?.();
|
|
218
219
|
const entryNodeRid = state.entryNodeRid ?? current.nodeRid;
|
|
219
220
|
if (node === undefined || completions === undefined) return false;
|
|
220
|
-
const destroyTask = state.getOrStartDestroy(entryNodeRid,
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
221
|
+
const destroyTask = state.getOrStartDestroy(entryNodeRid, (nativeRef) =>
|
|
222
|
+
this.terminateActor(state, async () => {
|
|
223
|
+
if (nativeRef !== undefined) {
|
|
224
|
+
const completion = await completions.submit(
|
|
225
|
+
() => node.destroyActor(nativeRef, 0),
|
|
226
|
+
signal
|
|
227
|
+
);
|
|
228
|
+
try {
|
|
229
|
+
if (completion.terminalResult !== 0 || completion.failureErrno !== 0) {
|
|
230
|
+
// Classify the (terminal, fine) pair via the shared translator
|
|
231
|
+
// (spec 32-framework-error-model:83-118, 99-108) instead of
|
|
232
|
+
// collapsing every destroy failure to NotFound; genuine
|
|
233
|
+
// route-not-found fine codes still yield NotFound through the
|
|
234
|
+
// shared table.
|
|
235
|
+
throw wireReplyFailureException(
|
|
236
|
+
completion.terminalResult,
|
|
237
|
+
completion.failureErrno,
|
|
238
|
+
`Actor '${actor.actorId}' destroy failed with result '${completion.terminalResult}' and errno '${completion.failureErrno}'.`
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
} finally {
|
|
242
|
+
closeMeshCompletion(completion);
|
|
235
243
|
}
|
|
236
|
-
|
|
237
|
-
closeMeshCompletion(completion);
|
|
244
|
+
state.markNativeActorDestroyed(nativeRef);
|
|
238
245
|
}
|
|
239
|
-
state.
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
+
if (state.actorType !== undefined && state.ownsLocation) {
|
|
247
|
+
await this.options.locationLifecycle?.releaseActor(
|
|
248
|
+
state.actorType,
|
|
249
|
+
actor.actorId,
|
|
250
|
+
current
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
await this.finalizeDestroyedActor(actor.actorId, state);
|
|
254
|
+
})
|
|
255
|
+
);
|
|
246
256
|
try {
|
|
247
|
-
await destroyTask;
|
|
257
|
+
await this.awaitActorDestroy(state, destroyTask);
|
|
248
258
|
} catch (error) {
|
|
249
259
|
state.clearFailedDestroy(destroyTask);
|
|
250
260
|
throw error;
|
|
@@ -548,6 +558,29 @@ export class DefaultZLinkActorManager implements ZLinkActorManager {
|
|
|
548
558
|
this.options.metrics?.change(METRIC_NAMES.ActorCount, -1);
|
|
549
559
|
}
|
|
550
560
|
}
|
|
561
|
+
|
|
562
|
+
private terminateActor(
|
|
563
|
+
state: ZLinkActorRuntimeState,
|
|
564
|
+
terminal: () => Promise<void>
|
|
565
|
+
): Promise<void> {
|
|
566
|
+
const actor = state.actor;
|
|
567
|
+
const completion =
|
|
568
|
+
actor === undefined || this.options.terminateActorActivation === undefined
|
|
569
|
+
? terminal()
|
|
570
|
+
: this.options.terminateActorActivation(actor, terminal);
|
|
571
|
+
return completion;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
private awaitActorDestroy(
|
|
575
|
+
state: ZLinkActorRuntimeState,
|
|
576
|
+
completion: Promise<void>
|
|
577
|
+
): Promise<void> {
|
|
578
|
+
if (currentZLinkActorExecution()?.actorId === state.actorId) {
|
|
579
|
+
this.detachedTaskRunner.runDetached('Actor terminal cleanup', () => completion);
|
|
580
|
+
return Promise.resolve();
|
|
581
|
+
}
|
|
582
|
+
return completion;
|
|
583
|
+
}
|
|
551
584
|
async getOrCreateActor(
|
|
552
585
|
actorId: string,
|
|
553
586
|
actorType: string,
|
|
@@ -648,25 +681,27 @@ export class DefaultZLinkActorManager implements ZLinkActorManager {
|
|
|
648
681
|
`Actor '${actor.context.actorId}' must leave its current SPOT before destroy.`
|
|
649
682
|
);
|
|
650
683
|
}
|
|
651
|
-
const destroyTask = state.getOrStartDestroy(entryNodeRid,
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
684
|
+
const destroyTask = state.getOrStartDestroy(entryNodeRid, (actorRef) =>
|
|
685
|
+
this.terminateActor(state, async () => {
|
|
686
|
+
const destroyedActorRef =
|
|
687
|
+
actorRef === undefined ? undefined : toFrameworkActorRef(actorRef, state.meshName ?? '');
|
|
688
|
+
if (actorRef !== undefined) {
|
|
689
|
+
await node.destroyActor(actorRef, 0, destroySignal);
|
|
690
|
+
state.markNativeActorDestroyed(actorRef);
|
|
691
|
+
}
|
|
692
|
+
if (state.actorType !== undefined && state.ownsLocation) {
|
|
693
|
+
await this.options.locationLifecycle?.releaseActor(
|
|
694
|
+
state.actorType,
|
|
695
|
+
actor.context.actorId,
|
|
696
|
+
destroyedActorRef
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
await this.finalizeDestroyedActor(actor.context.actorId, state);
|
|
700
|
+
})
|
|
701
|
+
);
|
|
667
702
|
|
|
668
703
|
try {
|
|
669
|
-
await destroyTask;
|
|
704
|
+
await this.awaitActorDestroy(state, destroyTask);
|
|
670
705
|
} catch (error) {
|
|
671
706
|
state.clearFailedDestroy(destroyTask);
|
|
672
707
|
throw error;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ApplicationJobOrigin,
|
|
3
|
+
ApplicationJobPermitPort,
|
|
4
|
+
ApplicationJobQueuePort
|
|
5
|
+
} from './contracts';
|
|
2
6
|
|
|
3
7
|
export type ApplicationJobRecordDomain = 'application' | 'infrastructure';
|
|
4
8
|
|
|
@@ -85,6 +89,10 @@ export class ApplicationJobRecordLease implements ApplicationJobPermitPort {
|
|
|
85
89
|
private readonly permit: ApplicationJobPermitPort
|
|
86
90
|
) {}
|
|
87
91
|
|
|
92
|
+
get origin(): ApplicationJobOrigin {
|
|
93
|
+
return this.shared.origin;
|
|
94
|
+
}
|
|
95
|
+
|
|
88
96
|
markApplicationQueued(): void {
|
|
89
97
|
// The owner classifies and marks the child atomically when it is created;
|
|
90
98
|
// downstream dispatch must not mutate queue accounting a second time.
|
|
@@ -132,12 +140,14 @@ class SharedIngressRecordState {
|
|
|
132
140
|
private jobCount = 0;
|
|
133
141
|
private initialPermit?: ApplicationJobPermitPort;
|
|
134
142
|
private recordClosed = false;
|
|
143
|
+
readonly origin: ApplicationJobOrigin;
|
|
135
144
|
|
|
136
145
|
constructor(
|
|
137
146
|
private readonly queue: ApplicationJobQueuePort,
|
|
138
147
|
initialPermit: ApplicationJobPermitPort,
|
|
139
148
|
private readonly record: IngressRecordPort
|
|
140
149
|
) {
|
|
150
|
+
this.origin = initialPermit.origin;
|
|
141
151
|
this.initialPermit = initialPermit;
|
|
142
152
|
}
|
|
143
153
|
|
|
@@ -160,7 +170,7 @@ class SharedIngressRecordState {
|
|
|
160
170
|
}
|
|
161
171
|
|
|
162
172
|
acquirePermit(signal: AbortSignal): Promise<ApplicationJobPermitPort> {
|
|
163
|
-
return this.queue.acquire(signal);
|
|
173
|
+
return this.queue.acquire(signal, this.origin);
|
|
164
174
|
}
|
|
165
175
|
|
|
166
176
|
createJob(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
2
|
|
|
3
|
-
import type { ApplicationJobPermitPort } from './contracts';
|
|
3
|
+
import type { ApplicationJobOrigin, ApplicationJobPermitPort } from './contracts';
|
|
4
4
|
|
|
5
5
|
interface ApplicationJobPermitScope {
|
|
6
6
|
readonly permit: ApplicationJobPermitPort;
|
|
@@ -42,6 +42,11 @@ export function hasApplicationJobPermit(): boolean {
|
|
|
42
42
|
return applicationJobPermitScope.getStore() !== undefined;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
/** Keeps the ingress origin when a durable record later reacquires its permit. */
|
|
46
|
+
export function currentApplicationJobOrigin(): ApplicationJobOrigin {
|
|
47
|
+
return applicationJobPermitScope.getStore()!.permit.origin;
|
|
48
|
+
}
|
|
49
|
+
|
|
45
50
|
/** Re-enters the captured permit scope when a serial executor runs later. */
|
|
46
51
|
export function bindApplicationJobPermit<TResult, TArgument>(
|
|
47
52
|
callback: (argument?: TArgument) => Promise<TResult> | TResult
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
export type ApplicationJobOrigin = 'local' | 'remote';
|
|
2
|
+
|
|
1
3
|
export interface ApplicationJobPermitPort {
|
|
4
|
+
readonly origin: ApplicationJobOrigin;
|
|
2
5
|
markApplicationQueued(): void;
|
|
3
6
|
/** Transfers ingress-record cleanup to a detached exact-target handler turn. */
|
|
4
7
|
detachForHandlerTurn?(): void;
|
|
@@ -7,7 +10,17 @@ export interface ApplicationJobPermitPort {
|
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
export interface ApplicationJobQueuePort {
|
|
10
|
-
acquire(
|
|
13
|
+
acquire(
|
|
14
|
+
signal: AbortSignal | undefined,
|
|
15
|
+
origin: ApplicationJobOrigin
|
|
16
|
+
): Promise<ApplicationJobPermitPort>;
|
|
17
|
+
/** Returns a grant now, or registers one FIFO waiter that later calls resume. */
|
|
18
|
+
acquireOrResume(
|
|
19
|
+
resume: (permit: ApplicationJobPermitPort) => void,
|
|
20
|
+
reject: (reason: unknown) => void,
|
|
21
|
+
signal: AbortSignal | undefined,
|
|
22
|
+
origin: ApplicationJobOrigin
|
|
23
|
+
): ApplicationJobPermitPort | undefined;
|
|
11
24
|
registerReceiveFlowTarget?(
|
|
12
25
|
identity: object,
|
|
13
26
|
applyState: (state: 'running' | 'paused') => void,
|
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
ZLinkBackendReceived,
|
|
7
7
|
ZLinkBackendTopicMessage
|
|
8
8
|
} from '../runtime-values';
|
|
9
|
-
import type { CoreHwmBudgetSnapshot } from '@zlink-systems/zlink';
|
|
9
|
+
import type { CoreHwmBudgetSnapshot, ReceiveFlowState } from '@zlink-systems/zlink';
|
|
10
10
|
import { type ZLinkBackendRecvFlags, type ZLinkBackendSendFlags } from '../runtime-values';
|
|
11
11
|
export * from '../runtime-values';
|
|
12
12
|
type MessageLike = ZLinkBackendMessageLike;
|
|
@@ -27,6 +27,7 @@ import type {
|
|
|
27
27
|
import type { RoutingId } from '../../../contracts';
|
|
28
28
|
import type { ZLinkCoreHwmOptions } from '../../../contracts/Configuration';
|
|
29
29
|
import type { ZLinkSubmitResult } from '../../messaging/submission-result';
|
|
30
|
+
import type { ZLinkMeshCompletionHandler } from '../mesh-completion-table';
|
|
30
31
|
import type { Message } from '../../../contracts/Common/Message';
|
|
31
32
|
import type {
|
|
32
33
|
ServiceSpotMessageFollowSeal,
|
|
@@ -38,6 +39,7 @@ import type {
|
|
|
38
39
|
ServiceActorCreateRecord,
|
|
39
40
|
ServiceDirectSpotRouteFence,
|
|
40
41
|
ServiceInstanceRouteFence,
|
|
42
|
+
ServiceInstanceColdActivationTarget,
|
|
41
43
|
ServiceUserSpotCloseRecord,
|
|
42
44
|
ServiceUserSpotCreateRecord
|
|
43
45
|
} from '../../foundation/service-stateful-wire-codec';
|
|
@@ -112,26 +114,14 @@ export interface ZLinkBackendMeshNode {
|
|
|
112
114
|
selectObjectPlacement(stableType: string): ZLinkBackendObjectPlacement;
|
|
113
115
|
instanceSpotPlacementTypes?(): readonly string[];
|
|
114
116
|
sendToMissingInstanceSpot(
|
|
115
|
-
target:
|
|
116
|
-
readonly targetNodeRid: string;
|
|
117
|
-
readonly targetNodeGeneration: bigint;
|
|
118
|
-
readonly targetSpotId: string;
|
|
119
|
-
readonly stableType: string;
|
|
120
|
-
readonly descriptorVersion: string;
|
|
121
|
-
},
|
|
117
|
+
target: ServiceInstanceColdActivationTarget,
|
|
122
118
|
parts: ZLinkBackendMessageLike | readonly ZLinkBackendMessageLike[],
|
|
123
119
|
deadlineUnixMs: bigint,
|
|
124
120
|
sourceSpotId?: string,
|
|
125
121
|
metadata?: ReadonlyMap<string, string>
|
|
126
122
|
): Promise<SubmitResult>;
|
|
127
123
|
requestToMissingInstanceSpot(
|
|
128
|
-
target:
|
|
129
|
-
readonly targetNodeRid: string;
|
|
130
|
-
readonly targetNodeGeneration: bigint;
|
|
131
|
-
readonly targetSpotId: string;
|
|
132
|
-
readonly stableType: string;
|
|
133
|
-
readonly descriptorVersion: string;
|
|
134
|
-
},
|
|
124
|
+
target: ServiceInstanceColdActivationTarget,
|
|
135
125
|
parts: ZLinkBackendMessageLike | readonly ZLinkBackendMessageLike[],
|
|
136
126
|
deadlineUnixMs: bigint,
|
|
137
127
|
sourceSpotId?: string,
|
|
@@ -390,6 +380,7 @@ export interface ZLinkBackendMeshNode {
|
|
|
390
380
|
timeoutMs?: number
|
|
391
381
|
): MeshOperationId;
|
|
392
382
|
setReadyHandler(handler: (readyDomains: number) => number): void;
|
|
383
|
+
setCompletionHandler(handler: ZLinkMeshCompletionHandler): void;
|
|
393
384
|
createReadyBatch(capacity: number): ReadyBatch;
|
|
394
385
|
createReceiveBatch(messageCapacity: number, partCapacity: number): ReceiveBatch;
|
|
395
386
|
drainReady(
|
|
@@ -476,7 +467,6 @@ export interface ZLinkBackendSocket extends ZLinkBackendObject {
|
|
|
476
467
|
readonly lastEndpoint?: string;
|
|
477
468
|
bind(endpoint: string): void;
|
|
478
469
|
setChannelName(channelName: string): void;
|
|
479
|
-
setReceiveFlowState?(state: 0 | 1): void;
|
|
480
470
|
dispose(): Promise<void>;
|
|
481
471
|
}
|
|
482
472
|
|
|
@@ -486,7 +476,7 @@ export interface ZLinkBackendConnectableSocket extends ZLinkBackendSocket {
|
|
|
486
476
|
}
|
|
487
477
|
|
|
488
478
|
export interface ZLinkBackendDealerSocket extends ZLinkBackendConnectableSocket {
|
|
489
|
-
|
|
479
|
+
receiveAdmission?: import('../../foundation/service-liveness-registry').ServiceLivenessConnection;
|
|
490
480
|
setRoutingId(routingId: RoutingId): void;
|
|
491
481
|
peerWeight: number;
|
|
492
482
|
sendHighWaterMark: number;
|
|
@@ -515,7 +505,7 @@ export interface ZLinkBackendRequestOperation {
|
|
|
515
505
|
}
|
|
516
506
|
|
|
517
507
|
export interface ZLinkBackendRouterSocket extends ZLinkBackendConnectableSocket {
|
|
518
|
-
setReceiveFlowState(state:
|
|
508
|
+
setReceiveFlowState(state: ReceiveFlowState): void;
|
|
519
509
|
/** Enables the native probe handshake for manually configured routes. */
|
|
520
510
|
setProbe(enabled: boolean): void;
|
|
521
511
|
peerWeight: number;
|
|
@@ -549,6 +539,7 @@ export interface ZLinkBackendRouterSocket extends ZLinkBackendConnectableSocket
|
|
|
549
539
|
}
|
|
550
540
|
|
|
551
541
|
export interface ZLinkBackendPublisherSocket extends ZLinkBackendSocket {
|
|
542
|
+
lingerMs: number;
|
|
552
543
|
sendTimeoutMs: number;
|
|
553
544
|
sendHighWaterMark: number;
|
|
554
545
|
noDrop: boolean;
|
|
@@ -739,6 +730,7 @@ export interface ZLinkMeshBackendAdapter {
|
|
|
739
730
|
readonly trustProfile?: string;
|
|
740
731
|
readonly applicationJobQueue: import('../../application-jobs/contracts').ApplicationJobQueuePort;
|
|
741
732
|
readonly applicationJobReceiveFlowFailureSink?: (error: unknown) => void;
|
|
733
|
+
readonly infrastructureTaskRunner?: import('../../spots/spot-actor-join-dispatch').ZLinkDetachedTaskRunner;
|
|
742
734
|
readonly peerAdmissionSealed?: () => boolean;
|
|
743
735
|
}
|
|
744
736
|
): ZLinkBackendMeshNode;
|
|
@@ -27,8 +27,14 @@ interface PendingCompletion {
|
|
|
27
27
|
readonly removeAbort?: () => void;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
export type ZLinkMeshCompletionTerminal = Pick<ReceiveRecord, 'operationId' | 'terminalResult'>;
|
|
31
|
+
export type ZLinkMeshCompletionHandler = (
|
|
32
|
+
terminal: ZLinkMeshCompletionTerminal,
|
|
33
|
+
materialize: () => ReceiveRecord
|
|
34
|
+
) => void;
|
|
35
|
+
|
|
30
36
|
export class ZLinkMeshCompletionTable {
|
|
31
|
-
private readonly pending = new Map<string, PendingCompletion>();
|
|
37
|
+
private readonly pending = new Map<string | symbol, PendingCompletion>();
|
|
32
38
|
private disposed = false;
|
|
33
39
|
|
|
34
40
|
constructor(
|
|
@@ -36,10 +42,9 @@ export class ZLinkMeshCompletionTable {
|
|
|
36
42
|
) {}
|
|
37
43
|
|
|
38
44
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* arrived before their waiter.
|
|
45
|
+
* Reserves the dispatcher slot before transport submission. The backend
|
|
46
|
+
* observes native terminals through Promises, so identity binding finishes
|
|
47
|
+
* before the terminal callback can run, without an infrastructure pump.
|
|
43
48
|
*/
|
|
44
49
|
submit(operation: () => MeshOperationId, signal?: AbortSignal): Promise<ZLinkMeshCompletion> {
|
|
45
50
|
if (this.isDisposed()) {
|
|
@@ -50,17 +55,8 @@ export class ZLinkMeshCompletionTable {
|
|
|
50
55
|
signal.reason ?? new DOMException('The operation was aborted.', 'AbortError')
|
|
51
56
|
);
|
|
52
57
|
}
|
|
53
|
-
const operationId = operation();
|
|
54
|
-
// The backend submission callback can synchronously re-enter `dispose()`.
|
|
55
|
-
// TypeScript's control-flow analysis cannot observe mutation through it.
|
|
56
|
-
if (this.disposed) {
|
|
57
|
-
return Promise.reject(new Error('Mesh completion table is disposed.'));
|
|
58
|
-
}
|
|
59
|
-
const key = operationIdentityKey(operationId);
|
|
60
|
-
if (this.pending.has(key)) {
|
|
61
|
-
return Promise.reject(new Error(`Mesh operation '${key}' is already pending.`));
|
|
62
|
-
}
|
|
63
58
|
return new Promise((resolve, reject) => {
|
|
59
|
+
let key: string | symbol = Symbol();
|
|
64
60
|
const abort = () => {
|
|
65
61
|
this.pending.delete(key);
|
|
66
62
|
reject(signal?.reason ?? new DOMException('The operation was aborted.', 'AbortError'));
|
|
@@ -70,12 +66,29 @@ export class ZLinkMeshCompletionTable {
|
|
|
70
66
|
return;
|
|
71
67
|
}
|
|
72
68
|
signal?.addEventListener('abort', abort, { once: true });
|
|
73
|
-
|
|
69
|
+
const entry: PendingCompletion = {
|
|
74
70
|
resolve,
|
|
75
71
|
reject,
|
|
76
72
|
removeAbort:
|
|
77
73
|
signal === undefined ? undefined : () => signal.removeEventListener('abort', abort)
|
|
78
|
-
}
|
|
74
|
+
};
|
|
75
|
+
this.pending.set(key, entry);
|
|
76
|
+
try {
|
|
77
|
+
const operationId = operation();
|
|
78
|
+
// dispose/abort can consume the reserved slot during submission.
|
|
79
|
+
if (!this.pending.delete(key)) return;
|
|
80
|
+
key = operationIdentityKey(operationId);
|
|
81
|
+
if (this.pending.has(key)) {
|
|
82
|
+
throw new Error(`Mesh operation '${key}' is already pending.`);
|
|
83
|
+
}
|
|
84
|
+
this.pending.set(key, entry);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
// Remove only this submission's slot; a duplicate identity retains
|
|
87
|
+
// the original waiter.
|
|
88
|
+
if (this.pending.get(key) === entry) this.pending.delete(key);
|
|
89
|
+
entry.removeAbort?.();
|
|
90
|
+
reject(error);
|
|
91
|
+
}
|
|
79
92
|
});
|
|
80
93
|
}
|
|
81
94
|
|
|
@@ -83,7 +96,9 @@ export class ZLinkMeshCompletionTable {
|
|
|
83
96
|
return this.disposed;
|
|
84
97
|
}
|
|
85
98
|
|
|
86
|
-
complete(record: ReceiveRecord): void
|
|
99
|
+
complete(record: ReceiveRecord): void;
|
|
100
|
+
complete(record: ZLinkMeshCompletionTerminal, materialize: () => ReceiveRecord): void;
|
|
101
|
+
complete(record: ZLinkMeshCompletionTerminal, materialize?: () => ReceiveRecord): void {
|
|
87
102
|
const key = operationIdentityKey(record.operationId);
|
|
88
103
|
const pending = this.pending.get(key);
|
|
89
104
|
if (pending === undefined) {
|
|
@@ -97,7 +112,9 @@ export class ZLinkMeshCompletionTable {
|
|
|
97
112
|
this.pending.delete(key);
|
|
98
113
|
pending.removeAbort?.();
|
|
99
114
|
try {
|
|
100
|
-
pending.resolve(
|
|
115
|
+
pending.resolve(
|
|
116
|
+
retainCompletion(materialize === undefined ? (record as ReceiveRecord) : materialize())
|
|
117
|
+
);
|
|
101
118
|
} catch (error) {
|
|
102
119
|
pending.reject(error);
|
|
103
120
|
}
|
|
@@ -253,7 +253,7 @@ export class ZLinkMeshDispatchPump {
|
|
|
253
253
|
): Promise<boolean> {
|
|
254
254
|
let claimsDrained = 0;
|
|
255
255
|
try {
|
|
256
|
-
|
|
256
|
+
while (!this.disposed) {
|
|
257
257
|
if (claimBudget !== undefined && claimsDrained >= claimBudget) {
|
|
258
258
|
// Lifecycle work has priority, but a bounded turn lets application
|
|
259
259
|
// work make progress when lifecycle records keep arriving.
|
|
@@ -282,19 +282,18 @@ export class ZLinkMeshDispatchPump {
|
|
|
282
282
|
);
|
|
283
283
|
const capacity =
|
|
284
284
|
owner.ordinaryIngressPreAdmitted === true ? MESH_DISPATCH_RECEIVE_CAPACITY : 1;
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
// This owner keeps its claim while it drains, so its records stay in FIFO order.
|
|
285
|
+
let claimPermit =
|
|
286
|
+
owner.terminalCompletion === true ||
|
|
287
|
+
owner.ordinaryIngressPreAdmitted === true ||
|
|
288
|
+
domain === ReadyDomain.Infrastructure
|
|
289
|
+
? undefined
|
|
290
|
+
: await this.acquirePermit();
|
|
291
|
+
try {
|
|
292
|
+
if (this.capacityStop.signal.aborted) return;
|
|
293
|
+
ownerReceiveBatch.reset(capacity);
|
|
294
|
+
const received = claim.recvBatch(ownerReceiveBatch, ZLINK_BACKEND_RECV_DONT_WAIT);
|
|
295
|
+
if (received.ok) {
|
|
296
|
+
// The bounded batch stays in claim order until its records finish.
|
|
298
297
|
try {
|
|
299
298
|
for (const record of received.records) {
|
|
300
299
|
if (this.disposed) break;
|
|
@@ -327,8 +326,6 @@ export class ZLinkMeshDispatchPump {
|
|
|
327
326
|
if (permit === claimPermit) claimPermit = undefined;
|
|
328
327
|
await runWithApplicationJobPermit(permit, dispatch);
|
|
329
328
|
}
|
|
330
|
-
const yieldTurn = this.yieldIfNeeded();
|
|
331
|
-
if (yieldTurn !== undefined) await yieldTurn;
|
|
332
329
|
}
|
|
333
330
|
} finally {
|
|
334
331
|
// Batch ownership includes records whose dispatch never began,
|
|
@@ -338,14 +335,16 @@ export class ZLinkMeshDispatchPump {
|
|
|
338
335
|
record.releaseRetainedIngress?.();
|
|
339
336
|
}
|
|
340
337
|
}
|
|
341
|
-
} finally {
|
|
342
|
-
claimPermit?.releaseAfterInternalProcessing();
|
|
343
338
|
}
|
|
339
|
+
} finally {
|
|
340
|
+
claimPermit?.releaseAfterInternalProcessing();
|
|
344
341
|
}
|
|
345
342
|
} finally {
|
|
346
343
|
claim.release();
|
|
347
344
|
if (receiveBatch === undefined) ownerReceiveBatch?.close();
|
|
348
345
|
}
|
|
346
|
+
const yieldTurn = this.yieldIfNeeded();
|
|
347
|
+
if (yieldTurn !== undefined) await yieldTurn;
|
|
349
348
|
};
|
|
350
349
|
// An application worker drains the one owner it claimed. Infrastructure owners
|
|
351
350
|
// drain independently, so a suspended owner does not hold the other claims.
|
|
@@ -366,10 +365,8 @@ export class ZLinkMeshDispatchPump {
|
|
|
366
365
|
this.recordsSinceYield += 1;
|
|
367
366
|
const yieldTurn = this.yieldIfNeeded();
|
|
368
367
|
if (yieldTurn !== undefined) await yieldTurn;
|
|
369
|
-
if (!drained.hasResidue) {
|
|
370
|
-
return false;
|
|
371
|
-
}
|
|
372
368
|
}
|
|
369
|
+
return false;
|
|
373
370
|
} finally {
|
|
374
371
|
readyBatch.reset();
|
|
375
372
|
}
|
|
@@ -394,7 +391,7 @@ export class ZLinkMeshDispatchPump {
|
|
|
394
391
|
|
|
395
392
|
private async acquirePermit(): Promise<ApplicationJobPermitPort | undefined> {
|
|
396
393
|
try {
|
|
397
|
-
return await this.options.applicationJobQueue.acquire(this.capacityStop.signal);
|
|
394
|
+
return await this.options.applicationJobQueue.acquire(this.capacityStop.signal, 'remote');
|
|
398
395
|
} catch (error) {
|
|
399
396
|
if (this.disposed || this.capacityStop.signal.aborted) return undefined;
|
|
400
397
|
throw error;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
Context,
|
|
3
|
+
CoreHwmBudgetSnapshot,
|
|
4
|
+
ReceiveFlowState,
|
|
5
|
+
TopicMessage
|
|
6
|
+
} from '@zlink-systems/zlink';
|
|
2
7
|
import type { ZLinkCoreHwmOptions } from '../../../contracts/Configuration';
|
|
3
8
|
import type {
|
|
4
9
|
ZLinkBackendAdapterFactory,
|
|
@@ -60,10 +65,12 @@ class ZLinkNodeChannelBackendAdapter implements ZLinkChannelBackendAdapter {
|
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
createRouterSocket(context: ZLinkBackendContext): ZLinkBackendRouterSocket {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
const socket = zlink.createRouterSocket(asNodeContext(context));
|
|
69
|
+
const adapter = wrapSocket(socket, true);
|
|
70
|
+
adapter.setReceiveFlowState = (state: ReceiveFlowState): void => {
|
|
71
|
+
socket.setReceiveFlowState(state);
|
|
72
|
+
};
|
|
73
|
+
return adapter as unknown as ZLinkBackendRouterSocket;
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
createPublisherSocket(context: ZLinkBackendContext): ZLinkBackendPublisherSocket {
|