@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
|
@@ -3,6 +3,7 @@ import type { ServiceRelocationRestoreOwner, ServiceRelocationStaging } from './
|
|
|
3
3
|
import type { ServiceRelocationEnvelope, ServiceRelocationMembership, ServiceRelocationParticipant, ServiceRelocationQueuedMessage, ServiceRelocationTimer } from './service-relocation-runtime';
|
|
4
4
|
export interface ServiceRelocationSealedWork {
|
|
5
5
|
readonly boundSessionState: Uint8Array;
|
|
6
|
+
readonly sessionBinding?: ServiceRelocationParticipant['sessionBinding'];
|
|
6
7
|
readonly queuedMessages: readonly ServiceRelocationQueuedMessage[];
|
|
7
8
|
readonly timers: readonly ServiceRelocationTimer[];
|
|
8
9
|
}
|
|
@@ -102,6 +102,7 @@ class ServiceRelocationObjectCaptureOwner {
|
|
|
102
102
|
authorityOwnerGeneration: unit.authorityOwnerGeneration,
|
|
103
103
|
applicationState: Buffer.from(await unit.captureApplicationState(signal)),
|
|
104
104
|
boundSessionState: Buffer.from(work.boundSessionState),
|
|
105
|
+
...(work.sessionBinding === undefined ? {} : { sessionBinding: work.sessionBinding }),
|
|
105
106
|
queuedMessages: work.queuedMessages.map((message) => ({
|
|
106
107
|
sequence: message.sequence,
|
|
107
108
|
payload: Buffer.from(message.payload)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ZLinkPlacementObjectKind } from '../locations/internal-location-contracts';
|
|
2
|
+
import { type RelocationEnvelopeV1 as GeneratedRelocationEnvelopeV1 } from '../protocol/service_wire_pilot_codec.generated';
|
|
2
3
|
export interface ServiceRelocationParticipant {
|
|
3
4
|
/** Wire-local participant ordinal; identity is projected from Location Store. */
|
|
4
5
|
readonly participantId?: bigint;
|
|
@@ -17,6 +18,7 @@ export interface ServiceRelocationParticipant {
|
|
|
17
18
|
readonly applicationStatePresent?: boolean;
|
|
18
19
|
readonly applicationState: Uint8Array;
|
|
19
20
|
readonly boundSessionState: Uint8Array;
|
|
21
|
+
readonly sessionBinding?: GeneratedRelocationEnvelopeV1['sessionBindings'][number];
|
|
20
22
|
readonly queuedMessages: readonly ServiceRelocationQueuedMessage[];
|
|
21
23
|
readonly timers: readonly ServiceRelocationTimer[];
|
|
22
24
|
}
|
|
@@ -480,6 +480,9 @@ function encodeServiceRelocationEnvelope(envelope, applicationVersion) {
|
|
|
480
480
|
lastCompletedScheduledIndex: nonNegativeBigInt(timer.lastScheduledIndex, 'timer scheduled index'),
|
|
481
481
|
nextScheduledAtUnixMilliseconds: nonNegativeUnixMilliseconds(timer.dueAtUnixMs, 'timer due time')
|
|
482
482
|
})),
|
|
483
|
+
sessionBindings: participants.flatMap((participant, index) => participant.sessionBinding === undefined
|
|
484
|
+
? []
|
|
485
|
+
: [{ ...participant.sessionBinding, participantId: BigInt(index + 1) }]),
|
|
483
486
|
pendingTimerTicks: pending.map((value) => ({
|
|
484
487
|
participantId: value.participantId,
|
|
485
488
|
order: value.order,
|
|
@@ -510,11 +513,20 @@ function decodeServiceRelocationEnvelope(payload, aggregateGeneration) {
|
|
|
510
513
|
if (aggregateId === undefined)
|
|
511
514
|
throw new TypeError('Invalid relocation identity.');
|
|
512
515
|
positiveBigInt(aggregateGeneration, 'aggregate generation');
|
|
516
|
+
const bindings = new Map(generated.sessionBindings.map((binding) => [binding.participantId, binding]));
|
|
517
|
+
for (const id of bindings.keys()) {
|
|
518
|
+
if (id > BigInt(generated.applicationStates.length))
|
|
519
|
+
throw new TypeError('Session binding participant is outside its inventory.');
|
|
520
|
+
}
|
|
513
521
|
const participants = generated.applicationStates.map((state, index) => {
|
|
514
522
|
if (state.participantId !== BigInt(index + 1)) {
|
|
515
523
|
throw new TypeError('Application state participant order is invalid.');
|
|
516
524
|
}
|
|
517
|
-
|
|
525
|
+
const binding = bindings.get(state.participantId);
|
|
526
|
+
return {
|
|
527
|
+
...wireParticipant(state.participantId, state.hasState, Buffer.from(state.payload)),
|
|
528
|
+
...(binding === undefined ? {} : { sessionBinding: binding })
|
|
529
|
+
};
|
|
518
530
|
});
|
|
519
531
|
const byId = new Map(participants.map((value) => [value.participantId, value]));
|
|
520
532
|
for (const work of generated.savedWork) {
|
|
@@ -343,6 +343,7 @@ export interface ServiceSpot {
|
|
|
343
343
|
flags?: number;
|
|
344
344
|
timeoutMs?: number;
|
|
345
345
|
applicationMetadata?: Buffer;
|
|
346
|
+
onAdmitted?: () => void;
|
|
346
347
|
}): MeshOperationId;
|
|
347
348
|
sendToSpot(targetNodeRid: unknown, targetSpotId: unknown, targetSpotGeneration: bigint, parts: MessageLike | readonly MessageLike[], options?: {
|
|
348
349
|
flags?: number;
|
|
@@ -354,6 +355,7 @@ export interface ServiceSpot {
|
|
|
354
355
|
timeoutMs?: number;
|
|
355
356
|
applicationMetadata?: Buffer;
|
|
356
357
|
routeFence?: ServiceDirectSpotRouteFence;
|
|
358
|
+
onAdmitted?: () => void;
|
|
357
359
|
entrySpot?: boolean;
|
|
358
360
|
}): MeshOperationId;
|
|
359
361
|
publish(channelName: string, topic: string, parts: MessageLike | readonly MessageLike[], options?: {
|
|
@@ -270,7 +270,7 @@ export declare class ServiceStatefulRuntime {
|
|
|
270
270
|
clearSubscriptions(spotId: string): void;
|
|
271
271
|
publishLogicalMulticast(channelName: string, topic: string, payload: ServiceApplicationPayload, sourceSpotId?: string): Promise<void>;
|
|
272
272
|
sendToSpot(sourceSpotId: string, requested: ServiceDirectSpotRouteFence, payload: ServiceApplicationPayload): Promise<number>;
|
|
273
|
-
requestToSpot(sourceSpotId: string, requested: ServiceDirectSpotRouteFence, payload: ServiceApplicationPayload, timeoutMs: number): ServiceStatefulPendingOperation;
|
|
273
|
+
requestToSpot(sourceSpotId: string, requested: ServiceDirectSpotRouteFence, payload: ServiceApplicationPayload, timeoutMs: number, onAdmitted?: () => void): ServiceStatefulPendingOperation;
|
|
274
274
|
sendToActor(target: ServiceActorRef, _targetNodeGeneration: bigint, _authorityOwnerGeneration: bigint, payload: ServiceApplicationPayload, sourceActor?: ServiceActorRef, boundSession?: {
|
|
275
275
|
readonly sessionRid: string;
|
|
276
276
|
readonly bindingGeneration: bigint;
|
|
@@ -278,13 +278,13 @@ export declare class ServiceStatefulRuntime {
|
|
|
278
278
|
requestToActor(target: ServiceActorRef, _targetNodeGeneration: bigint, _authorityOwnerGeneration: bigint, payload: ServiceApplicationPayload, timeoutMs: number, sourceActor?: ServiceActorRef, boundSession?: {
|
|
279
279
|
readonly sessionRid: string;
|
|
280
280
|
readonly bindingGeneration: bigint;
|
|
281
|
-
}): ServiceStatefulPendingOperation;
|
|
281
|
+
}, onAdmitted?: () => void): ServiceStatefulPendingOperation;
|
|
282
282
|
sendToInstanceSpot(route: ServiceInstanceRouteFence, payload: ServiceApplicationPayload, sourceSpotId?: string, metadataFrame?: Uint8Array, instanceIntent?: boolean): Promise<number>;
|
|
283
283
|
sendToMissingInstanceSpot(target: ServiceInstanceColdActivationTarget, payload: ServiceApplicationPayload, deadlineUnixMs: bigint, sourceSpotId?: string, metadataFrame?: Uint8Array): Promise<number>;
|
|
284
284
|
sendToMissingInstanceSpotFrame(target: ServiceInstanceColdActivationTarget, payloadFrame: Buffer, deadlineUnixMs: bigint, sourceSpotId?: string, metadataFrame?: Uint8Array): Promise<number>;
|
|
285
|
-
requestToInstanceSpot(route: ServiceInstanceRouteFence, payload: ServiceApplicationPayload, timeoutMs: number, sourceSpotId?: string, metadataFrame?: Uint8Array, instanceIntent?: boolean): ServiceStatefulPendingOperation;
|
|
285
|
+
requestToInstanceSpot(route: ServiceInstanceRouteFence, payload: ServiceApplicationPayload, timeoutMs: number, sourceSpotId?: string, metadataFrame?: Uint8Array, instanceIntent?: boolean, onAdmitted?: () => void): ServiceStatefulPendingOperation;
|
|
286
286
|
requestToMissingInstanceSpot(target: ServiceInstanceColdActivationTarget, payload: ServiceApplicationPayload, timeoutMs: number, sourceSpotId?: string, metadataFrame?: Uint8Array): ServiceStatefulPendingOperation;
|
|
287
|
-
requestToMissingInstanceSpotFrame(target: ServiceInstanceColdActivationTarget, payloadFrame: Buffer, deadlineUnixMs: bigint, sourceSpotId?: string, metadataFrame?: Uint8Array): ServiceStatefulPendingOperation;
|
|
287
|
+
requestToMissingInstanceSpotFrame(target: ServiceInstanceColdActivationTarget, payloadFrame: Buffer, deadlineUnixMs: bigint, sourceSpotId?: string, metadataFrame?: Uint8Array, onAdmitted?: () => void): ServiceStatefulPendingOperation;
|
|
288
288
|
lookupRemoteActor(targetNodeRid: string, actorId: string, timeoutMs: number): ServiceStatefulPendingOperation;
|
|
289
289
|
destroyActor(actor: ServiceActorRef, timeoutMs: number): ServiceStatefulPendingOperation;
|
|
290
290
|
joinActor(actor: ServiceActorRef, targetNodeRid: string, targetSpot: ServiceSpotRef, targetSpotGeneration: bigint, payload: ServiceApplicationPayload | undefined, timeoutMs: number): ServiceStatefulPendingOperation;
|
|
@@ -7,7 +7,7 @@ const node_async_hooks_1 = require("node:async_hooks");
|
|
|
7
7
|
const contracts_1 = require("../../contracts");
|
|
8
8
|
const service_authority_payload_codec_1 = require("./service-authority-payload-codec");
|
|
9
9
|
const ZLinkDispatchOptions_1 = require("../../contracts/Dispatch/ZLinkDispatchOptions");
|
|
10
|
-
const
|
|
10
|
+
const durable_service_request_1 = require("./durable-service-request");
|
|
11
11
|
const admission_1 = require("../admission");
|
|
12
12
|
const runtime_values_1 = require("../backend/runtime-values");
|
|
13
13
|
const message_flow_1 = require("../diagnostics/message-flow");
|
|
@@ -25,7 +25,6 @@ const service_stateful_wire_codec_1 = require("./service-stateful-wire-codec");
|
|
|
25
25
|
const service_wire_binary_primitives_1 = require("./service-wire-binary-primitives");
|
|
26
26
|
const service_wire_constants_generated_1 = require("./service-wire-constants.generated");
|
|
27
27
|
const service_wire_m6a_codec_1 = require("./service-wire-m6a-codec");
|
|
28
|
-
const STATEFUL_OPERATION_RETRY_TICK_MS = 20;
|
|
29
28
|
const MAX_NODE_TIMER_DELAY_MS = 2_147_483_647;
|
|
30
29
|
const SPOT_MOVING = 34;
|
|
31
30
|
const USER_SPOT_OPERATION_CAPACITY = 65_536;
|
|
@@ -92,7 +91,7 @@ class ServiceStatefulRuntime {
|
|
|
92
91
|
this.operations = new service_stateful_registry_1.ServiceTerminalOperationRegistry(new operation_registry_1.OperationRegistry(undefined, onPendingOperationsChanged));
|
|
93
92
|
this.registry = new service_stateful_registry_1.ServiceStatefulRegistry(nodeRid, nodeGeneration);
|
|
94
93
|
this.registry.createEntrySpot(nodeRid);
|
|
95
|
-
raw.setServiceIngress((record) => this.ingress(record));
|
|
94
|
+
raw.setServiceIngress((record) => this.ingress(record), acceptsStatefulIngress);
|
|
96
95
|
}
|
|
97
96
|
setMailboxDropHandler(handler) {
|
|
98
97
|
this.mailboxDropHandler = handler;
|
|
@@ -679,7 +678,7 @@ class ServiceStatefulRuntime {
|
|
|
679
678
|
});
|
|
680
679
|
return this.submitOneWay(target.targetNodeRid, [header, (0, service_wire_m6a_codec_1.encodeApplicationPayload)(payload)]);
|
|
681
680
|
}
|
|
682
|
-
requestToSpot(sourceSpotId, requested, payload, timeoutMs) {
|
|
681
|
+
requestToSpot(sourceSpotId, requested, payload, timeoutMs, onAdmitted) {
|
|
683
682
|
const pending = this.operations.register(timeoutMs);
|
|
684
683
|
const target = this.acceptSpotAuthority(requested);
|
|
685
684
|
if (target === undefined) {
|
|
@@ -690,7 +689,7 @@ class ServiceStatefulRuntime {
|
|
|
690
689
|
high: this.nodeGeneration,
|
|
691
690
|
low: this.nextMessageFollowOperation++
|
|
692
691
|
});
|
|
693
|
-
this.submitRequest(pending, target.targetNodeRid, [header, (0, service_wire_m6a_codec_1.encodeApplicationPayload)(payload)], timeoutMs, 'spotRequest');
|
|
692
|
+
this.submitRequest(pending, target.targetNodeRid, [header, (0, service_wire_m6a_codec_1.encodeApplicationPayload)(payload)], timeoutMs, 'spotRequest', undefined, onAdmitted);
|
|
694
693
|
return pending;
|
|
695
694
|
}
|
|
696
695
|
async sendToActor(target, _targetNodeGeneration, _authorityOwnerGeneration, payload, sourceActor, boundSession) {
|
|
@@ -705,7 +704,7 @@ class ServiceStatefulRuntime {
|
|
|
705
704
|
}, { high: this.nodeGeneration, low: this.nextMessageFollowOperation++ });
|
|
706
705
|
return this.submitOneWay(target.nodeRid, [header, (0, service_wire_m6a_codec_1.encodeApplicationPayload)(payload)]);
|
|
707
706
|
}
|
|
708
|
-
requestToActor(target, _targetNodeGeneration, _authorityOwnerGeneration, payload, timeoutMs, sourceActor, boundSession) {
|
|
707
|
+
requestToActor(target, _targetNodeGeneration, _authorityOwnerGeneration, payload, timeoutMs, sourceActor, boundSession, onAdmitted) {
|
|
709
708
|
const pending = this.operations.register(timeoutMs);
|
|
710
709
|
const route = this.tryActorFence(target);
|
|
711
710
|
if (route === undefined) {
|
|
@@ -718,7 +717,7 @@ class ServiceStatefulRuntime {
|
|
|
718
717
|
...boundSession,
|
|
719
718
|
sequence: this.nextSessionSequence++
|
|
720
719
|
}, { high: this.nodeGeneration, low: this.nextMessageFollowOperation++ });
|
|
721
|
-
this.submitRequest(pending, target.nodeRid, [header, (0, service_wire_m6a_codec_1.encodeApplicationPayload)(payload)], timeoutMs, 'actorRequest');
|
|
720
|
+
this.submitRequest(pending, target.nodeRid, [header, (0, service_wire_m6a_codec_1.encodeApplicationPayload)(payload)], timeoutMs, 'actorRequest', undefined, onAdmitted);
|
|
722
721
|
return pending;
|
|
723
722
|
}
|
|
724
723
|
async sendToInstanceSpot(route, payload, sourceSpotId, metadataFrame, instanceIntent = false) {
|
|
@@ -737,12 +736,12 @@ class ServiceStatefulRuntime {
|
|
|
737
736
|
payloadFrame
|
|
738
737
|
], metadataFrame));
|
|
739
738
|
}
|
|
740
|
-
requestToInstanceSpot(route, payload, timeoutMs, sourceSpotId, metadataFrame, instanceIntent = false) {
|
|
739
|
+
requestToInstanceSpot(route, payload, timeoutMs, sourceSpotId, metadataFrame, instanceIntent = false, onAdmitted) {
|
|
741
740
|
const pending = this.operations.register(timeoutMs);
|
|
742
741
|
this.submitRequest(pending, route.targetNodeRid, instanceOperationParts([
|
|
743
742
|
(0, service_stateful_wire_codec_1.encodeInstanceSpotHeader)(route, this.nodeGeneration, this.nodeRid, sourceSpotId, 'request', { high: operation_identity_1.ZLINK_NATIVE_CORRELATION_OPERATION_NAMESPACE, low: pending.id }, pending.id, metadataFrame !== undefined, instanceIntent),
|
|
744
743
|
(0, service_wire_m6a_codec_1.encodeApplicationPayload)(payload)
|
|
745
|
-
], metadataFrame), timeoutMs, 'instanceSpotRequest');
|
|
744
|
+
], metadataFrame), timeoutMs, 'instanceSpotRequest', undefined, onAdmitted);
|
|
746
745
|
return pending;
|
|
747
746
|
}
|
|
748
747
|
requestToMissingInstanceSpot(target, payload, timeoutMs, sourceSpotId, metadataFrame) {
|
|
@@ -750,13 +749,13 @@ class ServiceStatefulRuntime {
|
|
|
750
749
|
const payloadFrame = (0, service_wire_m6a_codec_1.encodeApplicationPayload)(payload);
|
|
751
750
|
return this.requestToMissingInstanceSpotFrame(target, payloadFrame, deadlineUnixMs, sourceSpotId, metadataFrame);
|
|
752
751
|
}
|
|
753
|
-
requestToMissingInstanceSpotFrame(target, payloadFrame, deadlineUnixMs, sourceSpotId, metadataFrame) {
|
|
752
|
+
requestToMissingInstanceSpotFrame(target, payloadFrame, deadlineUnixMs, sourceSpotId, metadataFrame, onAdmitted) {
|
|
754
753
|
const timeoutMs = remainingDeadlineMs(deadlineUnixMs);
|
|
755
754
|
const pending = this.operations.register(timeoutMs);
|
|
756
755
|
this.submitRequest(pending, target.targetNodeRid, instanceOperationParts([
|
|
757
756
|
(0, service_stateful_wire_codec_1.encodeInstanceSpotActivationHeader)(target, this.nodeGeneration, this.nodeRid, sourceSpotId, 'request', { high: operation_identity_1.ZLINK_NATIVE_CORRELATION_OPERATION_NAMESPACE, low: pending.id }, deadlineUnixMs, pending.id, metadataFrame !== undefined),
|
|
758
757
|
payloadFrame
|
|
759
|
-
], metadataFrame), timeoutMs, 'instanceSpotRequest');
|
|
758
|
+
], metadataFrame), timeoutMs, 'instanceSpotRequest', undefined, onAdmitted);
|
|
760
759
|
return pending;
|
|
761
760
|
}
|
|
762
761
|
lookupRemoteActor(targetNodeRid, actorId, timeoutMs) {
|
|
@@ -1072,25 +1071,6 @@ class ServiceStatefulRuntime {
|
|
|
1072
1071
|
this.spotMessageFollow.clear();
|
|
1073
1072
|
}
|
|
1074
1073
|
async ingress(record) {
|
|
1075
|
-
// These frozen relocation controls overlap the legacy stateful command
|
|
1076
|
-
// number range (30-34). They are bare infrastructure records and must
|
|
1077
|
-
// fall through to RawServiceMeshRuntime's relocation ingress instead of
|
|
1078
|
-
// being decoded as stateful actor/spot work.
|
|
1079
|
-
if (record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationReady ||
|
|
1080
|
-
record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationData ||
|
|
1081
|
-
record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.replyRelay ||
|
|
1082
|
-
record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationCutover) {
|
|
1083
|
-
return undefined;
|
|
1084
|
-
}
|
|
1085
|
-
if (record.command < service_stateful_wire_codec_1.M6bServiceWireCommand.spotSend ||
|
|
1086
|
-
(record.command > service_stateful_wire_codec_1.M6bServiceWireCommand.instanceSpot &&
|
|
1087
|
-
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.userSpotCreate &&
|
|
1088
|
-
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.userSpotClose &&
|
|
1089
|
-
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.actorCreate &&
|
|
1090
|
-
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.messageFollow &&
|
|
1091
|
-
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.boundSessionReplaced)) {
|
|
1092
|
-
return undefined;
|
|
1093
|
-
}
|
|
1094
1074
|
let decoded;
|
|
1095
1075
|
let canonicalActorJoin;
|
|
1096
1076
|
try {
|
|
@@ -1329,12 +1309,14 @@ class ServiceStatefulRuntime {
|
|
|
1329
1309
|
if (record.activation === 'missing' && this.asyncInstanceAuthority !== undefined) {
|
|
1330
1310
|
const ownedIngress = shareIngressOwnership(ingress);
|
|
1331
1311
|
void this.continueMissingInstanceActivation(ownedIngress, record, payloadFrame, localReply, metadataFrame).finally(() => ownedIngress.applicationJobOwner?.close());
|
|
1312
|
+
ingress.onAdmitted?.();
|
|
1332
1313
|
return 'infrastructure';
|
|
1333
1314
|
}
|
|
1334
1315
|
if (record.activation === 'ready' &&
|
|
1335
1316
|
this.needsInstanceApplicationMaterialization(ingress, record)) {
|
|
1336
1317
|
const ownedIngress = shareIngressOwnership(ingress);
|
|
1337
1318
|
void this.continueReadyInstanceMaterialization(ownedIngress, record, payloadFrame, metadataFrame).finally(() => ownedIngress.applicationJobOwner?.close());
|
|
1319
|
+
ingress.onAdmitted?.();
|
|
1338
1320
|
return 'infrastructure';
|
|
1339
1321
|
}
|
|
1340
1322
|
const spot = this.requireInstanceActivation(ingress, record);
|
|
@@ -2380,8 +2362,10 @@ class ServiceStatefulRuntime {
|
|
|
2380
2362
|
stateful,
|
|
2381
2363
|
applicationJob
|
|
2382
2364
|
});
|
|
2383
|
-
if (accepted)
|
|
2365
|
+
if (accepted) {
|
|
2366
|
+
ingress.onAdmitted?.();
|
|
2384
2367
|
return domain;
|
|
2368
|
+
}
|
|
2385
2369
|
applicationJob.close();
|
|
2386
2370
|
if (stateful.reply !== undefined) {
|
|
2387
2371
|
const result = failure((0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Mailbox owner '${owner}' no longer accepts work on this runtime.`));
|
|
@@ -2682,57 +2666,11 @@ class ServiceStatefulRuntime {
|
|
|
2682
2666
|
}
|
|
2683
2667
|
}
|
|
2684
2668
|
async requestDurableOperation(targetNodeRid, parts, correlation, operationKind, deadlineMs) {
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
stop.abort((0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RouteNotConnected, `${operationKind} target node lifecycle ended.`, true));
|
|
2689
|
-
}
|
|
2690
|
-
});
|
|
2691
|
-
let wasAdmitted = false;
|
|
2692
|
-
try {
|
|
2693
|
-
// Only durable lifecycle operations replay these frozen frames. Received
|
|
2694
|
-
// envelopes leave this loop before decoding, including failure terminals.
|
|
2695
|
-
for (;;) {
|
|
2696
|
-
this.requireOpen();
|
|
2697
|
-
stop.signal.throwIfAborted();
|
|
2698
|
-
const remainingMs = Math.ceil(deadlineMs - performance.now());
|
|
2699
|
-
if (remainingMs <= 0)
|
|
2700
|
-
throw durableOperationExhausted(operationKind, wasAdmitted);
|
|
2701
|
-
try {
|
|
2702
|
-
return await (0, abort_1.awaitWithAbort)(targetNodeRid === this.nodeRid
|
|
2703
|
-
? this.requestLocalInfrastructure(parts[0], correlation, remainingMs)
|
|
2704
|
-
: this.raw.requestService(targetNodeRid, parts, remainingMs), stop.signal);
|
|
2705
|
-
}
|
|
2706
|
-
catch (error) {
|
|
2707
|
-
stop.signal.throwIfAborted();
|
|
2708
|
-
if (!durableRequestCanReplay(error))
|
|
2709
|
-
throw error;
|
|
2710
|
-
if (durableRequestWasAdmitted(error))
|
|
2711
|
-
wasAdmitted = true;
|
|
2712
|
-
const retryDelayMs = Math.min(STATEFUL_OPERATION_RETRY_TICK_MS, deadlineMs - performance.now());
|
|
2713
|
-
if (retryDelayMs <= 0) {
|
|
2714
|
-
throw durableOperationExhausted(operationKind, wasAdmitted, error);
|
|
2715
|
-
}
|
|
2716
|
-
let timer;
|
|
2717
|
-
try {
|
|
2718
|
-
await (0, abort_1.awaitWithAbort)(new Promise((resolve) => {
|
|
2719
|
-
timer = setTimeout(resolve, retryDelayMs);
|
|
2720
|
-
}), stop.signal);
|
|
2721
|
-
}
|
|
2722
|
-
finally {
|
|
2723
|
-
if (timer !== undefined)
|
|
2724
|
-
clearTimeout(timer);
|
|
2725
|
-
}
|
|
2726
|
-
}
|
|
2727
|
-
}
|
|
2728
|
-
}
|
|
2729
|
-
catch (error) {
|
|
2730
|
-
stop.signal.throwIfAborted();
|
|
2731
|
-
throw error;
|
|
2732
|
-
}
|
|
2733
|
-
finally {
|
|
2734
|
-
unobserve();
|
|
2669
|
+
this.requireOpen();
|
|
2670
|
+
if (targetNodeRid === this.nodeRid) {
|
|
2671
|
+
return this.requestLocalInfrastructure(parts[0], correlation, Math.ceil(deadlineMs - performance.now()));
|
|
2735
2672
|
}
|
|
2673
|
+
return (0, durable_service_request_1.requestDurableService)(this.raw, targetNodeRid, parts, deadlineMs, operationKind);
|
|
2736
2674
|
}
|
|
2737
2675
|
requestLocalInfrastructure(header, requestSequence, timeoutMs) {
|
|
2738
2676
|
return new Promise((resolve, reject) => {
|
|
@@ -2838,7 +2776,7 @@ class ServiceStatefulRuntime {
|
|
|
2838
2776
|
? runtime_values_1.SubmitResult.Ok
|
|
2839
2777
|
: runtime_values_1.SubmitResult.NotConnected;
|
|
2840
2778
|
}
|
|
2841
|
-
submitRequest(pending, targetNodeRid, parts, timeoutMs, operationKind, actor) {
|
|
2779
|
+
submitRequest(pending, targetNodeRid, parts, timeoutMs, operationKind, actor, onAdmitted) {
|
|
2842
2780
|
if (targetNodeRid === this.nodeRid) {
|
|
2843
2781
|
const deadlineUnixMs = BigInt(Date.now() + Math.max(0, timeoutMs));
|
|
2844
2782
|
const capacityStop = new AbortController();
|
|
@@ -2853,6 +2791,7 @@ class ServiceStatefulRuntime {
|
|
|
2853
2791
|
flags: parts[0][service_wire_binary_primitives_1.SERVICE_WIRE_FLAGS_OFFSET],
|
|
2854
2792
|
sourceRoutingId: this.nodeRid,
|
|
2855
2793
|
requestSequence: pending.id,
|
|
2794
|
+
onAdmitted,
|
|
2856
2795
|
parts,
|
|
2857
2796
|
applicationJobOwner
|
|
2858
2797
|
};
|
|
@@ -2867,7 +2806,7 @@ class ServiceStatefulRuntime {
|
|
|
2867
2806
|
})().catch((error) => this.operations.reply(pending.id, failure(error)));
|
|
2868
2807
|
return;
|
|
2869
2808
|
}
|
|
2870
|
-
void this.raw.requestService(targetNodeRid, parts, timeoutMs).then((reply) => this.completeRemoteReply(pending, targetNodeRid, operationKind, actor, reply), (error) => this.operations.fail(pending.id, error));
|
|
2809
|
+
void this.raw.requestService(targetNodeRid, parts, timeoutMs, onAdmitted).then((reply) => this.completeRemoteReply(pending, targetNodeRid, operationKind, actor, reply), (error) => this.operations.fail(pending.id, error));
|
|
2871
2810
|
}
|
|
2872
2811
|
submitActorJoin(pending, actor, targetNodeRid, target, payload, deadlineMs, canonical) {
|
|
2873
2812
|
const actorRoute = canonical === undefined
|
|
@@ -3598,26 +3537,6 @@ function operationDeadline(deadlineUnixMs) {
|
|
|
3598
3537
|
function operationReplayExpired(replayExpiresAtMs) {
|
|
3599
3538
|
return performance.now() > replayExpiresAtMs;
|
|
3600
3539
|
}
|
|
3601
|
-
function durableRequestWasAdmitted(error) {
|
|
3602
|
-
// Request NotConnected includes Core handover of an admitted request. The
|
|
3603
|
-
// submit/request phase, rather than the result number, owns this distinction.
|
|
3604
|
-
return (0, runtime_values_1.isZLinkBackendResultError)(error) && error.operation === 'request';
|
|
3605
|
-
}
|
|
3606
|
-
function durableOperationExhausted(operationKind, wasAdmitted, cause) {
|
|
3607
|
-
return (0, framework_errors_internal_1.createInternalFrameworkException)(wasAdmitted
|
|
3608
|
-
? framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.DeadlineExceeded
|
|
3609
|
-
: framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RouteNotConnected, `${operationKind} exhausted its end-to-end deadline.`, true, cause);
|
|
3610
|
-
}
|
|
3611
|
-
function durableRequestCanReplay(error) {
|
|
3612
|
-
if (!(0, runtime_values_1.isZLinkBackendResultError)(error))
|
|
3613
|
-
return false;
|
|
3614
|
-
return error.operation === 'request'
|
|
3615
|
-
? error.result === runtime_values_1.RequestResult.NotConnected || error.result === runtime_values_1.RequestResult.TimedOut
|
|
3616
|
-
: error.result === runtime_values_1.SubmitResult.NotConnected ||
|
|
3617
|
-
error.result === runtime_values_1.SubmitResult.NotFound ||
|
|
3618
|
-
error.result === runtime_values_1.SubmitResult.NotAdmitted ||
|
|
3619
|
-
error.result === runtime_values_1.SubmitResult.Backpressured;
|
|
3620
|
-
}
|
|
3621
3540
|
function remainingDeadlineMs(deadlineUnixMs) {
|
|
3622
3541
|
const remainingMs = deadlineUnixMs - BigInt(Date.now());
|
|
3623
3542
|
if (remainingMs <= 0n) {
|
|
@@ -3944,3 +3863,25 @@ function instanceOperationParts(headerAndPayload, metadataFrame) {
|
|
|
3944
3863
|
function statefulMailboxData(record) {
|
|
3945
3864
|
return record.stateful;
|
|
3946
3865
|
}
|
|
3866
|
+
function acceptsStatefulIngress(command) {
|
|
3867
|
+
// These frozen relocation controls overlap the legacy stateful command
|
|
3868
|
+
// number range (30-34). They are bare infrastructure records and must
|
|
3869
|
+
// fall through to RawServiceMeshRuntime's relocation ingress instead of
|
|
3870
|
+
// being decoded as stateful actor/spot work.
|
|
3871
|
+
if (command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationReady ||
|
|
3872
|
+
command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationData ||
|
|
3873
|
+
command === service_stateful_wire_codec_1.M6bServiceWireCommand.replyRelay ||
|
|
3874
|
+
command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationCutover) {
|
|
3875
|
+
return false;
|
|
3876
|
+
}
|
|
3877
|
+
if (command < service_stateful_wire_codec_1.M6bServiceWireCommand.spotSend ||
|
|
3878
|
+
(command > service_stateful_wire_codec_1.M6bServiceWireCommand.instanceSpot &&
|
|
3879
|
+
command !== service_stateful_wire_codec_1.M6bServiceWireCommand.userSpotCreate &&
|
|
3880
|
+
command !== service_stateful_wire_codec_1.M6bServiceWireCommand.userSpotClose &&
|
|
3881
|
+
command !== service_stateful_wire_codec_1.M6bServiceWireCommand.actorCreate &&
|
|
3882
|
+
command !== service_stateful_wire_codec_1.M6bServiceWireCommand.messageFollow &&
|
|
3883
|
+
command !== service_stateful_wire_codec_1.M6bServiceWireCommand.boundSessionReplaced)) {
|
|
3884
|
+
return false;
|
|
3885
|
+
}
|
|
3886
|
+
return true;
|
|
3887
|
+
}
|
|
@@ -126,11 +126,6 @@ export interface ServiceMaintenanceRelocationPrepare extends ServiceWireRelocati
|
|
|
126
126
|
/** CRC-32C (Castagnoli) over the fully assembled payload bytes. */
|
|
127
127
|
readonly payloadChecksumCrc32c: number;
|
|
128
128
|
readonly applicationVersion: bigint;
|
|
129
|
-
/** NODE-INTERNAL; serialized as extra frames after canonical command 40. */
|
|
130
|
-
readonly nodeInternalBoundSessions?: readonly {
|
|
131
|
-
readonly participantKey: string;
|
|
132
|
-
readonly payload: Uint8Array;
|
|
133
|
-
}[];
|
|
134
129
|
}
|
|
135
130
|
export interface ServiceMaintenanceRelocationReady extends ServiceWireRelocationBase {
|
|
136
131
|
readonly kind: 'ready';
|
|
@@ -24,8 +24,13 @@ export interface ServiceNodeDescriptor {
|
|
|
24
24
|
readonly activeCapacityUsed: number;
|
|
25
25
|
readonly pendingCapacityUsed: number;
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
interface ServiceRouteAdmission {
|
|
28
28
|
readonly descriptor: ServiceNodeDescriptor;
|
|
29
|
+
readonly descriptorBytes?: Uint8Array;
|
|
30
|
+
readonly connectionId?: string | bigint;
|
|
31
|
+
readonly remoteAdmitReceived?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface AdmittedServicePeer extends ServiceRouteAdmission {
|
|
29
34
|
readonly connectionId: string | bigint;
|
|
30
35
|
readonly liveness?: ServiceLivenessConnection;
|
|
31
36
|
}
|
|
@@ -46,15 +51,19 @@ export declare class ServiceTopologyRegistry {
|
|
|
46
51
|
constructor(local: ServiceNodeDescriptor);
|
|
47
52
|
localDescriptor(): ServiceNodeDescriptor;
|
|
48
53
|
publishLocal(descriptor: ServiceNodeDescriptor): void;
|
|
49
|
-
admit(descriptor: ServiceNodeDescriptor, connectionId: string | bigint, expected?: ServicePeerAdmissionExpectation, admitLiveness?: () => ServiceLivenessConnection): PeerAdmissionResult;
|
|
54
|
+
admit(descriptor: ServiceNodeDescriptor, connectionId: string | bigint, expected?: ServicePeerAdmissionExpectation, admitLiveness?: () => ServiceLivenessConnection, command?: number, descriptorBytes?: Uint8Array): PeerAdmissionResult;
|
|
50
55
|
disconnect(nodeRoutingId: string, connectionId: string | bigint): boolean;
|
|
51
56
|
peer(nodeRoutingId: string): AdmittedServicePeer | undefined;
|
|
57
|
+
routeAdmission(nodeRoutingId: string): ServiceRouteAdmission | undefined;
|
|
58
|
+
admittedPeer(nodeRoutingId: string): AdmittedServicePeer | undefined;
|
|
52
59
|
peers(): readonly AdmittedServicePeer[];
|
|
53
60
|
private peersCore;
|
|
54
61
|
notRequiredPeers(): readonly ServiceNodeDescriptor[];
|
|
55
62
|
replaceDiscoveredNotRequired(descriptors: readonly ServiceNodeDescriptor[]): void;
|
|
56
63
|
forgetNotRequired(nodeRoutingId: string): void;
|
|
57
64
|
knownDescriptor(nodeRoutingId: string): ServiceNodeDescriptor | undefined;
|
|
65
|
+
isObjectClientNodeDirectTarget(nodeRoutingId: string): boolean;
|
|
66
|
+
private knownPeerDescriptor;
|
|
58
67
|
hasKnownChannelTarget(channelName: string): boolean;
|
|
59
68
|
private remember;
|
|
60
69
|
selectChannel(channelName: string, isReady?: (peer: AdmittedServicePeer) => boolean): AdmittedServicePeer | undefined;
|
|
@@ -72,3 +81,4 @@ export declare class ServiceTopologyRegistry {
|
|
|
72
81
|
}
|
|
73
82
|
export declare function validateDescriptor(descriptor: ServiceNodeDescriptor): void;
|
|
74
83
|
export declare function sameServiceNodeDescriptor(left: ServiceNodeDescriptor, right: ServiceNodeDescriptor): boolean;
|
|
84
|
+
export {};
|
|
@@ -35,13 +35,13 @@ class ServiceTopologyRegistry {
|
|
|
35
35
|
}
|
|
36
36
|
this.local = cloneDescriptor(descriptor);
|
|
37
37
|
for (const [nodeRoutingId, remote] of this.notRequiredByRid) {
|
|
38
|
-
if (!(0, route_mesh_connection_policy_1.descriptorConnectionNotRequired)(this.local, remote)) {
|
|
38
|
+
if (!(0, route_mesh_connection_policy_1.descriptorConnectionNotRequired)(this.local, remote.descriptor)) {
|
|
39
39
|
this.notRequiredByRid.delete(nodeRoutingId);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
this.rebuildSelections();
|
|
43
43
|
}
|
|
44
|
-
admit(descriptor, connectionId, expected, admitLiveness) {
|
|
44
|
+
admit(descriptor, connectionId, expected, admitLiveness, command = service_wire_constants_generated_1.ServiceWireCommand.hello, descriptorBytes) {
|
|
45
45
|
try {
|
|
46
46
|
validateDescriptor(descriptor);
|
|
47
47
|
if (typeof connectionId === 'string')
|
|
@@ -63,32 +63,46 @@ class ServiceTopologyRegistry {
|
|
|
63
63
|
descriptor.lifecycleGeneration !== expected.lifecycleGeneration)) {
|
|
64
64
|
return 'invalidDescriptor';
|
|
65
65
|
}
|
|
66
|
+
const current = this.peersByRid.get(descriptor.nodeRoutingId);
|
|
67
|
+
const previous = current ?? this.notRequiredByRid.get(descriptor.nodeRoutingId);
|
|
68
|
+
const receivedAdmit = command === service_wire_constants_generated_1.ServiceWireCommand.admit ||
|
|
69
|
+
(previous?.connectionId === connectionId && previous.remoteAdmitReceived === true);
|
|
70
|
+
if (previous !== undefined &&
|
|
71
|
+
previous.descriptor.lifecycleGeneration === descriptor.lifecycleGeneration) {
|
|
72
|
+
const existing = previous.descriptor;
|
|
73
|
+
if (descriptor.descriptorRevision < existing.descriptorRevision ||
|
|
74
|
+
(descriptor.descriptorRevision === existing.descriptorRevision &&
|
|
75
|
+
!(previous.descriptorBytes !== undefined && descriptorBytes !== undefined
|
|
76
|
+
? Buffer.compare(previous.descriptorBytes, descriptorBytes) === 0
|
|
77
|
+
: sameServiceNodeDescriptor(existing, descriptor))) ||
|
|
78
|
+
(descriptor.descriptorRevision > existing.descriptorRevision &&
|
|
79
|
+
command !== service_wire_constants_generated_1.ServiceWireCommand.update))
|
|
80
|
+
return 'staleDescriptor';
|
|
81
|
+
if (descriptor.descriptorRevision > existing.descriptorRevision &&
|
|
82
|
+
!sameImmutableDescriptor(existing, descriptor))
|
|
83
|
+
return 'invalidDescriptor';
|
|
84
|
+
}
|
|
85
|
+
else if (command === service_wire_constants_generated_1.ServiceWireCommand.update) {
|
|
86
|
+
return 'staleDescriptor';
|
|
87
|
+
}
|
|
88
|
+
const admission = {
|
|
89
|
+
descriptor: cloneDescriptor(descriptor),
|
|
90
|
+
...(descriptorBytes === undefined ? {} : { descriptorBytes: Buffer.from(descriptorBytes) }),
|
|
91
|
+
connectionId,
|
|
92
|
+
remoteAdmitReceived: receivedAdmit
|
|
93
|
+
};
|
|
66
94
|
if ((0, route_mesh_connection_policy_1.descriptorConnectionNotRequired)(this.local, descriptor)) {
|
|
67
95
|
this.peersByRid.delete(descriptor.nodeRoutingId);
|
|
68
96
|
this.remember(descriptor);
|
|
69
|
-
this.notRequiredByRid.set(descriptor.nodeRoutingId,
|
|
97
|
+
this.notRequiredByRid.set(descriptor.nodeRoutingId, admission);
|
|
70
98
|
this.rebuildSelections();
|
|
71
99
|
return 'notRequired';
|
|
72
100
|
}
|
|
73
101
|
this.notRequiredByRid.delete(descriptor.nodeRoutingId);
|
|
74
|
-
const current = this.peersByRid.get(descriptor.nodeRoutingId);
|
|
75
|
-
if (current !== undefined &&
|
|
76
|
-
current.descriptor.lifecycleGeneration === descriptor.lifecycleGeneration &&
|
|
77
|
-
descriptor.descriptorRevision > current.descriptor.descriptorRevision &&
|
|
78
|
-
!sameImmutableDescriptor(current.descriptor, descriptor)) {
|
|
79
|
-
return 'invalidDescriptor';
|
|
80
|
-
}
|
|
81
|
-
if (current !== undefined &&
|
|
82
|
-
current.descriptor.lifecycleGeneration === descriptor.lifecycleGeneration &&
|
|
83
|
-
(current.descriptor.descriptorRevision > descriptor.descriptorRevision ||
|
|
84
|
-
(current.descriptor.descriptorRevision === descriptor.descriptorRevision &&
|
|
85
|
-
!sameServiceNodeDescriptor(current.descriptor, descriptor)))) {
|
|
86
|
-
return 'staleDescriptor';
|
|
87
|
-
}
|
|
88
102
|
// Core selects the one route per RID (Core ROUTER §10.1); an admission on
|
|
89
103
|
// that route replaces the admission of a route it replaced.
|
|
90
104
|
this.peersByRid.set(descriptor.nodeRoutingId, {
|
|
91
|
-
|
|
105
|
+
...admission,
|
|
92
106
|
connectionId,
|
|
93
107
|
liveness: admitLiveness?.() ?? current?.liveness
|
|
94
108
|
});
|
|
@@ -105,9 +119,15 @@ class ServiceTopologyRegistry {
|
|
|
105
119
|
return true;
|
|
106
120
|
}
|
|
107
121
|
peer(nodeRoutingId) {
|
|
108
|
-
const peer = this.
|
|
122
|
+
const peer = this.admittedPeer(nodeRoutingId);
|
|
109
123
|
return peer === undefined ? undefined : clonePeer(peer);
|
|
110
124
|
}
|
|
125
|
+
routeAdmission(nodeRoutingId) {
|
|
126
|
+
return this.peersByRid.get(nodeRoutingId) ?? this.notRequiredByRid.get(nodeRoutingId);
|
|
127
|
+
}
|
|
128
|
+
admittedPeer(nodeRoutingId) {
|
|
129
|
+
return this.peersByRid.get(nodeRoutingId);
|
|
130
|
+
}
|
|
111
131
|
peers() {
|
|
112
132
|
return this.peersCore();
|
|
113
133
|
}
|
|
@@ -118,8 +138,8 @@ class ServiceTopologyRegistry {
|
|
|
118
138
|
}
|
|
119
139
|
notRequiredPeers() {
|
|
120
140
|
return [...this.notRequiredByRid.values()]
|
|
121
|
-
.sort((left, right) => compareOrdinal(left.nodeRoutingId, right.nodeRoutingId))
|
|
122
|
-
.map(cloneDescriptor);
|
|
141
|
+
.sort((left, right) => compareOrdinal(left.descriptor.nodeRoutingId, right.descriptor.nodeRoutingId))
|
|
142
|
+
.map((peer) => cloneDescriptor(peer.descriptor));
|
|
123
143
|
}
|
|
124
144
|
replaceDiscoveredNotRequired(descriptors) {
|
|
125
145
|
const next = new Map();
|
|
@@ -128,13 +148,16 @@ class ServiceTopologyRegistry {
|
|
|
128
148
|
if (descriptor.meshName === this.local.meshName &&
|
|
129
149
|
descriptor.nodeRoutingId !== this.local.nodeRoutingId &&
|
|
130
150
|
(0, route_mesh_connection_policy_1.descriptorConnectionNotRequired)(this.local, descriptor)) {
|
|
131
|
-
next.set(descriptor.nodeRoutingId,
|
|
151
|
+
next.set(descriptor.nodeRoutingId, {
|
|
152
|
+
...this.notRequiredByRid.get(descriptor.nodeRoutingId),
|
|
153
|
+
descriptor: cloneDescriptor(descriptor)
|
|
154
|
+
});
|
|
132
155
|
}
|
|
133
156
|
}
|
|
134
157
|
this.notRequiredByRid.clear();
|
|
135
|
-
for (const [nodeRoutingId,
|
|
136
|
-
this.notRequiredByRid.set(nodeRoutingId,
|
|
137
|
-
this.remember(descriptor);
|
|
158
|
+
for (const [nodeRoutingId, admission] of next) {
|
|
159
|
+
this.notRequiredByRid.set(nodeRoutingId, admission);
|
|
160
|
+
this.remember(admission.descriptor);
|
|
138
161
|
}
|
|
139
162
|
this.rebuildSelections();
|
|
140
163
|
}
|
|
@@ -143,10 +166,21 @@ class ServiceTopologyRegistry {
|
|
|
143
166
|
this.rebuildSelections();
|
|
144
167
|
}
|
|
145
168
|
knownDescriptor(nodeRoutingId) {
|
|
146
|
-
const
|
|
147
|
-
const descriptor = admitted ?? this.notRequiredByRid.get(nodeRoutingId) ?? this.knownByRid.get(nodeRoutingId);
|
|
169
|
+
const descriptor = this.knownPeerDescriptor(nodeRoutingId);
|
|
148
170
|
return descriptor === undefined ? undefined : cloneDescriptor(descriptor);
|
|
149
171
|
}
|
|
172
|
+
isObjectClientNodeDirectTarget(nodeRoutingId) {
|
|
173
|
+
const descriptor = nodeRoutingId === this.local.nodeRoutingId
|
|
174
|
+
? this.local
|
|
175
|
+
: this.knownPeerDescriptor(nodeRoutingId);
|
|
176
|
+
return descriptor?.objectRole === 'client';
|
|
177
|
+
}
|
|
178
|
+
knownPeerDescriptor(nodeRoutingId) {
|
|
179
|
+
const admitted = this.peersByRid.get(nodeRoutingId)?.descriptor;
|
|
180
|
+
return (admitted ??
|
|
181
|
+
this.notRequiredByRid.get(nodeRoutingId)?.descriptor ??
|
|
182
|
+
this.knownByRid.get(nodeRoutingId));
|
|
183
|
+
}
|
|
150
184
|
hasKnownChannelTarget(channelName) {
|
|
151
185
|
requireText(channelName, 'channelName');
|
|
152
186
|
return [...this.knownByRid.values()].some((descriptor) => (descriptor.state === 'serving' ||
|
|
@@ -66,11 +66,11 @@ export declare class ServiceWireProtocolError extends Error {
|
|
|
66
66
|
}
|
|
67
67
|
export declare function encodeNodeSendHeader(): Buffer;
|
|
68
68
|
export declare function encodeNodeRequestHeader(correlation: bigint): Buffer;
|
|
69
|
-
export declare function decodeNodeRequestHeader(frame: Uint8Array): bigint;
|
|
69
|
+
export declare function decodeNodeRequestHeader(frame: Uint8Array, header?: ServiceWireHeader): bigint;
|
|
70
70
|
export declare function encodeChannelSendHeader(channelName: string): Buffer;
|
|
71
|
-
export declare function decodeChannelSendHeader(frame: Uint8Array): string;
|
|
71
|
+
export declare function decodeChannelSendHeader(frame: Uint8Array, header?: ServiceWireHeader): string;
|
|
72
72
|
export declare function encodeChannelRequestHeader(correlation: bigint, channelName: string): Buffer;
|
|
73
|
-
export declare function decodeChannelRequestHeader(frame: Uint8Array): {
|
|
73
|
+
export declare function decodeChannelRequestHeader(frame: Uint8Array, header?: ServiceWireHeader): {
|
|
74
74
|
readonly correlation: bigint;
|
|
75
75
|
readonly channelName: string;
|
|
76
76
|
};
|