@zlink-systems/framework 0.30.0 → 0.30.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/LICENSE +150 -68
- package/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Actors/ZLinkActorClient.d.ts +2 -1
- package/dist/contracts/Channels/Calls.d.ts +2 -1
- package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
- package/dist/contracts/Handlers/Attributes.d.ts +5 -13
- package/dist/contracts/Handlers/Attributes.js +7 -11
- package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
- package/dist/contracts/Handlers/JsonContract.js +4 -153
- package/dist/contracts/Spots/Contracts.d.ts +2 -1
- package/dist/nest-integration.d.ts +1 -1
- package/dist/nest-integration.js +2 -1
- package/dist/runtime/actors/actor-client.d.ts +1 -1
- package/dist/runtime/actors/actor-client.js +14 -12
- package/dist/runtime/actors/actor-handoff.d.ts +1 -1
- package/dist/runtime/actors/actor-handoff.js +7 -4
- package/dist/runtime/actors/actor-join-relocation.d.ts +1 -0
- package/dist/runtime/actors/actor-local-native-join.js +9 -12
- package/dist/runtime/actors/actor-remote-wire.js +15 -0
- package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
- package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
- package/dist/runtime/actors/index.d.ts +2 -1
- package/dist/runtime/actors/index.js +18 -6
- package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
- package/dist/runtime/admission.d.ts +1 -1
- package/dist/runtime/admission.js +15 -5
- package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +6 -8
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +39 -22
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +2 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.js +37 -22
- package/dist/runtime/application-jobs/contracts.d.ts +10 -1
- package/dist/runtime/backend/contracts/index.d.ts +18 -9
- package/dist/runtime/backend/mesh-completion-table.d.ts +9 -1
- package/dist/runtime/backend/mesh-completion-table.js +149 -49
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +3 -0
- package/dist/runtime/backend/mesh-dispatch-pump.js +32 -11
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
- package/dist/runtime/backend/node/node-backend-adapter-support.js +16 -9
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
- package/dist/runtime/backend/node/node-raw-binding-port.js +42 -22
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +13 -5
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +69 -51
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +6 -6
- package/dist/runtime/backend/raw-binding-port.d.ts +2 -2
- package/dist/runtime/backend/runtime-message.d.ts +1 -0
- package/dist/runtime/backend/runtime-message.js +5 -0
- package/dist/runtime/backend/runtime-values.d.ts +1 -0
- package/dist/runtime/backend/runtime-values.js +2 -1
- package/dist/runtime/channels/channel-clients.d.ts +1 -0
- package/dist/runtime/channels/channel-clients.js +58 -21
- package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +3 -2
- package/dist/runtime/channels/channel-dispatch-pipeline.js +20 -11
- package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
- package/dist/runtime/channels/channel-dispatch-services.js +45 -0
- package/dist/runtime/channels/channel-dispatchers.d.ts +1 -1
- package/dist/runtime/channels/channel-dispatchers.js +27 -26
- package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
- package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
- package/dist/runtime/channels/channel-envelope.d.ts +1 -0
- package/dist/runtime/channels/channel-envelope.js +83 -8
- package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
- package/dist/runtime/channels/channel-outbound-operations.js +8 -8
- package/dist/runtime/channels/channel-runtime-manager.d.ts +6 -6
- package/dist/runtime/channels/channel-runtime-manager.js +12 -12
- package/dist/runtime/channels/channel-transports.d.ts +18 -15
- package/dist/runtime/channels/channel-transports.js +48 -31
- package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
- package/dist/runtime/channels/local-spot-route-transport.js +2 -1
- package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
- package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
- package/dist/runtime/channels/source-spot-router.d.ts +2 -2
- package/dist/runtime/channels/source-spot-router.js +4 -4
- package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
- package/dist/runtime/channels/spot-node-route-transport.js +4 -4
- package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
- package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
- package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
- package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
- package/dist/runtime/execution/serial-execution-queue.d.ts +1 -0
- package/dist/runtime/execution/serial-execution-queue.js +1 -0
- package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
- package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
- package/dist/runtime/foundation/durable-service-request.js +98 -0
- package/dist/runtime/foundation/operation-identity.d.ts +1 -0
- package/dist/runtime/foundation/operation-identity.js +5 -1
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +22 -5
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +356 -232
- package/dist/runtime/foundation/service-relocation-object-owner.d.ts +1 -0
- package/dist/runtime/foundation/service-relocation-object-owner.js +1 -0
- package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
- package/dist/runtime/foundation/service-relocation-runtime.js +13 -1
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -0
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +4 -4
- package/dist/runtime/foundation/service-stateful-runtime.js +44 -103
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +0 -5
- package/dist/runtime/foundation/service-topology-registry.d.ts +12 -2
- package/dist/runtime/foundation/service-topology-registry.js +61 -27
- package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +3 -3
- package/dist/runtime/foundation/service-wire-m6a-codec.js +36 -38
- package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
- package/dist/runtime/handlers/handler-instance-scope.js +54 -11
- package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
- package/dist/runtime/host/application-job-queue.d.ts +19 -7
- package/dist/runtime/host/application-job-queue.js +150 -42
- package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
- package/dist/runtime/host/entry-actor-runtime.js +3 -0
- package/dist/runtime/host/index.d.ts +7 -1
- package/dist/runtime/host/index.js +142 -118
- package/dist/runtime/host/remote-bound-session-relay.js +2 -18
- package/dist/runtime/host/route-mesh-runtime.js +1 -1
- package/dist/runtime/host/service-relocation-control.d.ts +1 -0
- package/dist/runtime/host/service-relocation-control.js +10 -4
- package/dist/runtime/host/service-relocation-host-runtime.d.ts +6 -8
- package/dist/runtime/host/service-relocation-host-runtime.js +213 -241
- package/dist/runtime/host/spot-address-transport.js +3 -2
- package/dist/runtime/host/spot-runtime-options-factory.js +1 -0
- package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
- package/dist/runtime/locations/actor-location-claims.js +34 -19
- package/dist/runtime/locations/lifecycle.d.ts +1 -2
- package/dist/runtime/locations/lifecycle.js +2 -5
- package/dist/runtime/locations/runtime.d.ts +1 -1
- package/dist/runtime/locations/runtime.js +24 -23
- package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
- package/dist/runtime/messaging/framework-json-v1.js +38 -294
- package/dist/runtime/messaging/packet-name.d.ts +1 -1
- package/dist/runtime/messaging/packet-name.js +8 -24
- package/dist/runtime/messaging/request-result.d.ts +2 -0
- package/dist/runtime/messaging/request-result.js +54 -0
- package/dist/runtime/messaging/submission-result.d.ts +1 -0
- package/dist/runtime/messaging/submission-result.js +5 -2
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +15 -0
- package/dist/runtime/protocol/service_wire_codec.generated.js +144 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +9 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +14 -1
- package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +7 -2
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +33 -19
- package/dist/runtime/spots/index.d.ts +3 -0
- package/dist/runtime/spots/index.js +9 -2
- package/dist/runtime/spots/spot-activation.d.ts +1 -0
- package/dist/runtime/spots/spot-activation.js +17 -8
- package/dist/runtime/spots/spot-entry-activation.js +6 -2
- package/dist/runtime/spots/spot-handler-registry.d.ts +3 -1
- package/dist/runtime/spots/spot-handler-registry.js +18 -8
- package/dist/runtime/spots/spot-node-autoconnect.js +4 -3
- package/dist/runtime/spots/spot-outbound.d.ts +3 -0
- package/dist/runtime/spots/spot-outbound.js +24 -15
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
- package/dist/runtime/spots/spot-runtime-ports.d.ts +1 -0
- package/dist/runtime/spots/spot-subscription-dispatch.js +0 -3
- package/dist/runtime/spots/spot-timer.js +1 -0
- package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
- package/dist/runtime/streams/stream-session-runtime.js +13 -27
- package/package.json +2 -2
- package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
- package/src/contracts/Channels/Calls.ts +2 -1
- package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
- package/src/contracts/Handlers/Attributes.ts +14 -21
- package/src/contracts/Handlers/JsonContract.ts +8 -216
- package/src/contracts/Spots/Contracts.ts +2 -1
- package/src/nest-integration.ts +1 -0
- package/src/runtime/actors/actor-client.ts +40 -16
- package/src/runtime/actors/actor-handoff.ts +9 -4
- package/src/runtime/actors/actor-join-relocation.ts +1 -0
- package/src/runtime/actors/actor-local-native-join.ts +17 -26
- package/src/runtime/actors/actor-remote-wire.ts +17 -0
- package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
- package/src/runtime/actors/actor-routed-json-request.ts +10 -2
- package/src/runtime/actors/index.ts +19 -5
- package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
- package/src/runtime/admission.ts +18 -5
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +41 -25
- package/src/runtime/application-jobs/application-job-queue-scope.ts +51 -22
- package/src/runtime/application-jobs/contracts.ts +14 -1
- package/src/runtime/backend/contracts/index.ts +53 -14
- package/src/runtime/backend/mesh-completion-table.ts +156 -57
- package/src/runtime/backend/mesh-dispatch-pump.ts +40 -10
- package/src/runtime/backend/node/node-backend-adapter-support.ts +17 -8
- package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
- package/src/runtime/backend/node/node-raw-binding-port.ts +57 -30
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +128 -65
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +21 -6
- package/src/runtime/backend/raw-binding-port.ts +7 -2
- package/src/runtime/backend/runtime-message.ts +6 -0
- package/src/runtime/backend/runtime-values.ts +1 -0
- package/src/runtime/channels/channel-clients.ts +90 -41
- package/src/runtime/channels/channel-dispatch-pipeline.ts +69 -34
- package/src/runtime/channels/channel-dispatch-services.ts +69 -1
- package/src/runtime/channels/channel-dispatchers.ts +29 -27
- package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
- package/src/runtime/channels/channel-envelope.ts +133 -8
- package/src/runtime/channels/channel-outbound-operations.ts +22 -8
- package/src/runtime/channels/channel-runtime-manager.ts +29 -12
- package/src/runtime/channels/channel-transports.ts +128 -60
- package/src/runtime/channels/local-spot-route-transport.ts +3 -1
- package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
- package/src/runtime/channels/source-spot-router.ts +8 -4
- package/src/runtime/channels/spot-node-route-transport.ts +8 -4
- package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
- package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
- package/src/runtime/execution/serial-execution-queue.ts +2 -0
- package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
- package/src/runtime/foundation/durable-service-request.ts +137 -0
- package/src/runtime/foundation/operation-identity.ts +5 -1
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +484 -293
- package/src/runtime/foundation/service-relocation-object-owner.ts +2 -0
- package/src/runtime/foundation/service-relocation-runtime.ts +18 -1
- package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
- package/src/runtime/foundation/service-stateful-runtime.ts +67 -125
- package/src/runtime/foundation/service-stateful-wire-codec.ts +0 -5
- package/src/runtime/foundation/service-topology-registry.ts +91 -36
- package/src/runtime/foundation/service-wire-m6a-codec.ts +57 -38
- package/src/runtime/handlers/handler-instance-scope.ts +67 -16
- package/src/runtime/host/actor-runtime-options-factory.ts +13 -2
- package/src/runtime/host/application-job-queue.ts +175 -41
- package/src/runtime/host/entry-actor-runtime.ts +4 -0
- package/src/runtime/host/index.ts +201 -156
- package/src/runtime/host/remote-bound-session-relay.ts +2 -23
- package/src/runtime/host/route-mesh-runtime.ts +1 -1
- package/src/runtime/host/service-relocation-control.ts +11 -5
- package/src/runtime/host/service-relocation-host-runtime.ts +315 -291
- package/src/runtime/host/spot-address-transport.ts +4 -2
- package/src/runtime/host/spot-runtime-options-factory.ts +2 -0
- package/src/runtime/locations/actor-location-claims.ts +52 -30
- package/src/runtime/locations/lifecycle.ts +8 -26
- package/src/runtime/locations/runtime.ts +28 -24
- package/src/runtime/messaging/framework-json-v1.ts +5 -325
- package/src/runtime/messaging/packet-name.ts +5 -25
- package/src/runtime/messaging/request-result.ts +58 -0
- package/src/runtime/messaging/submission-result.ts +5 -1
- package/src/runtime/protocol/service_wire_codec.generated.ts +131 -1
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +43 -23
- package/src/runtime/spots/index.ts +14 -2
- package/src/runtime/spots/spot-activation.ts +28 -10
- package/src/runtime/spots/spot-entry-activation.ts +9 -2
- package/src/runtime/spots/spot-handler-registry.ts +41 -8
- package/src/runtime/spots/spot-node-autoconnect.ts +6 -2
- package/src/runtime/spots/spot-outbound.ts +36 -16
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
- package/src/runtime/spots/spot-runtime-ports.ts +1 -0
- package/src/runtime/spots/spot-subscription-dispatch.ts +0 -3
- package/src/runtime/spots/spot-timer.ts +5 -1
- package/src/runtime/streams/stream-session-runtime.ts +12 -29
|
@@ -191,7 +191,7 @@ export class DefaultZLinkActorManager implements ZLinkActorManager {
|
|
|
191
191
|
const actorRef = this.actorRefForState(state);
|
|
192
192
|
return {
|
|
193
193
|
spotId: spotId,
|
|
194
|
-
objectGeneration: state.
|
|
194
|
+
objectGeneration: state.spotGeneration ?? 0n,
|
|
195
195
|
meshName: this.actorMeshNames.get(actorId) ?? '',
|
|
196
196
|
nodeRid: actorRef.nodeRid
|
|
197
197
|
};
|
|
@@ -467,7 +467,8 @@ export class DefaultZLinkActorManager implements ZLinkActorManager {
|
|
|
467
467
|
await registry.restore(transfer.adapterKey, actor, transfer.state, signal);
|
|
468
468
|
}
|
|
469
469
|
state.setLocationGeneration(authorityOwnerGeneration);
|
|
470
|
-
if (spotId !== undefined)
|
|
470
|
+
if (spotId !== undefined)
|
|
471
|
+
state.setJoinedSpot(spotId, undefined, membershipEpoch, spotGeneration);
|
|
471
472
|
return actor;
|
|
472
473
|
} catch (error) {
|
|
473
474
|
if (nativeRef !== undefined) node.discardRelocatedActor?.(nativeRef);
|
|
@@ -486,17 +487,30 @@ export class DefaultZLinkActorManager implements ZLinkActorManager {
|
|
|
486
487
|
}
|
|
487
488
|
|
|
488
489
|
async abortRelocationActor(actorId: string): Promise<void> {
|
|
489
|
-
await this.
|
|
490
|
+
await this.releaseLocalActor(actorId);
|
|
490
491
|
}
|
|
491
492
|
|
|
492
493
|
async completeRelocationSource(
|
|
493
494
|
actorId: string,
|
|
494
495
|
sourceActorRef?: ZLinkBackendActorRef
|
|
495
496
|
): Promise<void> {
|
|
496
|
-
await this.
|
|
497
|
+
await this.releaseLocalActor(actorId, sourceActorRef);
|
|
497
498
|
}
|
|
498
499
|
|
|
499
|
-
|
|
500
|
+
async releaseSpotActorMembers(meshName: string, spotId?: RoutingId): Promise<void> {
|
|
501
|
+
const results = await Promise.allSettled(
|
|
502
|
+
[...this.states.values()]
|
|
503
|
+
.filter((state) => state.meshName === meshName && state.spotId === spotId)
|
|
504
|
+
.map((state) => this.releaseLocalActor(state.actorId))
|
|
505
|
+
);
|
|
506
|
+
const errors = results
|
|
507
|
+
.filter((result): result is PromiseRejectedResult => result.status === 'rejected')
|
|
508
|
+
.map((result) => result.reason);
|
|
509
|
+
if (errors.length === 1) throw errors[0];
|
|
510
|
+
if (errors.length > 1) throw new AggregateError(errors, 'Actor member cleanup failed.');
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
private async releaseLocalActor(
|
|
500
514
|
actorId: string,
|
|
501
515
|
exactNativeActorRef?: ZLinkBackendActorRef
|
|
502
516
|
): Promise<void> {
|
|
@@ -49,7 +49,8 @@ export class ZLinkSpotActorHandlerRegistryRuntime implements ZLinkActorHandlerRe
|
|
|
49
49
|
);
|
|
50
50
|
const resolvedPacketName = packetName ?? metadata?.packetName;
|
|
51
51
|
if (metadata === undefined || resolvedPacketName === undefined) {
|
|
52
|
-
throw
|
|
52
|
+
throw createInternalFrameworkException(
|
|
53
|
+
ZLinkFrameworkInternalErrorKind.InvalidOperation,
|
|
53
54
|
`Actor packet handler '${handlerType.name}' must declare a packet name.`
|
|
54
55
|
);
|
|
55
56
|
}
|
|
@@ -68,7 +69,8 @@ export class ZLinkSpotActorHandlerRegistryRuntime implements ZLinkActorHandlerRe
|
|
|
68
69
|
addPacket(descriptor: ZLinkActorPacketDescriptor): this {
|
|
69
70
|
const key = packetKey(descriptor.kind, descriptor.actorType, descriptor.packetName);
|
|
70
71
|
if (this.packets.has(key)) {
|
|
71
|
-
throw
|
|
72
|
+
throw createInternalFrameworkException(
|
|
73
|
+
ZLinkFrameworkInternalErrorKind.InvalidOperation,
|
|
72
74
|
`Actor packet '${descriptor.packetName}' for '${descriptor.actorType.name}' is already registered.`
|
|
73
75
|
);
|
|
74
76
|
}
|
package/src/runtime/admission.ts
CHANGED
|
@@ -86,12 +86,25 @@ export class ZLinkRuntimeAdmissionGate {
|
|
|
86
86
|
);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
run<T>(meshName: string, operation: string, work: () => T | Promise<T>): Promise<T> {
|
|
90
|
+
let claim: ZLinkApplicationWorkClaim | undefined;
|
|
91
91
|
try {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
claim.close
|
|
92
|
+
claim = this.claim(meshName, operation);
|
|
93
|
+
const result = work();
|
|
94
|
+
const close = claim.close;
|
|
95
|
+
return Promise.resolve(result).then(
|
|
96
|
+
(value) => {
|
|
97
|
+
close();
|
|
98
|
+
return value;
|
|
99
|
+
},
|
|
100
|
+
(error) => {
|
|
101
|
+
close();
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
claim?.close();
|
|
107
|
+
return Promise.reject(error);
|
|
95
108
|
}
|
|
96
109
|
}
|
|
97
110
|
|
|
@@ -16,7 +16,7 @@ export interface IngressRecordPort {
|
|
|
16
16
|
* ordinary Framework-owned ingress record closes after the last child terminal.
|
|
17
17
|
*/
|
|
18
18
|
export class ApplicationIngressRecordOwner {
|
|
19
|
-
private
|
|
19
|
+
private stop?: AbortController;
|
|
20
20
|
private closed = false;
|
|
21
21
|
|
|
22
22
|
private constructor(private readonly shared: SharedIngressRecordState) {}
|
|
@@ -46,17 +46,34 @@ export class ApplicationIngressRecordOwner {
|
|
|
46
46
|
return job;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
acquire(
|
|
50
50
|
domain: ApplicationJobRecordDomain,
|
|
51
51
|
signal?: AbortSignal
|
|
52
|
-
): Promise<ApplicationJobRecordLease> {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
): ApplicationJobRecordLease | Promise<ApplicationJobRecordLease> {
|
|
53
|
+
try {
|
|
54
|
+
this.requireOpen();
|
|
55
|
+
const initial = this.shared.takeInitialPermit(domain);
|
|
56
|
+
if (initial !== undefined) return initial;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
return Promise.reject(error);
|
|
59
|
+
}
|
|
56
60
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
return this.acquireAdditional(domain, signal);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private async acquireAdditional(
|
|
65
|
+
domain: ApplicationJobRecordDomain,
|
|
66
|
+
signal?: AbortSignal
|
|
67
|
+
): Promise<ApplicationJobRecordLease> {
|
|
68
|
+
const stop = (this.stop ??= new AbortController());
|
|
69
|
+
const waitSignal = signal === undefined ? stop.signal : AbortSignal.any([stop.signal, signal]);
|
|
70
|
+
let permit: ApplicationJobPermitPort;
|
|
71
|
+
try {
|
|
72
|
+
permit = await this.shared.acquirePermit(waitSignal);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
if (error === ownerClosedError) throw ownerClosedError();
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
60
77
|
if (this.closed) {
|
|
61
78
|
permit.releaseAfterInternalProcessing();
|
|
62
79
|
throw ownerClosedError();
|
|
@@ -67,7 +84,8 @@ export class ApplicationIngressRecordOwner {
|
|
|
67
84
|
close(): void {
|
|
68
85
|
if (this.closed) return;
|
|
69
86
|
this.closed = true;
|
|
70
|
-
this.
|
|
87
|
+
// The queue forwards this reason; only a rejected acquisition constructs the error.
|
|
88
|
+
this.stop?.abort(ownerClosedError);
|
|
71
89
|
this.shared.releaseOwner();
|
|
72
90
|
}
|
|
73
91
|
|
|
@@ -79,14 +97,12 @@ export class ApplicationIngressRecordOwner {
|
|
|
79
97
|
/** Queue-permit child of one shared raw ingress record. */
|
|
80
98
|
export class ApplicationJobRecordLease implements ApplicationJobPermitPort {
|
|
81
99
|
private ingressClosed = false;
|
|
82
|
-
private permitReleased = false;
|
|
83
100
|
private processingTerminal = false;
|
|
84
|
-
|
|
85
|
-
private jobReleased = false;
|
|
101
|
+
detachedForHandlerTurn = false;
|
|
86
102
|
|
|
87
103
|
constructor(
|
|
88
104
|
private readonly shared: SharedIngressRecordState,
|
|
89
|
-
private
|
|
105
|
+
private permit: ApplicationJobPermitPort | undefined
|
|
90
106
|
) {}
|
|
91
107
|
|
|
92
108
|
get origin(): ApplicationJobOrigin {
|
|
@@ -103,12 +119,12 @@ export class ApplicationJobRecordLease implements ApplicationJobPermitPort {
|
|
|
103
119
|
}
|
|
104
120
|
|
|
105
121
|
releaseBeforeHandler(): void {
|
|
106
|
-
this.
|
|
122
|
+
this.permit?.releaseBeforeHandler();
|
|
107
123
|
}
|
|
108
124
|
|
|
109
125
|
releaseAfterInternalProcessing(): void {
|
|
110
126
|
this.processingTerminal = true;
|
|
111
|
-
this.
|
|
127
|
+
this.permit?.releaseAfterInternalProcessing();
|
|
112
128
|
this.releaseJobIfTerminal();
|
|
113
129
|
}
|
|
114
130
|
|
|
@@ -122,16 +138,15 @@ export class ApplicationJobRecordLease implements ApplicationJobPermitPort {
|
|
|
122
138
|
this.releaseJobIfTerminal();
|
|
123
139
|
}
|
|
124
140
|
|
|
125
|
-
private releasePermit(release: () => void): void {
|
|
126
|
-
if (this.permitReleased) return;
|
|
127
|
-
this.permitReleased = true;
|
|
128
|
-
release();
|
|
129
|
-
}
|
|
130
|
-
|
|
131
141
|
private releaseJobIfTerminal(): void {
|
|
132
|
-
|
|
133
|
-
this.
|
|
134
|
-
this.
|
|
142
|
+
const permit = this.permit;
|
|
143
|
+
if (permit === undefined || !this.ingressClosed || !this.processingTerminal) return;
|
|
144
|
+
this.permit = undefined;
|
|
145
|
+
try {
|
|
146
|
+
this.shared.releaseJob();
|
|
147
|
+
} finally {
|
|
148
|
+
permit.releaseStorage?.();
|
|
149
|
+
}
|
|
135
150
|
}
|
|
136
151
|
}
|
|
137
152
|
|
|
@@ -203,6 +218,7 @@ class SharedIngressRecordState {
|
|
|
203
218
|
try {
|
|
204
219
|
this.initialPermit?.releaseAfterInternalProcessing();
|
|
205
220
|
} finally {
|
|
221
|
+
this.initialPermit?.releaseStorage?.();
|
|
206
222
|
this.initialPermit = undefined;
|
|
207
223
|
this.record.close();
|
|
208
224
|
}
|
|
@@ -2,39 +2,69 @@ import { AsyncLocalStorage } from 'node:async_hooks';
|
|
|
2
2
|
|
|
3
3
|
import type { ApplicationJobOrigin, ApplicationJobPermitPort } from './contracts';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
const applicationJobPermitScope = new AsyncLocalStorage<ApplicationJobPermitPort | undefined>();
|
|
6
|
+
|
|
7
|
+
function releasePermitTurn(): void {
|
|
8
|
+
const permit = applicationJobPermitScope.getStore();
|
|
9
|
+
if (permit !== undefined && !permit.detachedForHandlerTurn)
|
|
10
|
+
permit.releaseAfterInternalProcessing();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function releasePermitSuccess<TResult>(value: TResult): TResult {
|
|
14
|
+
releasePermitTurn();
|
|
15
|
+
return value;
|
|
8
16
|
}
|
|
9
17
|
|
|
10
|
-
|
|
18
|
+
function releasePermitFailure(error: unknown): never {
|
|
19
|
+
releasePermitTurn();
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
11
22
|
|
|
12
23
|
/**
|
|
13
24
|
* Carries the host-owned queue permit through internal async dispatch without
|
|
14
25
|
* leaking capacity ownership into public handler contracts.
|
|
15
26
|
*/
|
|
16
|
-
export
|
|
27
|
+
export function runWithApplicationJobPermit<TResult>(
|
|
17
28
|
permit: ApplicationJobPermitPort,
|
|
18
|
-
callback: () => Promise<TResult>
|
|
19
|
-
): Promise<TResult
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
callback: () => Promise<TResult>
|
|
30
|
+
): Promise<TResult>;
|
|
31
|
+
export function runWithApplicationJobPermit<TResult, TFirst = undefined, TSecond = undefined>(
|
|
32
|
+
permit: ApplicationJobPermitPort,
|
|
33
|
+
callback: (first: TFirst, second: TSecond) => Promise<TResult> | TResult,
|
|
34
|
+
first?: TFirst,
|
|
35
|
+
second?: TSecond
|
|
36
|
+
): TResult | Promise<TResult>;
|
|
37
|
+
export function runWithApplicationJobPermit<TResult, TFirst, TSecond>(
|
|
38
|
+
permit: ApplicationJobPermitPort,
|
|
39
|
+
callback: (first: TFirst, second: TSecond) => Promise<TResult> | TResult,
|
|
40
|
+
first?: TFirst,
|
|
41
|
+
second?: TSecond
|
|
42
|
+
): TResult | Promise<TResult> {
|
|
43
|
+
const previous = applicationJobPermitScope.getStore();
|
|
44
|
+
applicationJobPermitScope.enterWith(permit);
|
|
45
|
+
try {
|
|
46
|
+
const result = callback(first as TFirst, second as TSecond);
|
|
47
|
+
if (result !== null && (typeof result === 'object' || typeof result === 'function')) {
|
|
48
|
+
return Promise.resolve(result).then(releasePermitSuccess, releasePermitFailure);
|
|
26
49
|
}
|
|
27
|
-
|
|
50
|
+
releasePermitTurn();
|
|
51
|
+
return result;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
releasePermitTurn();
|
|
54
|
+
return Promise.reject(error);
|
|
55
|
+
} finally {
|
|
56
|
+
applicationJobPermitScope.enterWith(previous);
|
|
57
|
+
}
|
|
28
58
|
}
|
|
29
59
|
|
|
30
60
|
/** Releases the current job permit immediately before the first user callback. */
|
|
31
61
|
export function releaseApplicationJobPermitBeforeHandler(): void {
|
|
32
|
-
applicationJobPermitScope.getStore()?.
|
|
62
|
+
applicationJobPermitScope.getStore()?.releaseBeforeHandler();
|
|
33
63
|
}
|
|
34
64
|
|
|
35
65
|
/** @internal Returns an ingress permit after a durable queue takes record ownership. */
|
|
36
66
|
export function releaseApplicationJobPermitForDurableHandoff(): void {
|
|
37
|
-
applicationJobPermitScope.getStore()?.
|
|
67
|
+
applicationJobPermitScope.getStore()?.releaseAfterInternalProcessing();
|
|
38
68
|
}
|
|
39
69
|
|
|
40
70
|
/** True while dispatch already owns the host-wide application job permit. */
|
|
@@ -44,7 +74,7 @@ export function hasApplicationJobPermit(): boolean {
|
|
|
44
74
|
|
|
45
75
|
/** Keeps the ingress origin when a durable record later reacquires its permit. */
|
|
46
76
|
export function currentApplicationJobOrigin(): ApplicationJobOrigin {
|
|
47
|
-
return applicationJobPermitScope.getStore()!.
|
|
77
|
+
return applicationJobPermitScope.getStore()!.origin;
|
|
48
78
|
}
|
|
49
79
|
|
|
50
80
|
/** Re-enters the captured permit scope when a serial executor runs later. */
|
|
@@ -61,9 +91,8 @@ export function bindApplicationJobPermit<TResult, TArgument>(
|
|
|
61
91
|
* detached owner must release it at handler entry or at a pre-start terminal.
|
|
62
92
|
*/
|
|
63
93
|
export function detachApplicationJobPermit(): ApplicationJobPermitPort | undefined {
|
|
64
|
-
const
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return scope.permit;
|
|
94
|
+
const permit = applicationJobPermitScope.getStore();
|
|
95
|
+
if (permit === undefined) return undefined;
|
|
96
|
+
permit.detachForHandlerTurn();
|
|
97
|
+
return permit;
|
|
69
98
|
}
|
|
@@ -2,14 +2,27 @@ export type ApplicationJobOrigin = 'local' | 'remote';
|
|
|
2
2
|
|
|
3
3
|
export interface ApplicationJobPermitPort {
|
|
4
4
|
readonly origin: ApplicationJobOrigin;
|
|
5
|
+
readonly detachedForHandlerTurn: boolean;
|
|
5
6
|
markApplicationQueued(): void;
|
|
6
7
|
/** Transfers ingress-record cleanup to a detached exact-target handler turn. */
|
|
7
|
-
detachForHandlerTurn
|
|
8
|
+
detachForHandlerTurn(): void;
|
|
8
9
|
releaseBeforeHandler(): void;
|
|
9
10
|
releaseAfterInternalProcessing(): void;
|
|
11
|
+
/** Returns reusable reservation storage only after its ingress lifetime ends. */
|
|
12
|
+
releaseStorage?(): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ApplicationJobReceiveRotationPort {
|
|
16
|
+
reserve(): void;
|
|
17
|
+
take(): ApplicationJobPermitPort | undefined;
|
|
18
|
+
releaseUnused(): void;
|
|
10
19
|
}
|
|
11
20
|
|
|
12
21
|
export interface ApplicationJobQueuePort {
|
|
22
|
+
createReceiveRotation(
|
|
23
|
+
capacity: number,
|
|
24
|
+
origin: ApplicationJobOrigin
|
|
25
|
+
): ApplicationJobReceiveRotationPort;
|
|
13
26
|
acquire(
|
|
14
27
|
signal: AbortSignal | undefined,
|
|
15
28
|
origin: ApplicationJobOrigin
|
|
@@ -62,6 +62,7 @@ export type ZLinkBackendObjectPlacement =
|
|
|
62
62
|
| { readonly kind: 'unavailable' };
|
|
63
63
|
|
|
64
64
|
export interface ZLinkBackendMeshNode {
|
|
65
|
+
readonly routingId?: RoutingId;
|
|
65
66
|
completeClosedInstance?(spotId: string, objectGeneration: bigint): void;
|
|
66
67
|
setDispatchErrorReporter?(
|
|
67
68
|
reporter: import('../../channels/dispatch-error-reporter').ZLinkDispatchErrorReporter,
|
|
@@ -125,7 +126,8 @@ export interface ZLinkBackendMeshNode {
|
|
|
125
126
|
parts: ZLinkBackendMessageLike | readonly ZLinkBackendMessageLike[],
|
|
126
127
|
deadlineUnixMs: bigint,
|
|
127
128
|
sourceSpotId?: string,
|
|
128
|
-
metadata?: ReadonlyMap<string, string
|
|
129
|
+
metadata?: ReadonlyMap<string, string>,
|
|
130
|
+
onAdmitted?: () => void
|
|
129
131
|
): MeshOperationId;
|
|
130
132
|
sendToInstanceSpot(
|
|
131
133
|
route: ServiceInstanceRouteFence,
|
|
@@ -140,7 +142,8 @@ export interface ZLinkBackendMeshNode {
|
|
|
140
142
|
timeoutMs?: number,
|
|
141
143
|
sourceSpotId?: string,
|
|
142
144
|
metadata?: ReadonlyMap<string, string>,
|
|
143
|
-
instanceIntent?: boolean
|
|
145
|
+
instanceIntent?: boolean,
|
|
146
|
+
onAdmitted?: () => void
|
|
144
147
|
): MeshOperationId;
|
|
145
148
|
registerUserSpotOperationHandler(handler: ServiceUserSpotOperationHandler): void;
|
|
146
149
|
requestUserSpotCreate(
|
|
@@ -182,12 +185,16 @@ export interface ZLinkBackendMeshNode {
|
|
|
182
185
|
readonly lifecycleGeneration: bigint;
|
|
183
186
|
}): void;
|
|
184
187
|
isObjectClientNodeDirectTarget?(targetRid: unknown): boolean;
|
|
188
|
+
observePeerRoute?(
|
|
189
|
+
targetRid: unknown
|
|
190
|
+
): import('../../foundation/durable-service-request').PeerRouteObservation;
|
|
191
|
+
hasPeerRouteOrConnectionIntent?(targetRid: unknown, endpoint: string): boolean;
|
|
185
192
|
isPeerRouteReady?(targetRid: unknown, lifecycleGeneration?: bigint): boolean;
|
|
186
193
|
sendToNode(
|
|
187
194
|
targetRid: unknown,
|
|
188
195
|
parts: MessageLike | readonly MessageLike[],
|
|
189
196
|
options?: { flags?: number }
|
|
190
|
-
): Promise<SubmitResult>;
|
|
197
|
+
): SubmitResult | Promise<SubmitResult>;
|
|
191
198
|
/**
|
|
192
199
|
* Sends service-wire infrastructure frames directly to a peer. Relocation
|
|
193
200
|
* Prepare may add NODE-INTERNAL sideband frames after its canonical frame.
|
|
@@ -208,12 +215,21 @@ export interface ZLinkBackendMeshNode {
|
|
|
208
215
|
requestInfrastructureControlFrames?(
|
|
209
216
|
targetRid: unknown,
|
|
210
217
|
frames: readonly Uint8Array[],
|
|
211
|
-
options?: {
|
|
218
|
+
options?: {
|
|
219
|
+
readonly timeoutMs?: number;
|
|
220
|
+
readonly signal?: AbortSignal;
|
|
221
|
+
readonly onSubmitted?: (signal: AbortSignal) => Promise<void>;
|
|
222
|
+
}
|
|
212
223
|
): Promise<readonly Uint8Array[]>;
|
|
213
224
|
requestToNode(
|
|
214
225
|
targetRid: unknown,
|
|
215
226
|
parts: MessageLike | readonly MessageLike[],
|
|
216
|
-
options?: {
|
|
227
|
+
options?: {
|
|
228
|
+
flags?: number;
|
|
229
|
+
timeoutMs?: number;
|
|
230
|
+
applicationMetadata?: Buffer;
|
|
231
|
+
onAdmitted?: () => void;
|
|
232
|
+
}
|
|
217
233
|
): MeshOperationId;
|
|
218
234
|
sendToChannel(
|
|
219
235
|
channelName: string,
|
|
@@ -223,7 +239,12 @@ export interface ZLinkBackendMeshNode {
|
|
|
223
239
|
requestToChannel(
|
|
224
240
|
channelName: string,
|
|
225
241
|
parts: MessageLike | readonly MessageLike[],
|
|
226
|
-
options?: {
|
|
242
|
+
options?: {
|
|
243
|
+
flags?: number;
|
|
244
|
+
timeoutMs?: number;
|
|
245
|
+
applicationMetadata?: Buffer;
|
|
246
|
+
onAdmitted?: () => void;
|
|
247
|
+
}
|
|
227
248
|
): MeshOperationId;
|
|
228
249
|
status(): MeshNodeStatus;
|
|
229
250
|
peers(): MeshPeerEntry[];
|
|
@@ -349,7 +370,12 @@ export interface ZLinkBackendMeshNode {
|
|
|
349
370
|
requestToActor(
|
|
350
371
|
actor: ZLinkBackendActorRef,
|
|
351
372
|
parts: MessageLike | readonly MessageLike[],
|
|
352
|
-
options?: {
|
|
373
|
+
options?: {
|
|
374
|
+
flags?: number;
|
|
375
|
+
timeoutMs?: number;
|
|
376
|
+
applicationMetadata?: Buffer;
|
|
377
|
+
onAdmitted?: () => void;
|
|
378
|
+
}
|
|
353
379
|
): MeshOperationId;
|
|
354
380
|
actorSendToActor(
|
|
355
381
|
source: ZLinkBackendActorRef,
|
|
@@ -361,7 +387,12 @@ export interface ZLinkBackendMeshNode {
|
|
|
361
387
|
source: ZLinkBackendActorRef,
|
|
362
388
|
target: ZLinkBackendActorRef,
|
|
363
389
|
parts: MessageLike | readonly MessageLike[],
|
|
364
|
-
options?: {
|
|
390
|
+
options?: {
|
|
391
|
+
flags?: number;
|
|
392
|
+
timeoutMs?: number;
|
|
393
|
+
applicationMetadata?: Buffer;
|
|
394
|
+
onAdmitted?: () => void;
|
|
395
|
+
}
|
|
365
396
|
): MeshOperationId;
|
|
366
397
|
sendActorBoundSession(
|
|
367
398
|
actor: ZLinkBackendActorRef,
|
|
@@ -484,7 +515,11 @@ export interface ZLinkBackendDealerSocket extends ZLinkBackendConnectableSocket
|
|
|
484
515
|
receiveTimeoutMs: number;
|
|
485
516
|
maxMessageSize: number;
|
|
486
517
|
send(message: Message | readonly Message[]): Promise<void>;
|
|
487
|
-
request(
|
|
518
|
+
request(
|
|
519
|
+
message: Message | readonly Message[],
|
|
520
|
+
timeoutMs?: number,
|
|
521
|
+
onAdmitted?: () => void
|
|
522
|
+
): Promise<readonly Message[]>;
|
|
488
523
|
recv(flags?: ZLinkBackendRecvFlags): Received | undefined;
|
|
489
524
|
}
|
|
490
525
|
|
|
@@ -501,7 +536,7 @@ export interface ZLinkBackendSendOperation {
|
|
|
501
536
|
export interface ZLinkBackendRequestOperation {
|
|
502
537
|
message(message: MessageLike): ZLinkBackendRequestOperation;
|
|
503
538
|
timeout(timeoutMs: number): ZLinkBackendRequestOperation;
|
|
504
|
-
submit(): Promise<readonly Message[]>;
|
|
539
|
+
submit(onAdmitted?: () => void): Promise<readonly Message[]>;
|
|
505
540
|
}
|
|
506
541
|
|
|
507
542
|
export interface ZLinkBackendRouterSocket extends ZLinkBackendConnectableSocket {
|
|
@@ -519,7 +554,8 @@ export interface ZLinkBackendRouterSocket extends ZLinkBackendConnectableSocket
|
|
|
519
554
|
request(
|
|
520
555
|
routingId: RoutingId,
|
|
521
556
|
message: Message | readonly Message[],
|
|
522
|
-
timeoutMs?: number
|
|
557
|
+
timeoutMs?: number,
|
|
558
|
+
onAdmitted?: () => void
|
|
523
559
|
): Promise<readonly Message[]>;
|
|
524
560
|
sendToSpot(
|
|
525
561
|
targetNodeRid: RoutingId,
|
|
@@ -531,7 +567,8 @@ export interface ZLinkBackendRouterSocket extends ZLinkBackendConnectableSocket
|
|
|
531
567
|
targetNodeRid: RoutingId,
|
|
532
568
|
targetSpotId: RoutingId,
|
|
533
569
|
parts: readonly Message[],
|
|
534
|
-
timeoutMs?: number
|
|
570
|
+
timeoutMs?: number,
|
|
571
|
+
onAdmitted?: () => void
|
|
535
572
|
): Promise<readonly Message[]>;
|
|
536
573
|
disconnectPeer(routingId: RoutingId): void;
|
|
537
574
|
reply(routingId: RoutingId, replyToken: unknown): ZLinkBackendReplyOperation;
|
|
@@ -688,7 +725,8 @@ export interface ZLinkBackendSpot extends ZLinkBackendObject {
|
|
|
688
725
|
requestToChannel(
|
|
689
726
|
channelName: string,
|
|
690
727
|
payload: Message | readonly Message[],
|
|
691
|
-
timeoutMs?: number
|
|
728
|
+
timeoutMs?: number,
|
|
729
|
+
onAdmitted?: () => void
|
|
692
730
|
): Promise<readonly Message[]>;
|
|
693
731
|
sendToChannel(channelName: string, payload: Message | readonly Message[]): Promise<void>;
|
|
694
732
|
publish(
|
|
@@ -705,7 +743,8 @@ export interface ZLinkBackendSpot extends ZLinkBackendObject {
|
|
|
705
743
|
targetRid: RoutingId,
|
|
706
744
|
spotId: RoutingId,
|
|
707
745
|
payload: Message | readonly Message[],
|
|
708
|
-
timeoutMs?: number
|
|
746
|
+
timeoutMs?: number,
|
|
747
|
+
onAdmitted?: () => void
|
|
709
748
|
): Promise<readonly Message[]>;
|
|
710
749
|
dispose(): Promise<void>;
|
|
711
750
|
}
|