@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
|
@@ -144,7 +144,8 @@ class ZLinkHostSpotAddressTransport {
|
|
|
144
144
|
instanceSpot: call.instanceSpot,
|
|
145
145
|
timeoutMs: deadline.requireRemaining(),
|
|
146
146
|
signal: deadline.signal,
|
|
147
|
-
metadata: call.metadata
|
|
147
|
+
metadata: call.metadata,
|
|
148
|
+
onAdmitted: call.onAdmitted
|
|
148
149
|
}), deadline.signal);
|
|
149
150
|
this.traceInstanceAddress(ZLinkDispatchOptions_1.ZLinkRuntimeMessageFlowOutcome.ReplyReceived, ZLinkDispatchOptions_1.ZLinkDispatchMessageKind.Request, spotId, request, existing.routerChannelId, existing.stableType, existing.targetNodeRid);
|
|
150
151
|
return reply;
|
|
@@ -173,7 +174,7 @@ class ZLinkHostSpotAddressTransport {
|
|
|
173
174
|
const table = this.options.completions(selected.meshName);
|
|
174
175
|
if (table === undefined)
|
|
175
176
|
throw new Error(`MeshNode '${selected.meshName}' completion table is not started.`);
|
|
176
|
-
const completionPromise = table.submit(() => selected.node.requestToMissingInstanceSpot(selected.target, encoded, deadlineUnixMs, call.sourceSpot === undefined ? undefined : String(call.sourceSpot.routingId), call.metadata), deadline.signal);
|
|
177
|
+
const completionPromise = table.submit(() => selected.node.requestToMissingInstanceSpot(selected.target, encoded, deadlineUnixMs, call.sourceSpot === undefined ? undefined : String(call.sourceSpot.routingId), call.metadata, call.onAdmitted), deadline.signal);
|
|
177
178
|
this.traceInstanceAddress(ZLinkDispatchOptions_1.ZLinkRuntimeMessageFlowOutcome.Sent, ZLinkDispatchOptions_1.ZLinkDispatchMessageKind.Request, spotId, request, selected.meshName, selected.target.stableType, selected.target.targetNodeRid);
|
|
178
179
|
const completion = await (0, abort_1.awaitWithAbort)(completionPromise, deadline.signal);
|
|
179
180
|
try {
|
|
@@ -178,6 +178,7 @@ class ZLinkSpotRuntimeOptionsFactory {
|
|
|
178
178
|
contracts_1.ZLinkSpotRelocationCoordinationMode.FrameworkManaged);
|
|
179
179
|
},
|
|
180
180
|
actorTransferRuntime,
|
|
181
|
+
releaseActorMembers: (meshName, spotId) => this.options.actorManager()?.releaseSpotActorMembers(meshName, spotId) ?? Promise.resolve(),
|
|
181
182
|
boundSessionRuntime: this.options.boundSessionRelay.boundSessions,
|
|
182
183
|
actorHandoffRuntime: this.options.actorHandoff,
|
|
183
184
|
metrics: this.options.metrics,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ActorRef, RoutingId } from '../../contracts/Common';
|
|
2
2
|
import { type ZLinkActorLocation } from './internal-location-contracts';
|
|
3
3
|
import type { ZLinkActorLocationStore, ZLinkAuthorityStore } from './internal-store-contracts';
|
|
4
|
+
import { ZLinkSpotKind } from '../../contracts/Spots';
|
|
4
5
|
import type { IZLinkLocationLifecycleRuntime, ZLinkOwnershipLostEvent } from './lifecycle-runtime';
|
|
5
6
|
export declare enum ZLinkActorClaimStatus {
|
|
6
7
|
Claimed = "claimed",
|
|
@@ -31,8 +32,7 @@ export declare class ZLinkActorLocationClaims {
|
|
|
31
32
|
claim(actorType: string, actorId: string, nodeRid: RoutingId, deactivate?: () => Promise<void>): Promise<ZLinkActorClaimResult>;
|
|
32
33
|
setRef(actorType: string, actorId: string, actorRef: ActorRef, ownerNodeGeneration: bigint): Promise<void>;
|
|
33
34
|
takeoverJoinedSpot(actorType: string, actorId: string, actorRef: ActorRef, spotMeshName: string, spotId: RoutingId, spotGeneration: bigint, membershipEpoch: bigint, ownerNodeGeneration: bigint, deactivate?: () => Promise<void>): Promise<ZLinkActorClaimResult>;
|
|
34
|
-
|
|
35
|
-
notifyLeftSpot(actorType: string, actorId: string, entrySpotId: RoutingId, entrySpotGeneration: bigint, membershipEpoch: bigint, ownerNodeGeneration: bigint): Promise<void>;
|
|
35
|
+
commitMembership(actorType: string, actorRef: ActorRef, authorityOwnerGeneration: bigint, spotId: RoutingId, spotGeneration: bigint, spotKind: ZLinkSpotKind.Entry | ZLinkSpotKind.User, ownerNodeGeneration: bigint): Promise<void>;
|
|
36
36
|
release(_actorType: string, actorId: string, actorRef?: ActorRef): Promise<void>;
|
|
37
37
|
owns(_actorType: string, actorId: string): boolean;
|
|
38
38
|
snapshot(actorId: string): ZLinkActorLocation | undefined;
|
|
@@ -6,6 +6,7 @@ const Spots_1 = require("../../contracts/Spots");
|
|
|
6
6
|
const key_codec_1 = require("./key-codec");
|
|
7
7
|
const authority_key_codec_1 = require("./authority-key-codec");
|
|
8
8
|
const routing_id_1 = require("../routing-id");
|
|
9
|
+
const actor_authority_publication_1 = require("../actors/actor-authority-publication");
|
|
9
10
|
var ZLinkActorClaimStatus;
|
|
10
11
|
(function (ZLinkActorClaimStatus) {
|
|
11
12
|
ZLinkActorClaimStatus["Claimed"] = "claimed";
|
|
@@ -149,25 +150,39 @@ class ZLinkActorLocationClaims {
|
|
|
149
150
|
});
|
|
150
151
|
return { status: ZLinkActorClaimStatus.Claimed, claimed, generation: result.generation };
|
|
151
152
|
}
|
|
152
|
-
async
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
153
|
+
async commitMembership(actorType, actorRef, authorityOwnerGeneration, spotId, spotGeneration, spotKind, ownerNodeGeneration) {
|
|
154
|
+
const actorId = actorRef.actorId;
|
|
155
|
+
const store = this.authorityStore;
|
|
156
|
+
const owner = this.runtime.currentOwnerToken;
|
|
157
|
+
if (store === undefined || owner === undefined) {
|
|
158
|
+
throw new Error('Actor membership commit requires Location Store authority and owner.');
|
|
159
|
+
}
|
|
160
|
+
const key = (0, authority_key_codec_1.encodeAuthorityKey)('actor', actorId);
|
|
161
|
+
const current = await store.readAuthority(key);
|
|
162
|
+
if (!matchesActorAuthority(current, actorRef, owner) ||
|
|
163
|
+
current.allocation.stableType !== actorType ||
|
|
164
|
+
current.authorityOwnerGeneration !== authorityOwnerGeneration ||
|
|
165
|
+
current.allocation.descriptorLifecycleGeneration !== ownerNodeGeneration) {
|
|
166
|
+
throw new Error(`Actor '${actorId}' membership authority fence does not match.`);
|
|
167
|
+
}
|
|
168
|
+
const identity = (0, actor_authority_publication_1.decodeActorAuthorityIdentity)(current.payload, current.objectGeneration);
|
|
169
|
+
if (identity === undefined ||
|
|
170
|
+
identity.actorType !== actorType ||
|
|
171
|
+
identity.ownerNodeGeneration !== ownerNodeGeneration ||
|
|
172
|
+
identity.owner.ownerId !== owner.ownerId ||
|
|
173
|
+
identity.owner.leaseGeneration !== owner.leaseGeneration ||
|
|
174
|
+
!(0, routing_id_1.routingIdsEqual)(identity.actor.nodeRid, actorRef.nodeRid) ||
|
|
175
|
+
identity.meshName !== actorRef.meshName) {
|
|
176
|
+
throw new Error(`Actor '${actorId}' membership authority identity does not match.`);
|
|
177
|
+
}
|
|
178
|
+
const result = await store.compareExchangeAuthority(key, current.storeVersion, {
|
|
179
|
+
kind: 'put',
|
|
180
|
+
generationTransition: 'preserve',
|
|
181
|
+
payload: (0, actor_authority_publication_1.rewriteActorAuthorityRoute)(current.payload, actorRef, String(spotId), spotGeneration, spotKind)
|
|
182
|
+
});
|
|
183
|
+
if (result.kind !== 'stored') {
|
|
184
|
+
throw new Error(`Actor '${actorId}' membership commit was rejected with status ${result.kind}.`);
|
|
185
|
+
}
|
|
171
186
|
}
|
|
172
187
|
async release(_actorType, actorId, actorRef) {
|
|
173
188
|
const key = { meshName: this.entryMeshName, actorId };
|
|
@@ -19,8 +19,7 @@ export declare class ZLinkLocationLifecycle {
|
|
|
19
19
|
claimActor(actorType: string, actorId: string, nodeRid: RoutingId, deactivate?: () => Promise<void>): Promise<ZLinkActorClaimResult>;
|
|
20
20
|
setActorRef(actorType: string, actorId: string, actorRef: ActorRef, ownerNodeGeneration?: bigint): Promise<void>;
|
|
21
21
|
takeoverActorJoinedSpot(actorType: string, actorId: string, actorRef: ActorRef, spotMeshName: string, spotId: RoutingId, spotGeneration: bigint, membershipEpoch: bigint, ownerNodeGeneration: bigint, deactivate?: () => Promise<void>): Promise<ZLinkActorClaimResult>;
|
|
22
|
-
|
|
23
|
-
notifyActorLeftSpot(actorType: string, actorId: string, entrySpotId: RoutingId, entrySpotGeneration: bigint, membershipEpoch: bigint, ownerNodeGeneration: bigint): Promise<void>;
|
|
22
|
+
commitActorMembership(actorType: string, actorRef: ActorRef, authorityOwnerGeneration: bigint, spotId: RoutingId, spotGeneration: bigint, spotKind: ZLinkSpotKind.Entry | ZLinkSpotKind.User, ownerNodeGeneration: bigint): Promise<void>;
|
|
24
23
|
releaseActor(actorType: string, actorId: string, actorRef?: ActorRef): Promise<void>;
|
|
25
24
|
ownsActor(actorType: string, actorId: string): boolean;
|
|
26
25
|
actorLocationSnapshot(actorId: string): ZLinkActorLocation | undefined;
|
|
@@ -34,11 +34,8 @@ class ZLinkLocationLifecycle {
|
|
|
34
34
|
async takeoverActorJoinedSpot(actorType, actorId, actorRef, spotMeshName, spotId, spotGeneration, membershipEpoch, ownerNodeGeneration, deactivate) {
|
|
35
35
|
return await this.actorClaims.takeoverJoinedSpot(actorType, actorId, actorRef, spotMeshName, spotId, spotGeneration, membershipEpoch, ownerNodeGeneration, deactivate);
|
|
36
36
|
}
|
|
37
|
-
async
|
|
38
|
-
await this.actorClaims.
|
|
39
|
-
}
|
|
40
|
-
async notifyActorLeftSpot(actorType, actorId, entrySpotId, entrySpotGeneration, membershipEpoch, ownerNodeGeneration) {
|
|
41
|
-
await this.actorClaims.notifyLeftSpot(actorType, actorId, entrySpotId, entrySpotGeneration, membershipEpoch, ownerNodeGeneration);
|
|
37
|
+
async commitActorMembership(actorType, actorRef, authorityOwnerGeneration, spotId, spotGeneration, spotKind, ownerNodeGeneration) {
|
|
38
|
+
await this.actorClaims.commitMembership(actorType, actorRef, authorityOwnerGeneration, spotId, spotGeneration, spotKind, ownerNodeGeneration);
|
|
42
39
|
}
|
|
43
40
|
async releaseActor(actorType, actorId, actorRef) {
|
|
44
41
|
await this.actorClaims.release(actorType, actorId, actorRef);
|
|
@@ -83,7 +83,7 @@ export declare class ZLinkLocationRuntime implements ZLinkLocationRuntimeQuery {
|
|
|
83
83
|
private readonly meshNames;
|
|
84
84
|
private readonly leaseScopes;
|
|
85
85
|
private readonly rewriteAuthorityPayloadForOwner?;
|
|
86
|
-
private
|
|
86
|
+
private leaseOperationStartedAtMs;
|
|
87
87
|
private ownerToken?;
|
|
88
88
|
private lastOwnerToken?;
|
|
89
89
|
private ownerLeaseDeadlineMs?;
|
|
@@ -52,7 +52,7 @@ class ZLinkLocationRuntime {
|
|
|
52
52
|
meshNames;
|
|
53
53
|
leaseScopes;
|
|
54
54
|
rewriteAuthorityPayloadForOwner;
|
|
55
|
-
|
|
55
|
+
leaseOperationStartedAtMs = 0;
|
|
56
56
|
ownerToken;
|
|
57
57
|
lastOwnerToken;
|
|
58
58
|
ownerLeaseDeadlineMs;
|
|
@@ -191,12 +191,7 @@ class ZLinkLocationRuntime {
|
|
|
191
191
|
const claim = this.renewOwnerLeaseOnce(signal, shutdownSignal);
|
|
192
192
|
this.heartbeatRenewal = claim;
|
|
193
193
|
try {
|
|
194
|
-
|
|
195
|
-
if (claimed) {
|
|
196
|
-
this.scheduleHeartbeat();
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
this.nextLeaseRenewAtMs = this.monotonicNowMs() + this.options.ownerLeaseRenewIntervalMs;
|
|
194
|
+
await claim;
|
|
200
195
|
this.scheduleHeartbeat();
|
|
201
196
|
}
|
|
202
197
|
catch (error) {
|
|
@@ -211,7 +206,7 @@ class ZLinkLocationRuntime {
|
|
|
211
206
|
this.clearTimer(this.heartbeatTimer);
|
|
212
207
|
this.heartbeatTimer = undefined;
|
|
213
208
|
}
|
|
214
|
-
this.
|
|
209
|
+
this.leaseOperationStartedAtMs = 0;
|
|
215
210
|
this.ownerLeaseDeadlineMs = undefined;
|
|
216
211
|
await this.cleanupOwner(signal);
|
|
217
212
|
}
|
|
@@ -263,6 +258,7 @@ class ZLinkLocationRuntime {
|
|
|
263
258
|
const wasOwnerLeaseUsable = this.ownerLeaseUsable;
|
|
264
259
|
try {
|
|
265
260
|
const renewStartedAtMs = this.monotonicNowMs();
|
|
261
|
+
this.leaseOperationStartedAtMs = renewStartedAtMs;
|
|
266
262
|
const result = await withTimeout((renewSignal) => this.stores.ownerLeaseStore.renewOwnerLease(this.ownerToken, this.options.ownerLeaseTtlMs, renewSignal), this.options.ownerLeaseRenewTimeoutMs, signal);
|
|
267
263
|
const renewCompletedAtMs = this.monotonicNowMs();
|
|
268
264
|
if (result.kind !== 'renewed') {
|
|
@@ -303,10 +299,11 @@ class ZLinkLocationRuntime {
|
|
|
303
299
|
}
|
|
304
300
|
async claimFreshOwnerLease(signal, shutdownSignal) {
|
|
305
301
|
const claimStartedAtMs = this.monotonicNowMs();
|
|
306
|
-
|
|
302
|
+
this.leaseOperationStartedAtMs = claimStartedAtMs;
|
|
303
|
+
const timeoutStartedAtMs = performance.now();
|
|
307
304
|
let claim;
|
|
308
305
|
try {
|
|
309
|
-
claim = await this.claimOwnerLeaseWithConfirmation(
|
|
306
|
+
claim = await this.claimOwnerLeaseWithConfirmation(timeoutStartedAtMs, signal, shutdownSignal);
|
|
310
307
|
}
|
|
311
308
|
catch (error) {
|
|
312
309
|
if (signal?.aborted === true)
|
|
@@ -334,7 +331,6 @@ class ZLinkLocationRuntime {
|
|
|
334
331
|
this.ownerLeaseRenewedAt = claim.storeNow;
|
|
335
332
|
this.setOwnerLeaseDeadline(claimStartedAtMs, claimCompletedAtMs, claim.leaseExpiresAt, claim.storeNow);
|
|
336
333
|
this.lastError = undefined;
|
|
337
|
-
this.nextLeaseRenewAtMs = this.monotonicNowMs() + this.options.ownerLeaseRenewIntervalMs;
|
|
338
334
|
for (const handler of this.ownerLeaseRenewedHandlers) {
|
|
339
335
|
handler({
|
|
340
336
|
kind: 'renewed',
|
|
@@ -351,12 +347,12 @@ class ZLinkLocationRuntime {
|
|
|
351
347
|
return false;
|
|
352
348
|
}
|
|
353
349
|
}
|
|
354
|
-
async claimOwnerLeaseWithConfirmation(
|
|
350
|
+
async claimOwnerLeaseWithConfirmation(timeoutStartedAtMs, signal, shutdownSignal) {
|
|
355
351
|
signal?.throwIfAborted();
|
|
356
352
|
let claim;
|
|
357
353
|
let request;
|
|
358
354
|
try {
|
|
359
|
-
claim = await withTimeout((claimSignal) => (request = this.stores.ownerLeaseStore.claimOwnerLease(this.ownerId, this.options.ownerLeaseTtlMs, claimSignal)), remainingTimeoutMs(
|
|
355
|
+
claim = await withTimeout((claimSignal) => (request = this.stores.ownerLeaseStore.claimOwnerLease(this.ownerId, this.options.ownerLeaseTtlMs, claimSignal)), remainingTimeoutMs(timeoutStartedAtMs, this.options.ownerLeaseRenewTimeoutMs), signal);
|
|
360
356
|
}
|
|
361
357
|
catch (error) {
|
|
362
358
|
if (error instanceof OwnerLeaseRenewTimeoutError)
|
|
@@ -364,7 +360,9 @@ class ZLinkLocationRuntime {
|
|
|
364
360
|
if (signal?.aborted === true && request !== undefined) {
|
|
365
361
|
const cleanupSignal = shutdownSignal?.();
|
|
366
362
|
try {
|
|
367
|
-
await withTimeout(() => request, cleanupSignal === undefined
|
|
363
|
+
await withTimeout(() => request, cleanupSignal === undefined
|
|
364
|
+
? remainingTimeoutMs(timeoutStartedAtMs, this.options.ownerLeaseRenewTimeoutMs)
|
|
365
|
+
: undefined, cleanupSignal);
|
|
368
366
|
}
|
|
369
367
|
catch (completionError) {
|
|
370
368
|
if (cleanupSignal?.aborted === true ||
|
|
@@ -376,7 +374,7 @@ class ZLinkLocationRuntime {
|
|
|
376
374
|
}
|
|
377
375
|
}
|
|
378
376
|
}
|
|
379
|
-
const confirmed = await this.confirmOwnerLease(error,
|
|
377
|
+
const confirmed = await this.confirmOwnerLease(error, timeoutStartedAtMs, signal, shutdownSignal);
|
|
380
378
|
if (confirmed !== undefined)
|
|
381
379
|
return confirmed;
|
|
382
380
|
throw error;
|
|
@@ -384,12 +382,14 @@ class ZLinkLocationRuntime {
|
|
|
384
382
|
if (claim.kind !== 'conflict')
|
|
385
383
|
return claim;
|
|
386
384
|
const conflict = new ZLinkOwnerLeaseClaimError(claim.kind);
|
|
387
|
-
return ((await this.confirmOwnerLease(conflict,
|
|
385
|
+
return ((await this.confirmOwnerLease(conflict, timeoutStartedAtMs, signal, shutdownSignal)) ?? claim);
|
|
388
386
|
}
|
|
389
|
-
async confirmOwnerLease(originalError,
|
|
387
|
+
async confirmOwnerLease(originalError, timeoutStartedAtMs, signal, shutdownSignal) {
|
|
390
388
|
const cancelled = signal?.aborted === true;
|
|
391
389
|
const cleanupSignal = cancelled ? shutdownSignal?.() : undefined;
|
|
392
|
-
const confirmationTimeoutMs = cleanupSignal === undefined
|
|
390
|
+
const confirmationTimeoutMs = cleanupSignal === undefined
|
|
391
|
+
? remainingTimeoutMs(timeoutStartedAtMs, this.options.ownerLeaseRenewTimeoutMs)
|
|
392
|
+
: undefined;
|
|
393
393
|
if (confirmationTimeoutMs !== undefined && confirmationTimeoutMs <= 0)
|
|
394
394
|
throw originalError;
|
|
395
395
|
let confirmed;
|
|
@@ -407,7 +407,9 @@ class ZLinkLocationRuntime {
|
|
|
407
407
|
}
|
|
408
408
|
if (signal?.aborted === true) {
|
|
409
409
|
try {
|
|
410
|
-
await withTimeout((releaseSignal) => this.stores.ownerLeaseStore.releaseOwnerLease(confirmed.token, releaseSignal), cleanupSignal === undefined
|
|
410
|
+
await withTimeout((releaseSignal) => this.stores.ownerLeaseStore.releaseOwnerLease(confirmed.token, releaseSignal), cleanupSignal === undefined
|
|
411
|
+
? remainingTimeoutMs(timeoutStartedAtMs, this.options.ownerLeaseRenewTimeoutMs)
|
|
412
|
+
: undefined, cleanupSignal);
|
|
411
413
|
}
|
|
412
414
|
catch (releaseError) {
|
|
413
415
|
this.recordFailure(errorMessage(releaseError), 'owner_lease_release');
|
|
@@ -778,7 +780,7 @@ class ZLinkLocationRuntime {
|
|
|
778
780
|
if (!this.started) {
|
|
779
781
|
return;
|
|
780
782
|
}
|
|
781
|
-
const scheduledAt = this.
|
|
783
|
+
const scheduledAt = this.leaseOperationStartedAtMs + this.options.ownerLeaseRenewIntervalMs;
|
|
782
784
|
const delayMs = Math.max(0, scheduledAt - this.monotonicNowMs());
|
|
783
785
|
this.heartbeatTimer = this.setTimer(() => {
|
|
784
786
|
this.heartbeatTimer = undefined;
|
|
@@ -786,7 +788,6 @@ class ZLinkLocationRuntime {
|
|
|
786
788
|
for (const scope of this.leaseScopes) {
|
|
787
789
|
this.metrics?.recordOwnerLeaseRenewLateness(lateness, scope.kind, scope.name);
|
|
788
790
|
}
|
|
789
|
-
this.nextLeaseRenewAtMs = this.monotonicNowMs() + this.options.ownerLeaseRenewIntervalMs;
|
|
790
791
|
if (this.ownerLeaseDeadlineMs !== undefined &&
|
|
791
792
|
this.monotonicNowMs() >= this.ownerLeaseDeadlineMs) {
|
|
792
793
|
this.ownerLeaseHealthy = false;
|
|
@@ -908,8 +909,8 @@ class OwnerLeaseRenewTimeoutError extends Error {
|
|
|
908
909
|
this.name = 'OwnerLeaseRenewTimeoutError';
|
|
909
910
|
}
|
|
910
911
|
}
|
|
911
|
-
function remainingTimeoutMs(
|
|
912
|
-
return Math.max(0,
|
|
912
|
+
function remainingTimeoutMs(timeoutStartedAtMs, timeoutMs) {
|
|
913
|
+
return Math.max(0, timeoutMs - (performance.now() - timeoutStartedAtMs));
|
|
913
914
|
}
|
|
914
915
|
function errorMessage(error) {
|
|
915
916
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as profile from '@zlink-systems/stream-wire/internal/json';
|
|
2
2
|
export declare const FRAMEWORK_JSON_V1_PROFILE = "framework-json-v1";
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
export declare function stringifyFrameworkJsonV1(value: unknown, schema?: ZLinkJsonSchema): string;
|
|
7
|
-
export declare function parseFrameworkJsonV1(text: string, options?: FrameworkJsonParseOptions, schema?: ZLinkJsonSchema): unknown;
|
|
3
|
+
export declare const stringifyFrameworkJsonV1: typeof profile.stringifyFrameworkJsonV1;
|
|
4
|
+
export declare const parseFrameworkJsonV1: typeof profile.parseFrameworkJsonV1;
|
|
5
|
+
export type { FrameworkJsonParseOptions } from '@zlink-systems/stream-wire/internal/json';
|
|
@@ -1,296 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FRAMEWORK_JSON_V1_PROFILE = void 0;
|
|
4
|
-
|
|
5
|
-
exports.
|
|
6
|
-
exports.
|
|
7
|
-
|
|
8
|
-
const UNSIGNED_64_MAX = (1n << 64n) - 1n;
|
|
9
|
-
function stringifyFrameworkJsonV1(value, schema) {
|
|
10
|
-
if (value === undefined || typeof value === 'function' || typeof value === 'symbol') {
|
|
11
|
-
throw new TypeError('framework-json-v1 payload is not a JSON value.');
|
|
12
|
-
}
|
|
13
|
-
const encoded = JSON.stringify(value, frameworkJsonV1Replacer);
|
|
14
|
-
if (schema !== undefined) {
|
|
15
|
-
validateFrameworkJsonV1Value(JSON.parse(encoded), schema, '$', false);
|
|
16
|
-
}
|
|
17
|
-
return encoded;
|
|
18
|
-
}
|
|
19
|
-
// Module-level so JSON.stringify does not allocate a fresh closure per
|
|
20
|
-
// encoded message. On the root call `this` is the {'': value} wrapper, so
|
|
21
|
-
// this[key] resolves the raw (pre-toJSON) source for every key including ''.
|
|
22
|
-
function frameworkJsonV1Replacer(key, item) {
|
|
23
|
-
const source = this[key];
|
|
24
|
-
if (typeof source === 'number' && !Number.isFinite(source)) {
|
|
25
|
-
throw new TypeError('framework-json-v1 only accepts finite JSON numbers.');
|
|
26
|
-
}
|
|
27
|
-
if (typeof source === 'bigint') {
|
|
28
|
-
if (source < SIGNED_64_MIN || source > UNSIGNED_64_MAX) {
|
|
29
|
-
throw new RangeError('framework-json-v1 64-bit integer is outside the supported range.');
|
|
30
|
-
}
|
|
31
|
-
return source.toString(10);
|
|
32
|
-
}
|
|
33
|
-
if (source instanceof Uint8Array) {
|
|
34
|
-
return Buffer.from(source.buffer, source.byteOffset, source.byteLength).toString('base64');
|
|
35
|
-
}
|
|
36
|
-
if (source instanceof Date) {
|
|
37
|
-
throw new TypeError('framework-json-v1 does not implicitly encode Date values.');
|
|
38
|
-
}
|
|
39
|
-
if (typeof source === 'object' &&
|
|
40
|
-
source !== null &&
|
|
41
|
-
typeof source.toJSON === 'function') {
|
|
42
|
-
throw new TypeError('framework-json-v1 does not implicitly invoke custom toJSON methods.');
|
|
43
|
-
}
|
|
44
|
-
return item;
|
|
45
|
-
}
|
|
46
|
-
function parseFrameworkJsonV1(text, options = {}, schema) {
|
|
47
|
-
if (text.charCodeAt(0) === 0xfeff) {
|
|
48
|
-
throw new SyntaxError('framework-json-v1 does not allow a UTF-8 BOM.');
|
|
49
|
-
}
|
|
50
|
-
new JsonPropertyScanner(text, options).scan();
|
|
51
|
-
const parsed = JSON.parse(text);
|
|
52
|
-
return schema === undefined ? parsed : validateFrameworkJsonV1Value(parsed, schema, '$', true);
|
|
53
|
-
}
|
|
54
|
-
// Sticky pattern shared across scans; matching happens synchronously so the
|
|
55
|
-
// mutable lastIndex never crosses calls.
|
|
56
|
-
const NUMBER_TOKEN_PATTERN = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/uy;
|
|
57
|
-
const BASE64_PATTERN = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u;
|
|
58
|
-
const INT32_MIN = -2_147_483_648;
|
|
59
|
-
const INT32_MAX = 2_147_483_647;
|
|
60
|
-
const UINT32_MAX = 4_294_967_295;
|
|
61
|
-
function validateFrameworkJsonV1Value(value, schema, path, decode) {
|
|
62
|
-
switch (schema.type) {
|
|
63
|
-
case 'boolean':
|
|
64
|
-
if (typeof value !== 'boolean')
|
|
65
|
-
schemaFailure(path, 'a boolean');
|
|
66
|
-
return value;
|
|
67
|
-
case 'string':
|
|
68
|
-
if (typeof value !== 'string')
|
|
69
|
-
schemaFailure(path, 'a string');
|
|
70
|
-
return value;
|
|
71
|
-
case 'number':
|
|
72
|
-
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
73
|
-
schemaFailure(path, 'a finite number');
|
|
74
|
-
return value;
|
|
75
|
-
case 'int32':
|
|
76
|
-
if (!Number.isInteger(value) ||
|
|
77
|
-
value < INT32_MIN ||
|
|
78
|
-
value > INT32_MAX) {
|
|
79
|
-
schemaFailure(path, 'an int32 JSON number');
|
|
80
|
-
}
|
|
81
|
-
return value;
|
|
82
|
-
case 'uint32':
|
|
83
|
-
if (!Number.isInteger(value) || value < 0 || value > UINT32_MAX) {
|
|
84
|
-
schemaFailure(path, 'a uint32 JSON number');
|
|
85
|
-
}
|
|
86
|
-
return value;
|
|
87
|
-
case 'int64':
|
|
88
|
-
return validateDecimalInteger(value, path, true, decode);
|
|
89
|
-
case 'uint64':
|
|
90
|
-
return validateDecimalInteger(value, path, false, decode);
|
|
91
|
-
case 'bytes': {
|
|
92
|
-
if (typeof value !== 'string' || !BASE64_PATTERN.test(value)) {
|
|
93
|
-
schemaFailure(path, 'padded RFC 4648 base64');
|
|
94
|
-
}
|
|
95
|
-
const bytes = Buffer.from(value, 'base64');
|
|
96
|
-
if (bytes.toString('base64') !== value)
|
|
97
|
-
schemaFailure(path, 'canonical padded RFC 4648 base64');
|
|
98
|
-
return decode ? Uint8Array.from(bytes) : value;
|
|
99
|
-
}
|
|
100
|
-
case 'enum':
|
|
101
|
-
if (typeof value !== 'string' || !schema.names.includes(value)) {
|
|
102
|
-
schemaFailure(path, `one of ${schema.names.join(', ')}`);
|
|
103
|
-
}
|
|
104
|
-
return value;
|
|
105
|
-
case 'nullable':
|
|
106
|
-
return value === null
|
|
107
|
-
? null
|
|
108
|
-
: validateFrameworkJsonV1Value(value, schema.value, path, decode);
|
|
109
|
-
case 'array':
|
|
110
|
-
if (!Array.isArray(value))
|
|
111
|
-
schemaFailure(path, 'an array');
|
|
112
|
-
return value.map((item, index) => validateFrameworkJsonV1Value(item, schema.items, `${path}[${index}]`, decode));
|
|
113
|
-
case 'record': {
|
|
114
|
-
if (!isJsonObject(value))
|
|
115
|
-
schemaFailure(path, 'an object');
|
|
116
|
-
const result = {};
|
|
117
|
-
for (const [name, item] of Object.entries(value)) {
|
|
118
|
-
result[name] = validateFrameworkJsonV1Value(item, schema.values, `${path}.${name}`, decode);
|
|
119
|
-
}
|
|
120
|
-
return decode ? result : value;
|
|
121
|
-
}
|
|
122
|
-
case 'object': {
|
|
123
|
-
if (!isJsonObject(value))
|
|
124
|
-
schemaFailure(path, 'an object');
|
|
125
|
-
const input = value;
|
|
126
|
-
for (const name of schema.required) {
|
|
127
|
-
if (!Object.prototype.hasOwnProperty.call(input, name)) {
|
|
128
|
-
throw new TypeError(`framework-json-v1 required property '${path}.${name}' is missing.`);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
const result = {};
|
|
132
|
-
for (const [name, item] of Object.entries(input)) {
|
|
133
|
-
const propertySchema = schema.properties[name];
|
|
134
|
-
if (propertySchema === undefined) {
|
|
135
|
-
if (schema.additionalProperties === false) {
|
|
136
|
-
throw new TypeError(`framework-json-v1 property '${path}.${name}' is not allowed.`);
|
|
137
|
-
}
|
|
138
|
-
continue;
|
|
139
|
-
}
|
|
140
|
-
result[name] = validateFrameworkJsonV1Value(item, propertySchema, `${path}.${name}`, decode);
|
|
141
|
-
}
|
|
142
|
-
return decode ? result : value;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
function validateDecimalInteger(value, path, signed, decode) {
|
|
147
|
-
if (typeof value !== 'string' || !/^(?:0|[1-9][0-9]*|-[1-9][0-9]*)$/u.test(value)) {
|
|
148
|
-
schemaFailure(path, signed ? 'a canonical int64 decimal string' : 'a canonical uint64 decimal string');
|
|
149
|
-
}
|
|
150
|
-
const parsed = BigInt(value);
|
|
151
|
-
const minimum = signed ? SIGNED_64_MIN : 0n;
|
|
152
|
-
const maximum = signed ? (1n << 63n) - 1n : UNSIGNED_64_MAX;
|
|
153
|
-
if (parsed < minimum || parsed > maximum)
|
|
154
|
-
schemaFailure(path, signed ? 'an int64 value' : 'a uint64 value');
|
|
155
|
-
return decode ? parsed : value;
|
|
156
|
-
}
|
|
157
|
-
function isJsonObject(value) {
|
|
158
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
159
|
-
}
|
|
160
|
-
function schemaFailure(path, expected) {
|
|
161
|
-
throw new TypeError(`framework-json-v1 value '${path}' must be ${expected}.`);
|
|
162
|
-
}
|
|
163
|
-
class JsonPropertyScanner {
|
|
164
|
-
text;
|
|
165
|
-
options;
|
|
166
|
-
index = 0;
|
|
167
|
-
constructor(text, options) {
|
|
168
|
-
this.text = text;
|
|
169
|
-
this.options = options;
|
|
170
|
-
}
|
|
171
|
-
scan() {
|
|
172
|
-
this.skipWhitespace();
|
|
173
|
-
this.scanValue();
|
|
174
|
-
this.skipWhitespace();
|
|
175
|
-
if (this.index !== this.text.length)
|
|
176
|
-
this.fail('trailing data');
|
|
177
|
-
}
|
|
178
|
-
scanValue() {
|
|
179
|
-
this.skipWhitespace();
|
|
180
|
-
const token = this.text[this.index];
|
|
181
|
-
if (token === '{')
|
|
182
|
-
return this.scanObject();
|
|
183
|
-
if (token === '[')
|
|
184
|
-
return this.scanArray();
|
|
185
|
-
if (token === '"') {
|
|
186
|
-
this.scanString();
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
if (token === 't')
|
|
190
|
-
return this.scanLiteral('true');
|
|
191
|
-
if (token === 'f')
|
|
192
|
-
return this.scanLiteral('false');
|
|
193
|
-
if (token === 'n')
|
|
194
|
-
return this.scanLiteral('null');
|
|
195
|
-
this.scanNumber();
|
|
196
|
-
}
|
|
197
|
-
scanObject() {
|
|
198
|
-
this.index++;
|
|
199
|
-
this.skipWhitespace();
|
|
200
|
-
if (this.text[this.index] === '}') {
|
|
201
|
-
this.index++;
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
const properties = new Set();
|
|
205
|
-
for (;;) {
|
|
206
|
-
this.skipWhitespace();
|
|
207
|
-
if (this.text[this.index] !== '"')
|
|
208
|
-
this.fail('object property name');
|
|
209
|
-
const property = this.scanString();
|
|
210
|
-
if (properties.has(property)) {
|
|
211
|
-
throw new SyntaxError(`framework-json-v1 duplicate property '${property}'.`);
|
|
212
|
-
}
|
|
213
|
-
properties.add(property);
|
|
214
|
-
if (this.options.rejectPropertyName?.(property) === true) {
|
|
215
|
-
throw new SyntaxError(`framework-json-v1 property '${property}' is not allowed.`);
|
|
216
|
-
}
|
|
217
|
-
this.skipWhitespace();
|
|
218
|
-
if (this.text[this.index] !== ':')
|
|
219
|
-
this.fail("':' after object property");
|
|
220
|
-
this.index++;
|
|
221
|
-
this.scanValue();
|
|
222
|
-
this.skipWhitespace();
|
|
223
|
-
const delimiter = this.text[this.index++];
|
|
224
|
-
if (delimiter === '}')
|
|
225
|
-
return;
|
|
226
|
-
if (delimiter !== ',')
|
|
227
|
-
this.fail("',' or '}' after object property");
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
scanArray() {
|
|
231
|
-
this.index++;
|
|
232
|
-
this.skipWhitespace();
|
|
233
|
-
if (this.text[this.index] === ']') {
|
|
234
|
-
this.index++;
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
for (;;) {
|
|
238
|
-
this.scanValue();
|
|
239
|
-
this.skipWhitespace();
|
|
240
|
-
const delimiter = this.text[this.index++];
|
|
241
|
-
if (delimiter === ']')
|
|
242
|
-
return;
|
|
243
|
-
if (delimiter !== ',')
|
|
244
|
-
this.fail("',' or ']' after array item");
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
scanString() {
|
|
248
|
-
const start = this.index++;
|
|
249
|
-
let sawEscape = false;
|
|
250
|
-
for (;;) {
|
|
251
|
-
if (this.index >= this.text.length)
|
|
252
|
-
this.fail('unterminated string');
|
|
253
|
-
const character = this.text[this.index++];
|
|
254
|
-
if (character === '"') {
|
|
255
|
-
// Without escapes the token content is verbatim; the outer
|
|
256
|
-
// JSON.parse pass still rejects any raw control characters.
|
|
257
|
-
return sawEscape
|
|
258
|
-
? JSON.parse(this.text.slice(start, this.index))
|
|
259
|
-
: this.text.slice(start + 1, this.index - 1);
|
|
260
|
-
}
|
|
261
|
-
if (character === '\\') {
|
|
262
|
-
sawEscape = true;
|
|
263
|
-
if (this.index >= this.text.length)
|
|
264
|
-
this.fail('unterminated escape');
|
|
265
|
-
const escaped = this.text[this.index++];
|
|
266
|
-
if (escaped === 'u')
|
|
267
|
-
this.index += 4;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
scanLiteral(value) {
|
|
272
|
-
if (!this.text.startsWith(value, this.index))
|
|
273
|
-
this.fail(value);
|
|
274
|
-
this.index += value.length;
|
|
275
|
-
}
|
|
276
|
-
scanNumber() {
|
|
277
|
-
NUMBER_TOKEN_PATTERN.lastIndex = this.index;
|
|
278
|
-
const match = NUMBER_TOKEN_PATTERN.exec(this.text);
|
|
279
|
-
if (match === null)
|
|
280
|
-
this.fail('JSON value');
|
|
281
|
-
this.index += match[0].length;
|
|
282
|
-
}
|
|
283
|
-
skipWhitespace() {
|
|
284
|
-
for (;;) {
|
|
285
|
-
const code = this.text.charCodeAt(this.index);
|
|
286
|
-
if (code === 0x20 || code === 0x09 || code === 0x0a || code === 0x0d) {
|
|
287
|
-
this.index += 1;
|
|
288
|
-
continue;
|
|
289
|
-
}
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
fail(expected) {
|
|
294
|
-
throw new SyntaxError(`framework-json-v1 expected ${expected} at offset ${this.index}.`);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
36
|
+
exports.parseFrameworkJsonV1 = exports.stringifyFrameworkJsonV1 = exports.FRAMEWORK_JSON_V1_PROFILE = void 0;
|
|
37
|
+
const profile = __importStar(require("@zlink-systems/stream-wire/internal/json"));
|
|
38
|
+
exports.FRAMEWORK_JSON_V1_PROFILE = profile.FRAMEWORK_JSON_V1_PROFILE;
|
|
39
|
+
exports.stringifyFrameworkJsonV1 = profile.stringifyFrameworkJsonV1;
|
|
40
|
+
exports.parseFrameworkJsonV1 = profile.parseFrameworkJsonV1;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ZLinkPacketJsonContract } from '../../contracts/Handlers/JsonContract';
|
|
2
2
|
export declare function resolveFrameworkPacketName(payload: unknown, explicitPacketName: string | undefined, surface: string): string;
|
|
3
3
|
export declare function resolveFrameworkPacketJsonContract(payload: unknown, explicitPacketName?: string): ZLinkPacketJsonContract | undefined;
|
|
4
|
-
export
|
|
4
|
+
export { readFrameworkPacketJsonContract } from '@zlink-systems/stream-wire/internal/json';
|