@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
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readFrameworkPacketJsonContract,
|
|
3
|
+
normalizePacketName
|
|
4
|
+
} from '@zlink-systems/stream-wire/internal/json';
|
|
1
5
|
import { readZLinkDecoratorMetadata } from '../../contracts/Handlers/Attributes';
|
|
2
6
|
import type { ZLinkPacketJsonContract } from '../../contracts/Handlers/JsonContract';
|
|
3
7
|
import { ZLinkConfigurationException } from '../configuration';
|
|
@@ -42,23 +46,7 @@ export function resolveFrameworkPacketJsonContract(
|
|
|
42
46
|
return readFrameworkPacketJsonContract(constructor, explicitPacketName);
|
|
43
47
|
}
|
|
44
48
|
|
|
45
|
-
export
|
|
46
|
-
type: object,
|
|
47
|
-
explicitPacketName?: string
|
|
48
|
-
): ZLinkPacketJsonContract | undefined {
|
|
49
|
-
const expectedPacketName = normalizePacketName(explicitPacketName);
|
|
50
|
-
for (const metadata of readZLinkDecoratorMetadata(type)) {
|
|
51
|
-
if (
|
|
52
|
-
metadata.kind === 'packet' &&
|
|
53
|
-
metadata.jsonContract !== undefined &&
|
|
54
|
-
(expectedPacketName === undefined ||
|
|
55
|
-
normalizePacketName(metadata.packetName) === expectedPacketName)
|
|
56
|
-
) {
|
|
57
|
-
return metadata.jsonContract;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return undefined;
|
|
61
|
-
}
|
|
49
|
+
export { readFrameworkPacketJsonContract } from '@zlink-systems/stream-wire/internal/json';
|
|
62
50
|
|
|
63
51
|
function tryDecoratorPacketName(payload: unknown): string | undefined {
|
|
64
52
|
if (typeof payload !== 'object' || payload === null) {
|
|
@@ -86,11 +74,3 @@ function tryConstructorPacketName(payload: unknown): string | undefined {
|
|
|
86
74
|
}
|
|
87
75
|
return normalizePacketName(name);
|
|
88
76
|
}
|
|
89
|
-
|
|
90
|
-
function normalizePacketName(value: unknown): string | undefined {
|
|
91
|
-
if (typeof value !== 'string') {
|
|
92
|
-
return undefined;
|
|
93
|
-
}
|
|
94
|
-
const trimmed = value.trim();
|
|
95
|
-
return trimmed.length > 0 ? trimmed : undefined;
|
|
96
|
-
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { ZLinkRequest } from '../../contracts/Handlers/Attributes';
|
|
2
|
+
|
|
3
|
+
const completedAdmission = Promise.resolve();
|
|
4
|
+
const ignoreAdmissionFailure = (): void => {};
|
|
5
|
+
|
|
6
|
+
export function createZLinkRequest<TReply>(
|
|
7
|
+
start: (onAdmitted: () => void) => Promise<TReply>,
|
|
8
|
+
deliverReply?: (reply: Promise<TReply>) => Promise<TReply>
|
|
9
|
+
): ZLinkRequest<TReply> {
|
|
10
|
+
let admitted: Promise<void> | undefined;
|
|
11
|
+
let resolveAdmission: (() => void) | undefined;
|
|
12
|
+
let rejectAdmission: ((error: unknown) => void) | undefined;
|
|
13
|
+
const confirmAdmission = (): void => {
|
|
14
|
+
admitted ??= completedAdmission;
|
|
15
|
+
resolveAdmission?.();
|
|
16
|
+
};
|
|
17
|
+
const failAdmission = (error: unknown): void => {
|
|
18
|
+
if (admitted === undefined) {
|
|
19
|
+
admitted = Promise.reject(error);
|
|
20
|
+
// Existing callers may observe only the reply Promise. Observing the
|
|
21
|
+
// rejection here leaves the public admission Promise rejected.
|
|
22
|
+
void admitted.catch(ignoreAdmissionFailure);
|
|
23
|
+
} else {
|
|
24
|
+
rejectAdmission?.(error);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const observeAdmission = (): Promise<void> => {
|
|
28
|
+
if (admitted === undefined) {
|
|
29
|
+
admitted = new Promise<void>((resolve, reject) => {
|
|
30
|
+
resolveAdmission = resolve;
|
|
31
|
+
rejectAdmission = reject;
|
|
32
|
+
});
|
|
33
|
+
void admitted.catch(ignoreAdmissionFailure);
|
|
34
|
+
}
|
|
35
|
+
return admitted;
|
|
36
|
+
};
|
|
37
|
+
let pending: Promise<TReply>;
|
|
38
|
+
try {
|
|
39
|
+
pending = start(confirmAdmission);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
pending = Promise.reject(error);
|
|
42
|
+
}
|
|
43
|
+
const observed = pending.then(
|
|
44
|
+
(value) => {
|
|
45
|
+
// A successful reply proves admission even without an observation callback.
|
|
46
|
+
confirmAdmission();
|
|
47
|
+
return value;
|
|
48
|
+
},
|
|
49
|
+
(error: unknown) => {
|
|
50
|
+
failAdmission(error);
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
const reply = deliverReply?.(observed) ?? observed;
|
|
55
|
+
return Object.defineProperty(reply, 'admitted', {
|
|
56
|
+
get: observeAdmission
|
|
57
|
+
}) as ZLinkRequest<TReply>;
|
|
58
|
+
}
|
|
@@ -18,6 +18,10 @@ export interface ZLinkSubmitResult {
|
|
|
18
18
|
readonly status: ZLinkSubmitStatus;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
export const submittedResult: ZLinkSubmitResult = Object.freeze({
|
|
22
|
+
status: ZLinkSubmitStatus.Submitted
|
|
23
|
+
});
|
|
24
|
+
|
|
21
25
|
/** Projects typed submit failure; capacity refusal has no admission wait token. */
|
|
22
26
|
export function submitToRequestResult(result: number, phase: 'submit' | 'completion'): number {
|
|
23
27
|
switch (result) {
|
|
@@ -54,7 +58,7 @@ export function classifySubmitResult(
|
|
|
54
58
|
const terminal = submitToRequestResult(result, phase);
|
|
55
59
|
switch (terminal) {
|
|
56
60
|
case RequestResult.Ok:
|
|
57
|
-
return
|
|
61
|
+
return submittedResult;
|
|
58
62
|
case RequestResult.TimedOut:
|
|
59
63
|
return { status: ZLinkSubmitStatus.TimedOut };
|
|
60
64
|
case RequestResult.NotFound:
|
|
@@ -7584,7 +7584,127 @@ function writeRelocationPendingTimerTickVector(input: RelocationPendingTimerTick
|
|
|
7584
7584
|
export function decodeRelocationPendingTimerTickVector(bytes: Uint8Array, context: ServiceWireDecoderContext): RelocationPendingTimerTickVector { const reader = new Reader(bytes); const value = readRelocationPendingTimerTickVector(reader, context, {}, 0); reader.done("relocation-pending-timer-tick-vector"); return value; }
|
|
7585
7585
|
export function encodeRelocationPendingTimerTickVector(value: RelocationPendingTimerTickVector, context: ServiceWireDecoderContext): Uint8Array { const writer = new Writer(); writeRelocationPendingTimerTickVector(value, writer, context, {}, 0); return writer.result(); }
|
|
7586
7586
|
|
|
7587
|
-
export type
|
|
7587
|
+
export type RelocationSessionBinding = { readonly participantId: NonzeroU64; readonly sessionOwnerNodeRid: Rid; readonly sessionOwnerNodeGeneration: NonzeroU64; readonly sessionOwnerId: Text8; readonly sessionOwnerLeaseGeneration: NonzeroU64; readonly sessionRid: Rid; readonly bindingGeneration: NonzeroU64 };
|
|
7588
|
+
|
|
7589
|
+
function readRelocationSessionBinding(reader: Reader, context: ServiceWireDecoderContext, enclosing: any, flags: number): RelocationSessionBinding {
|
|
7590
|
+
void context; void enclosing; void flags;
|
|
7591
|
+
const value: any = {};
|
|
7592
|
+
value["participantId"] = readNonzeroU64(reader, context, value, flags);
|
|
7593
|
+
|
|
7594
|
+
|
|
7595
|
+
value["sessionOwnerNodeRid"] = readRid(reader, context, value, flags);
|
|
7596
|
+
|
|
7597
|
+
|
|
7598
|
+
value["sessionOwnerNodeGeneration"] = readNonzeroU64(reader, context, value, flags);
|
|
7599
|
+
|
|
7600
|
+
|
|
7601
|
+
value["sessionOwnerId"] = readText8(reader, context, value, flags);
|
|
7602
|
+
|
|
7603
|
+
|
|
7604
|
+
value["sessionOwnerLeaseGeneration"] = readNonzeroU64(reader, context, value, flags);
|
|
7605
|
+
|
|
7606
|
+
|
|
7607
|
+
value["sessionRid"] = readRid(reader, context, value, flags);
|
|
7608
|
+
|
|
7609
|
+
|
|
7610
|
+
value["bindingGeneration"] = readNonzeroU64(reader, context, value, flags);
|
|
7611
|
+
|
|
7612
|
+
|
|
7613
|
+
|
|
7614
|
+
|
|
7615
|
+
return value;
|
|
7616
|
+
}
|
|
7617
|
+
function* readIncrementalRelocationSessionBinding(reader: IncrementalInput, context: ServiceWireDecoderContext, enclosing: any, flags: number): Generator<void, RelocationSessionBinding, void> {
|
|
7618
|
+
void context; void enclosing; void flags;
|
|
7619
|
+
const value: any = {};
|
|
7620
|
+
value["participantId"] = yield* readIncrementalNonzeroU64(reader, context, value, flags);
|
|
7621
|
+
|
|
7622
|
+
|
|
7623
|
+
value["sessionOwnerNodeRid"] = yield* readIncrementalRid(reader, context, value, flags);
|
|
7624
|
+
|
|
7625
|
+
|
|
7626
|
+
value["sessionOwnerNodeGeneration"] = yield* readIncrementalNonzeroU64(reader, context, value, flags);
|
|
7627
|
+
|
|
7628
|
+
|
|
7629
|
+
value["sessionOwnerId"] = yield* readIncrementalText8(reader, context, value, flags);
|
|
7630
|
+
|
|
7631
|
+
|
|
7632
|
+
value["sessionOwnerLeaseGeneration"] = yield* readIncrementalNonzeroU64(reader, context, value, flags);
|
|
7633
|
+
|
|
7634
|
+
|
|
7635
|
+
value["sessionRid"] = yield* readIncrementalRid(reader, context, value, flags);
|
|
7636
|
+
|
|
7637
|
+
|
|
7638
|
+
value["bindingGeneration"] = yield* readIncrementalNonzeroU64(reader, context, value, flags);
|
|
7639
|
+
|
|
7640
|
+
|
|
7641
|
+
|
|
7642
|
+
|
|
7643
|
+
return value;
|
|
7644
|
+
}
|
|
7645
|
+
function writeRelocationSessionBinding(input: RelocationSessionBinding, writer: Writer, context: ServiceWireDecoderContext, enclosing: any, flags: number): void {
|
|
7646
|
+
void context; void enclosing; void flags; const value: any = input;
|
|
7647
|
+
|
|
7648
|
+
|
|
7649
|
+
if (value["participantId"] === undefined) fail("participantId required");
|
|
7650
|
+
|
|
7651
|
+
|
|
7652
|
+
writeNonzeroU64(numeric(value["participantId"]), writer, context, value, flags);
|
|
7653
|
+
if (value["sessionOwnerNodeRid"] === undefined) fail("sessionOwnerNodeRid required");
|
|
7654
|
+
|
|
7655
|
+
|
|
7656
|
+
writeRid(value["sessionOwnerNodeRid"], writer, context, value, flags);
|
|
7657
|
+
if (value["sessionOwnerNodeGeneration"] === undefined) fail("sessionOwnerNodeGeneration required");
|
|
7658
|
+
|
|
7659
|
+
|
|
7660
|
+
writeNonzeroU64(numeric(value["sessionOwnerNodeGeneration"]), writer, context, value, flags);
|
|
7661
|
+
if (value["sessionOwnerId"] === undefined) fail("sessionOwnerId required");
|
|
7662
|
+
|
|
7663
|
+
|
|
7664
|
+
writeText8(value["sessionOwnerId"], writer, context, value, flags);
|
|
7665
|
+
if (value["sessionOwnerLeaseGeneration"] === undefined) fail("sessionOwnerLeaseGeneration required");
|
|
7666
|
+
|
|
7667
|
+
|
|
7668
|
+
writeNonzeroU64(numeric(value["sessionOwnerLeaseGeneration"]), writer, context, value, flags);
|
|
7669
|
+
if (value["sessionRid"] === undefined) fail("sessionRid required");
|
|
7670
|
+
|
|
7671
|
+
|
|
7672
|
+
writeRid(value["sessionRid"], writer, context, value, flags);
|
|
7673
|
+
if (value["bindingGeneration"] === undefined) fail("bindingGeneration required");
|
|
7674
|
+
|
|
7675
|
+
|
|
7676
|
+
writeNonzeroU64(numeric(value["bindingGeneration"]), writer, context, value, flags);
|
|
7677
|
+
}
|
|
7678
|
+
export function decodeRelocationSessionBinding(bytes: Uint8Array, context: ServiceWireDecoderContext): RelocationSessionBinding { const reader = new Reader(bytes); const value = readRelocationSessionBinding(reader, context, {}, 0); reader.done("relocation-session-binding"); return value; }
|
|
7679
|
+
export function encodeRelocationSessionBinding(value: RelocationSessionBinding, context: ServiceWireDecoderContext): Uint8Array { const writer = new Writer(); writeRelocationSessionBinding(value, writer, context, {}, 0); return writer.result(); }
|
|
7680
|
+
|
|
7681
|
+
export type RelocationSessionBindingVector = readonly RelocationSessionBinding[];
|
|
7682
|
+
|
|
7683
|
+
function readRelocationSessionBindingVector(reader: Reader, context: ServiceWireDecoderContext, enclosing: any, flags: number): RelocationSessionBindingVector {
|
|
7684
|
+
void context; void enclosing; void flags;
|
|
7685
|
+
const count = Number(readU32(reader, context, enclosing, flags)); if (count > 1024) fail("relocation-session-binding-vector count"); const value: any = Array.from({ length: count }, () => readRelocationSessionBinding(reader, context, enclosing, flags));
|
|
7686
|
+
try { for (let index = 1; index < value.length; ++index) if (compareResults([compareBigint(numeric(value[index - 1]["participantId"]), numeric(value[index]["participantId"]))]) >= 0) fail("relocation-session-binding-vector sorted"); } catch (error) { if (error instanceof ServiceWireProtocolError || error instanceof ServiceWireCapacityError) throw error; if (error instanceof RangeError) capacityFail("relocation-session-binding-vector constraint capacity"); throw error; }
|
|
7687
|
+
|
|
7688
|
+
return value;
|
|
7689
|
+
}
|
|
7690
|
+
function* readIncrementalRelocationSessionBindingVector(reader: IncrementalInput, context: ServiceWireDecoderContext, enclosing: any, flags: number): Generator<void, RelocationSessionBindingVector, void> {
|
|
7691
|
+
void context; void enclosing; void flags;
|
|
7692
|
+
const count = Number(yield* readIncrementalU32(reader, context, enclosing, flags)); if (count > 1024) fail("relocation-session-binding-vector count"); const value: any[] = []; for (let index = 0; index < count; ++index) { const item = yield* readIncrementalRelocationSessionBinding(reader, context, enclosing, flags); try { value.push(item); } catch { capacityFail("relocation-session-binding-vector capacity"); } }
|
|
7693
|
+
try { for (let index = 1; index < value.length; ++index) if (compareResults([compareBigint(numeric(value[index - 1]["participantId"]), numeric(value[index]["participantId"]))]) >= 0) fail("relocation-session-binding-vector sorted"); } catch (error) { if (error instanceof ServiceWireProtocolError || error instanceof ServiceWireCapacityError) throw error; if (error instanceof RangeError) capacityFail("relocation-session-binding-vector constraint capacity"); throw error; }
|
|
7694
|
+
|
|
7695
|
+
return value;
|
|
7696
|
+
}
|
|
7697
|
+
function writeRelocationSessionBindingVector(input: RelocationSessionBindingVector, writer: Writer, context: ServiceWireDecoderContext, enclosing: any, flags: number): void {
|
|
7698
|
+
void context; void enclosing; void flags; const value: any = input;
|
|
7699
|
+
if (!Array.isArray(value) || value.length > 1024) fail("relocation-session-binding-vector count");
|
|
7700
|
+
try { for (let index = 1; index < value.length; ++index) if (compareResults([compareBigint(numeric(value[index - 1]["participantId"]), numeric(value[index]["participantId"]))]) >= 0) fail("relocation-session-binding-vector sorted"); } catch (error) { if (error instanceof ServiceWireProtocolError || error instanceof ServiceWireCapacityError) throw error; if (error instanceof RangeError) capacityFail("relocation-session-binding-vector constraint capacity"); throw error; }
|
|
7701
|
+
|
|
7702
|
+
writeU32(value.length, writer, context, enclosing, flags); for (const item of value) writeRelocationSessionBinding(item, writer, context, enclosing, flags);
|
|
7703
|
+
}
|
|
7704
|
+
export function decodeRelocationSessionBindingVector(bytes: Uint8Array, context: ServiceWireDecoderContext): RelocationSessionBindingVector { const reader = new Reader(bytes); const value = readRelocationSessionBindingVector(reader, context, {}, 0); reader.done("relocation-session-binding-vector"); return value; }
|
|
7705
|
+
export function encodeRelocationSessionBindingVector(value: RelocationSessionBindingVector, context: ServiceWireDecoderContext): Uint8Array { const writer = new Writer(); writeRelocationSessionBindingVector(value, writer, context, {}, 0); return writer.result(); }
|
|
7706
|
+
|
|
7707
|
+
export type RelocationEnvelopeV1 = { readonly relocation: RelocationId; readonly object: RelocationObjectIdentity; readonly applicationVersion: ApplicationVersion; readonly applicationStates: RelocationParticipantApplicationStateVector; readonly savedWork: SavedWorkVector; readonly timerRegistrations: RelocationTimerRegistrationVector; readonly pendingTimerTicks: RelocationPendingTimerTickVector; readonly sessionBindings: RelocationSessionBindingVector };
|
|
7588
7708
|
|
|
7589
7709
|
function readRelocationEnvelopeV1(reader: Reader, context: ServiceWireDecoderContext, enclosing: any, flags: number): RelocationEnvelopeV1 {
|
|
7590
7710
|
void context; void enclosing; void flags;
|
|
@@ -7610,6 +7730,9 @@ function readRelocationEnvelopeV1(reader: Reader, context: ServiceWireDecoderCon
|
|
|
7610
7730
|
value["pendingTimerTicks"] = readRelocationPendingTimerTickVector(reader, context, value, flags);
|
|
7611
7731
|
|
|
7612
7732
|
|
|
7733
|
+
value["sessionBindings"] = readRelocationSessionBindingVector(reader, context, value, flags);
|
|
7734
|
+
|
|
7735
|
+
|
|
7613
7736
|
|
|
7614
7737
|
|
|
7615
7738
|
return value;
|
|
@@ -7638,6 +7761,9 @@ function* readIncrementalRelocationEnvelopeV1(reader: IncrementalInput, context:
|
|
|
7638
7761
|
value["pendingTimerTicks"] = yield* readIncrementalRelocationPendingTimerTickVector(reader, context, value, flags);
|
|
7639
7762
|
|
|
7640
7763
|
|
|
7764
|
+
value["sessionBindings"] = yield* readIncrementalRelocationSessionBindingVector(reader, context, value, flags);
|
|
7765
|
+
|
|
7766
|
+
|
|
7641
7767
|
|
|
7642
7768
|
|
|
7643
7769
|
return value;
|
|
@@ -7674,6 +7800,10 @@ function writeRelocationEnvelopeV1(input: RelocationEnvelopeV1, writer: Writer,
|
|
|
7674
7800
|
|
|
7675
7801
|
|
|
7676
7802
|
writeRelocationPendingTimerTickVector(value["pendingTimerTicks"], writer, context, value, flags);
|
|
7803
|
+
if (value["sessionBindings"] === undefined) fail("sessionBindings required");
|
|
7804
|
+
|
|
7805
|
+
|
|
7806
|
+
writeRelocationSessionBindingVector(value["sessionBindings"], writer, context, value, flags);
|
|
7677
7807
|
}
|
|
7678
7808
|
export function decodeRelocationEnvelopeV1(bytes: Uint8Array, context: ServiceWireDecoderContext): RelocationEnvelopeV1 { const reader = new Reader(bytes); const value = readRelocationEnvelopeV1(reader, context, {}, 0); reader.done("relocation-envelope-v1"); return value; }
|
|
7679
7809
|
export function encodeRelocationEnvelopeV1(value: RelocationEnvelopeV1, context: ServiceWireDecoderContext): Uint8Array { const writer = new Writer(); writeRelocationEnvelopeV1(value, writer, context, {}, 0); return writer.result(); }
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// <auto-generated> DO NOT EDIT. schema-sha256:
|
|
1
|
+
// <auto-generated> DO NOT EDIT. schema-sha256: c9a343a64d205ce666d1e866df72538c11b3b52cf4bff41562e46d4aeaf20df6
|
|
2
2
|
export interface ServiceWireRouteFence { readonly id: string; readonly generation: bigint; readonly targetNodeRid: Uint8Array; readonly targetNodeGeneration: bigint; readonly expectedAuthorityOwnerGeneration: bigint; readonly expectedOwnerLeaseGeneration: bigint; }
|
|
3
3
|
export interface ApplicationPayloadEnvelopeV1 { readonly packetName: string; readonly contentType: string; readonly payload: Uint8Array; }
|
|
4
4
|
export interface ActorJoin28 { readonly correlation: bigint; readonly actor: ServiceWireRouteFence; readonly entry: boolean; readonly targetSpot: ServiceWireRouteFence; readonly payload?: ApplicationPayloadEnvelopeV1; }
|
|
@@ -19,7 +19,7 @@ export interface ServiceWireRouteFence { readonly id: string; readonly generatio
|
|
|
19
19
|
export function encodeActorJoin28(value: ActorJoin28): readonly Uint8Array[] { const out=[90,77,1,28,0]; if(value.correlation===0n) throw new RangeError("correlation"); u64(out,value.correlation); fence(out,value.actor); out.push(value.entry?1:0); fence(out,value.targetSpot); return value.payload===undefined?[Uint8Array.from(out)]:[Uint8Array.from(out),encodePayload(value.payload)]; }
|
|
20
20
|
export function decodeActorJoin28(frames: readonly Uint8Array[]): ActorJoin28 { if(frames.length<1||frames.length>2)throw new RangeError("actorJoin frames");const bytes=frames[0]!; const at={value:0}; if(bytes.length<5 || bytes[at.value++]!==90 || bytes[at.value++]!==77 || bytes[at.value++]!==1 || bytes[at.value++]!==28 || bytes[at.value++]!==0) throw new RangeError("actorJoin header"); const correlation=read64(bytes,at); const actor=readFence(bytes,at); const entry=bytes[at.value++]; const targetSpot=readFence(bytes,at); if(correlation===0n || entry>1 || at.value!==bytes.length) throw new RangeError("actorJoin body"); const payload=frames.length===2?decodePayload(frames[1]!):undefined; return payload===undefined?{ correlation, actor, entry:entry===1, targetSpot }:{ correlation, actor, entry:entry===1, targetSpot,payload }; }
|
|
21
21
|
export type RelocationObjectIdentity = { readonly objectKind:"actor";readonly actorId:string;readonly objectGeneration:bigint;readonly expectedAuthorityOwnerGeneration:bigint; }|{ readonly objectKind:"userSpot";readonly spotId:string;readonly objectGeneration:bigint;readonly expectedAuthorityOwnerGeneration:bigint; }|{ readonly objectKind:"instanceSpot";readonly instanceType:string;readonly spotId:string;readonly objectGeneration:bigint; };
|
|
22
|
-
export interface RelocationEnvelopeV1 { readonly relocationHigh: bigint; readonly relocationLow: bigint; readonly object: RelocationObjectIdentity; readonly applicationVersion: bigint; readonly applicationStates: readonly { readonly participantId: bigint; readonly hasState: boolean; readonly payload: Uint8Array; }[]; readonly savedWork: readonly { readonly participantId: bigint; readonly order: bigint; readonly frozenRecord: Uint8Array; }[]; readonly timerRegistrations: readonly { readonly participantId: bigint; readonly name: string; readonly handlerType: string; readonly periodMilliseconds: bigint; readonly overrunPolicy: 1|2|3; readonly maxCatchUpTicks: bigint; readonly stopOnUnhandledException: boolean; readonly lastCompletedDeliveryIndex: bigint; readonly lastCompletedScheduledIndex: bigint; readonly nextScheduledAtUnixMilliseconds: bigint; }[]; readonly pendingTimerTicks: readonly { readonly participantId: bigint; readonly order: bigint; readonly timerName: string; readonly deliveryIndex: bigint; readonly scheduledIndex: bigint; readonly scheduledAtUnixMilliseconds: bigint; readonly skippedTicks: bigint; }[]; }
|
|
22
|
+
export interface RelocationEnvelopeV1 { readonly relocationHigh: bigint; readonly relocationLow: bigint; readonly object: RelocationObjectIdentity; readonly applicationVersion: bigint; readonly applicationStates: readonly { readonly participantId: bigint; readonly hasState: boolean; readonly payload: Uint8Array; }[]; readonly savedWork: readonly { readonly participantId: bigint; readonly order: bigint; readonly frozenRecord: Uint8Array; }[]; readonly timerRegistrations: readonly { readonly participantId: bigint; readonly name: string; readonly handlerType: string; readonly periodMilliseconds: bigint; readonly overrunPolicy: 1|2|3; readonly maxCatchUpTicks: bigint; readonly stopOnUnhandledException: boolean; readonly lastCompletedDeliveryIndex: bigint; readonly lastCompletedScheduledIndex: bigint; readonly nextScheduledAtUnixMilliseconds: bigint; }[]; readonly pendingTimerTicks: readonly { readonly participantId: bigint; readonly order: bigint; readonly timerName: string; readonly deliveryIndex: bigint; readonly scheduledIndex: bigint; readonly scheduledAtUnixMilliseconds: bigint; readonly skippedTicks: bigint; }[]; readonly sessionBindings: readonly {readonly participantId:bigint;readonly sessionOwnerNodeRid:Uint8Array;readonly sessionOwnerNodeGeneration:bigint;readonly sessionOwnerId:string;readonly sessionOwnerLeaseGeneration:bigint;readonly sessionRid:Uint8Array;readonly bindingGeneration:bigint;}[]; }
|
|
23
23
|
export interface RelocationDataChunkV1 { readonly order:number;readonly data:Uint8Array; }
|
|
24
24
|
export interface RelocationChunkEntryV1 { readonly order:number;readonly reference:string;readonly length:bigint;readonly checksumCrc32c:number; }
|
|
25
25
|
export interface RelocationManifestV1 { readonly logicalFormatVersion:1;readonly totalLength:bigint;readonly totalChecksumCrc32c:number;readonly inventoryDigestSha256:Uint8Array;readonly chunks:readonly RelocationChunkEntryV1[]; }
|
|
@@ -51,8 +51,8 @@ function skipFrozenRecord(bytes:Uint8Array,at:{value:number}):void{const kind=re
|
|
|
51
51
|
function compareUtf8(a:string,b:string):number{const x=text.encode(a),y=text.encode(b),n=Math.min(x.length,y.length);for(let i=0;i<n;i++)if(x[i]!==y[i])return x[i]!-y[i]!;return x.length-y.length;}
|
|
52
52
|
function writeRelocationObject(out:number[],value:RelocationObjectIdentity):void{const kind=value.objectKind==="actor"?1:value.objectKind==="userSpot"?2:3;out.push(kind);body16(out,b=>{if(value.objectKind==="actor"){text8(b,value.actorId);if(value.objectGeneration===0n||value.expectedAuthorityOwnerGeneration===0n)throw new RangeError("object");u64(b,value.objectGeneration);u64(b,value.expectedAuthorityOwnerGeneration);}else if(value.objectKind==="userSpot"){text8(b,value.spotId);if(value.objectGeneration===0n||value.expectedAuthorityOwnerGeneration===0n)throw new RangeError("object");u64(b,value.objectGeneration);u64(b,value.expectedAuthorityOwnerGeneration);}else{text8(b,value.instanceType);text8(b,value.spotId);if(value.objectGeneration===0n)throw new RangeError("object");u64(b,value.objectGeneration);}});}
|
|
53
53
|
function readRelocationObject(bytes:Uint8Array,at:{value:number}):RelocationObjectIdentity{const kind=read8(bytes,at),end=boundedEnd(bytes,at,read16(bytes,at),"relocation object");let value:RelocationObjectIdentity;if(kind===1)value={objectKind:"actor",actorId:readText8(bytes,at),objectGeneration:nonzero64(bytes,at,"object generation"),expectedAuthorityOwnerGeneration:nonzero64(bytes,at,"authority generation")};else if(kind===2)value={objectKind:"userSpot",spotId:readText8(bytes,at),objectGeneration:nonzero64(bytes,at,"object generation"),expectedAuthorityOwnerGeneration:nonzero64(bytes,at,"authority generation")};else if(kind===3)value={objectKind:"instanceSpot",instanceType:readText8(bytes,at),spotId:readText8(bytes,at),objectGeneration:nonzero64(bytes,at,"object generation")};else throw new RangeError("object kind");exactEnd(at,end,"relocation object");return value;}
|
|
54
|
-
export function encodeRelocationEnvelopeV1(value:RelocationEnvelopeV1):Uint8Array{const out:number[]=[];if(value.relocationHigh===0n&&value.relocationLow===0n)throw new RangeError("relocation");u64(out,value.relocationHigh);u64(out,value.relocationLow);writeRelocationObject(out,value.object);if(value.applicationVersion<0n||value.applicationVersion>9223372036854775807n)throw new RangeError("application version");u64(out,value.applicationVersion);sorted(value.applicationStates,(a,b)=>a.participantId<b.participantId?-1:a.participantId>b.participantId?1:0,"applicationStates");if(value.applicationStates.length===0)throw new RangeError("applicationStates");u32(out,value.applicationStates.length);for(const s of value.applicationStates){if(s.participantId===0n)throw new RangeError("participant");u64(out,s.participantId);out.push(s.hasState?1:0);body64(out,b=>{if(s.hasState)bytes64(b,s.payload);else if(s.payload.length!==0)throw new RangeError("absent state payload");});}sorted(value.savedWork,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"savedWork");u32(out,value.savedWork.length);for(const w of value.savedWork){if(w.participantId===0n||w.order===0n)throw new RangeError("saved work");const at={value:0};skipFrozenRecord(w.frozenRecord,at);exactEnd(at,w.frozenRecord.length,"frozen record");u64(out,w.participantId);u64(out,w.order);appendBytes(out,w.frozenRecord);}sorted(value.timerRegistrations,(a,b)=>a.participantId===b.participantId?compareUtf8(a.name,b.name):a.participantId<b.participantId?-1:1,"timerRegistrations");u32(out,value.timerRegistrations.length);for(const t of value.timerRegistrations){if(t.participantId===0n||t.periodMilliseconds===0n||t.maxCatchUpTicks===0n||t.overrunPolicy<1||t.overrunPolicy>3)throw new RangeError("timer");u64(out,t.participantId);text8(out,t.name);text8(out,t.handlerType);u64(out,t.periodMilliseconds);out.push(t.overrunPolicy);u64(out,t.maxCatchUpTicks);out.push(t.stopOnUnhandledException?1:0);u64(out,t.lastCompletedDeliveryIndex);u64(out,t.lastCompletedScheduledIndex);u64(out,t.nextScheduledAtUnixMilliseconds);}sorted(value.pendingTimerTicks,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"pendingTimerTicks");u32(out,value.pendingTimerTicks.length);for(const p of value.pendingTimerTicks){if(p.participantId===0n||p.order===0n||p.deliveryIndex===0n||p.scheduledIndex===0n)throw new RangeError("pending timer");u64(out,p.participantId);u64(out,p.order);text8(out,p.timerName);u64(out,p.deliveryIndex);u64(out,p.scheduledIndex);u64(out,p.scheduledAtUnixMilliseconds);u64(out,p.skippedTicks);}if(out.length>274877906944)throw new RangeError("relocation logical bytes");return Uint8Array.from(out);}
|
|
55
|
-
export function decodeRelocationEnvelopeV1(chunks:readonly Uint8Array[]):RelocationEnvelopeV1{const n=chunks.reduce((s,c)=>s+c.length,0);if(n>274877906944)throw new RangeError("relocation logical bytes");const bytes=new Uint8Array(n);let offset=0;for(const c of chunks){bytes.set(c,offset);offset+=c.length;}const at={value:0},relocationHigh=read64(bytes,at),relocationLow=read64(bytes,at);if(relocationHigh===0n&&relocationLow===0n)throw new RangeError("relocation");const object=readRelocationObject(bytes,at),applicationVersion=read64(bytes,at);if(applicationVersion>9223372036854775807n)throw new RangeError("application version");const applicationStates:RelocationEnvelopeV1["applicationStates"][number][]=[];const stateCount=read32(bytes,at);if(stateCount===0)throw new RangeError("applicationStates");for(let i=0,count=stateCount;i<count;i++){const participantId=nonzero64(bytes,at,"participant"),has=read8(bytes,at),end=boundedEnd(bytes,at,Number(read64(bytes,at)),"application state");if(has>1)throw new RangeError("application state");let payload=new Uint8Array();if(has===1)payload=take(bytes,at,Number(read64(bytes,at)),"state payload");exactEnd(at,end,"application state");applicationStates.push({participantId,hasState:has===1,payload});}const participants=new Set(applicationStates.map((s)=>s.participantId));const savedWork:RelocationEnvelopeV1["savedWork"][number][]=[];for(let i=0,count=read32(bytes,at);i<count;i++){const participantId=nonzero64(bytes,at,"participant");if(!participants.has(participantId))throw new RangeError("saved work participant");const order=nonzero64(bytes,at,"order"),start=at.value;skipFrozenRecord(bytes,at);savedWork.push({participantId,order,frozenRecord:bytes.slice(start,at.value)});}const timerRegistrations:RelocationEnvelopeV1["timerRegistrations"][number][]=[],registeredTimerNames=new Map<bigint,Set<string>>();for(let i=0,count=read32(bytes,at);i<count;i++){const participantId=nonzero64(bytes,at,"participant");if(!participants.has(participantId))throw new RangeError("timer participant");const name=readText8(bytes,at),handlerType=readText8(bytes,at),periodMilliseconds=nonzero64(bytes,at,"period"),overrunPolicy=read8(bytes,at);if(overrunPolicy<1||overrunPolicy>3)throw new RangeError("overrun policy");const maxCatchUpTicks=nonzero64(bytes,at,"catch-up"),stop=read8(bytes,at);if(stop>1)throw new RangeError("stop flag");let names=registeredTimerNames.get(participantId);if(names===undefined){names=new Set<string>();registeredTimerNames.set(participantId,names);}names.add(name);timerRegistrations.push({participantId,name,handlerType,periodMilliseconds,overrunPolicy:overrunPolicy as 1|2|3,maxCatchUpTicks,stopOnUnhandledException:stop===1,lastCompletedDeliveryIndex:read64(bytes,at),lastCompletedScheduledIndex:read64(bytes,at),nextScheduledAtUnixMilliseconds:read64(bytes,at)});}const pendingTimerTicks:RelocationEnvelopeV1["pendingTimerTicks"][number][]=[];for(let i=0,count=read32(bytes,at);i<count;i++){const participantId=nonzero64(bytes,at,"participant");if(!participants.has(participantId))throw new RangeError("pending timer participant");const order=nonzero64(bytes,at,"order"),timerName=readText8(bytes,at);if(registeredTimerNames.get(participantId)?.has(timerName)!==true)throw new RangeError("pending timer registration");pendingTimerTicks.push({participantId,order,timerName,deliveryIndex:nonzero64(bytes,at,"delivery"),scheduledIndex:nonzero64(bytes,at,"scheduled"),scheduledAtUnixMilliseconds:read64(bytes,at),skippedTicks:read64(bytes,at)});}exactEnd(at,bytes.length,"relocation envelope");sorted(applicationStates,(a,b)=>a.participantId<b.participantId?-1:a.participantId>b.participantId?1:0,"applicationStates");sorted(savedWork,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"savedWork");sorted(timerRegistrations,(a,b)=>a.participantId===b.participantId?compareUtf8(a.name,b.name):a.participantId<b.participantId?-1:1,"timerRegistrations");sorted(pendingTimerTicks,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"pendingTimerTicks");return{relocationHigh,relocationLow,object,applicationVersion,applicationStates,savedWork,timerRegistrations,pendingTimerTicks};}
|
|
54
|
+
export function encodeRelocationEnvelopeV1(value:RelocationEnvelopeV1):Uint8Array{const out:number[]=[];if(value.relocationHigh===0n&&value.relocationLow===0n)throw new RangeError("relocation");u64(out,value.relocationHigh);u64(out,value.relocationLow);writeRelocationObject(out,value.object);if(value.applicationVersion<0n||value.applicationVersion>9223372036854775807n)throw new RangeError("application version");u64(out,value.applicationVersion);sorted(value.applicationStates,(a,b)=>a.participantId<b.participantId?-1:a.participantId>b.participantId?1:0,"applicationStates");if(value.applicationStates.length===0)throw new RangeError("applicationStates");u32(out,value.applicationStates.length);for(const s of value.applicationStates){if(s.participantId===0n)throw new RangeError("participant");u64(out,s.participantId);out.push(s.hasState?1:0);body64(out,b=>{if(s.hasState)bytes64(b,s.payload);else if(s.payload.length!==0)throw new RangeError("absent state payload");});}sorted(value.savedWork,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"savedWork");u32(out,value.savedWork.length);for(const w of value.savedWork){if(w.participantId===0n||w.order===0n)throw new RangeError("saved work");const at={value:0};skipFrozenRecord(w.frozenRecord,at);exactEnd(at,w.frozenRecord.length,"frozen record");u64(out,w.participantId);u64(out,w.order);appendBytes(out,w.frozenRecord);}sorted(value.timerRegistrations,(a,b)=>a.participantId===b.participantId?compareUtf8(a.name,b.name):a.participantId<b.participantId?-1:1,"timerRegistrations");u32(out,value.timerRegistrations.length);for(const t of value.timerRegistrations){if(t.participantId===0n||t.periodMilliseconds===0n||t.maxCatchUpTicks===0n||t.overrunPolicy<1||t.overrunPolicy>3)throw new RangeError("timer");u64(out,t.participantId);text8(out,t.name);text8(out,t.handlerType);u64(out,t.periodMilliseconds);out.push(t.overrunPolicy);u64(out,t.maxCatchUpTicks);out.push(t.stopOnUnhandledException?1:0);u64(out,t.lastCompletedDeliveryIndex);u64(out,t.lastCompletedScheduledIndex);u64(out,t.nextScheduledAtUnixMilliseconds);}sorted(value.pendingTimerTicks,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"pendingTimerTicks");u32(out,value.pendingTimerTicks.length);for(const p of value.pendingTimerTicks){if(p.participantId===0n||p.order===0n||p.deliveryIndex===0n||p.scheduledIndex===0n)throw new RangeError("pending timer");u64(out,p.participantId);u64(out,p.order);text8(out,p.timerName);u64(out,p.deliveryIndex);u64(out,p.scheduledIndex);u64(out,p.scheduledAtUnixMilliseconds);u64(out,p.skippedTicks);}sorted(value.sessionBindings,(a,b)=>a.participantId<b.participantId?-1:a.participantId>b.participantId?1:0,"sessionBindings");if(value.sessionBindings.length>1024)throw new RangeError("bindings count");u32(out,value.sessionBindings.length);for(const b of value.sessionBindings){if(b.participantId===0n||b.sessionOwnerNodeGeneration===0n||b.sessionOwnerLeaseGeneration===0n||b.bindingGeneration===0n)throw new RangeError("binding");u64(out,b.participantId);rid(out,b.sessionOwnerNodeRid);u64(out,b.sessionOwnerNodeGeneration);text8(out,b.sessionOwnerId);u64(out,b.sessionOwnerLeaseGeneration);rid(out,b.sessionRid);u64(out,b.bindingGeneration);}if(out.length>274877906944)throw new RangeError("relocation logical bytes");return Uint8Array.from(out);}
|
|
55
|
+
export function decodeRelocationEnvelopeV1(chunks:readonly Uint8Array[]):RelocationEnvelopeV1{const n=chunks.reduce((s,c)=>s+c.length,0);if(n>274877906944)throw new RangeError("relocation logical bytes");const bytes=new Uint8Array(n);let offset=0;for(const c of chunks){bytes.set(c,offset);offset+=c.length;}const at={value:0},relocationHigh=read64(bytes,at),relocationLow=read64(bytes,at);if(relocationHigh===0n&&relocationLow===0n)throw new RangeError("relocation");const object=readRelocationObject(bytes,at),applicationVersion=read64(bytes,at);if(applicationVersion>9223372036854775807n)throw new RangeError("application version");const applicationStates:RelocationEnvelopeV1["applicationStates"][number][]=[];const stateCount=read32(bytes,at);if(stateCount===0)throw new RangeError("applicationStates");for(let i=0,count=stateCount;i<count;i++){const participantId=nonzero64(bytes,at,"participant"),has=read8(bytes,at),end=boundedEnd(bytes,at,Number(read64(bytes,at)),"application state");if(has>1)throw new RangeError("application state");let payload=new Uint8Array();if(has===1)payload=take(bytes,at,Number(read64(bytes,at)),"state payload");exactEnd(at,end,"application state");applicationStates.push({participantId,hasState:has===1,payload});}const participants=new Set(applicationStates.map((s)=>s.participantId));const savedWork:RelocationEnvelopeV1["savedWork"][number][]=[];for(let i=0,count=read32(bytes,at);i<count;i++){const participantId=nonzero64(bytes,at,"participant");if(!participants.has(participantId))throw new RangeError("saved work participant");const order=nonzero64(bytes,at,"order"),start=at.value;skipFrozenRecord(bytes,at);savedWork.push({participantId,order,frozenRecord:bytes.slice(start,at.value)});}const timerRegistrations:RelocationEnvelopeV1["timerRegistrations"][number][]=[],registeredTimerNames=new Map<bigint,Set<string>>();for(let i=0,count=read32(bytes,at);i<count;i++){const participantId=nonzero64(bytes,at,"participant");if(!participants.has(participantId))throw new RangeError("timer participant");const name=readText8(bytes,at),handlerType=readText8(bytes,at),periodMilliseconds=nonzero64(bytes,at,"period"),overrunPolicy=read8(bytes,at);if(overrunPolicy<1||overrunPolicy>3)throw new RangeError("overrun policy");const maxCatchUpTicks=nonzero64(bytes,at,"catch-up"),stop=read8(bytes,at);if(stop>1)throw new RangeError("stop flag");let names=registeredTimerNames.get(participantId);if(names===undefined){names=new Set<string>();registeredTimerNames.set(participantId,names);}names.add(name);timerRegistrations.push({participantId,name,handlerType,periodMilliseconds,overrunPolicy:overrunPolicy as 1|2|3,maxCatchUpTicks,stopOnUnhandledException:stop===1,lastCompletedDeliveryIndex:read64(bytes,at),lastCompletedScheduledIndex:read64(bytes,at),nextScheduledAtUnixMilliseconds:read64(bytes,at)});}const pendingTimerTicks:RelocationEnvelopeV1["pendingTimerTicks"][number][]=[];for(let i=0,count=read32(bytes,at);i<count;i++){const participantId=nonzero64(bytes,at,"participant");if(!participants.has(participantId))throw new RangeError("pending timer participant");const order=nonzero64(bytes,at,"order"),timerName=readText8(bytes,at);if(registeredTimerNames.get(participantId)?.has(timerName)!==true)throw new RangeError("pending timer registration");pendingTimerTicks.push({participantId,order,timerName,deliveryIndex:nonzero64(bytes,at,"delivery"),scheduledIndex:nonzero64(bytes,at,"scheduled"),scheduledAtUnixMilliseconds:read64(bytes,at),skippedTicks:read64(bytes,at)});}const sessionBindings:RelocationEnvelopeV1["sessionBindings"][number][]=[];const bindingCount=read32(bytes,at);if(bindingCount>1024)throw new RangeError("bindings count");for(let n=0;n<bindingCount;n++)sessionBindings.push({participantId:nonzero64(bytes,at,"participant"),sessionOwnerNodeRid:readRid(bytes,at),sessionOwnerNodeGeneration:nonzero64(bytes,at,"session node"),sessionOwnerId:readText8(bytes,at),sessionOwnerLeaseGeneration:nonzero64(bytes,at,"session lease"),sessionRid:readRid(bytes,at),bindingGeneration:nonzero64(bytes,at,"binding")});sorted(sessionBindings,(a,b)=>a.participantId<b.participantId?-1:a.participantId>b.participantId?1:0,"sessionBindings");exactEnd(at,bytes.length,"relocation envelope");sorted(applicationStates,(a,b)=>a.participantId<b.participantId?-1:a.participantId>b.participantId?1:0,"applicationStates");sorted(savedWork,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"savedWork");sorted(timerRegistrations,(a,b)=>a.participantId===b.participantId?compareUtf8(a.name,b.name):a.participantId<b.participantId?-1:1,"timerRegistrations");sorted(pendingTimerTicks,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"pendingTimerTicks");return{relocationHigh,relocationLow,object,applicationVersion,applicationStates,savedWork,timerRegistrations,pendingTimerTicks,sessionBindings};}
|
|
56
56
|
function crc32c(bytes:Uint8Array):number{let crc=0xffffffff;for(const octet of bytes){crc^=octet;for(let bit=0;bit<8;bit++)crc=(crc>>>1)^((crc&1)!==0?0x82f63b78:0);}return(~crc)>>>0;}
|
|
57
57
|
function encodeDurable(magic:readonly number[],body:readonly number[],maximum:number):Uint8Array{const out=[...magic,1,0,0];u32(out,body.length);appendBytes(out,body);if(out.length+4>maximum)throw new RangeError("durable format bytes");u32(out,crc32c(Uint8Array.from(out)));return Uint8Array.from(out);}
|
|
58
58
|
function decodeDurable(bytes:Uint8Array,magic:readonly number[],maximum:number):Uint8Array{if(bytes.length>maximum||bytes.length<15||magic.some((v,i)=>bytes[i]!==v)||bytes[4]!==1||bytes[5]!==0||bytes[6]!==0)throw new RangeError("durable header");const at={value:7},length=read32(bytes,at),end=boundedEnd(bytes,at,length,"durable body");if(end+4!==bytes.length)throw new RangeError("durable length");const body=bytes.slice(at.value,end);at.value=end;const expected=read32(bytes,at);if(crc32c(bytes.slice(0,end))!==expected)throw new RangeError("durable checksum");return body;}
|
|
@@ -33,7 +33,14 @@ function objectKey(actorId: string, objectGeneration: bigint): string {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export type ZLinkFormalRemoteActorAdmissionState =
|
|
36
|
-
|
|
36
|
+
| 'provisional'
|
|
37
|
+
| 'admitting'
|
|
38
|
+
| 'admitted'
|
|
39
|
+
| 'restoring'
|
|
40
|
+
| 'rejected'
|
|
41
|
+
| 'committed'
|
|
42
|
+
| 'aborted'
|
|
43
|
+
| 'failed';
|
|
37
44
|
|
|
38
45
|
export interface ZLinkFormalRemoteActorAdmission {
|
|
39
46
|
readonly actorId: string;
|
|
@@ -78,7 +85,7 @@ export interface ZLinkFormalRemoteActorAdmissionRecord {
|
|
|
78
85
|
}
|
|
79
86
|
|
|
80
87
|
interface ZLinkFormalRemoteActorAdmissionEntry extends ZLinkFormalRemoteActorAdmissionRecord {
|
|
81
|
-
|
|
88
|
+
timer: ReturnType<typeof setTimeout>;
|
|
82
89
|
readonly resolveResult: (result: ZLinkFormalRemoteActorAdmissionResult) => void;
|
|
83
90
|
admission: ZLinkFormalRemoteActorAdmission;
|
|
84
91
|
state: ZLinkFormalRemoteActorAdmissionState;
|
|
@@ -107,6 +114,35 @@ export class ZLinkFormalRemoteActorAdmissionRegistry {
|
|
|
107
114
|
return this.admissions.get(transferId);
|
|
108
115
|
}
|
|
109
116
|
|
|
117
|
+
/** PREPARE transfers prepared resources to the target attempt until its terminal. */
|
|
118
|
+
beginRestore(transferId: string): void {
|
|
119
|
+
const entry = this.admissions.get(transferId);
|
|
120
|
+
if (entry === undefined || (entry.state !== 'admitted' && entry.state !== 'restoring')) {
|
|
121
|
+
throw new Error(`Remote actor admission '${transferId}' is not ready to restore.`);
|
|
122
|
+
}
|
|
123
|
+
clearTimeout(entry.timer);
|
|
124
|
+
entry.state = 'restoring';
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Retains successful commit replay; unsuccessful attempts release their resources now. */
|
|
128
|
+
finishRestore(transferId: string): void {
|
|
129
|
+
const entry = this.admissions.get(transferId);
|
|
130
|
+
if (entry === undefined) return;
|
|
131
|
+
if (entry.state === 'committed') {
|
|
132
|
+
clearTimeout(entry.timer);
|
|
133
|
+
entry.timer = this.scheduleExpiry(transferId);
|
|
134
|
+
} else {
|
|
135
|
+
this.abort(transferId);
|
|
136
|
+
this.delete(transferId);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private scheduleExpiry(transferId: string): ReturnType<typeof setTimeout> {
|
|
141
|
+
const timer = setTimeout(() => this.delete(transferId), ADMISSION_RETENTION_MS);
|
|
142
|
+
timer.unref();
|
|
143
|
+
return timer;
|
|
144
|
+
}
|
|
145
|
+
|
|
110
146
|
begin(input: ZLinkFormalRemoteActorAdmission): {
|
|
111
147
|
readonly record: ZLinkFormalRemoteActorAdmissionEntry;
|
|
112
148
|
readonly created: boolean;
|
|
@@ -182,10 +218,7 @@ export class ZLinkFormalRemoteActorAdmissionRegistry {
|
|
|
182
218
|
const resultTask = new Promise<ZLinkFormalRemoteActorAdmissionResult>((resolve) => {
|
|
183
219
|
resolveResult = resolve;
|
|
184
220
|
});
|
|
185
|
-
const timer =
|
|
186
|
-
this.delete(input.transferId);
|
|
187
|
-
}, ADMISSION_RETENTION_MS);
|
|
188
|
-
timer.unref();
|
|
221
|
+
const timer = this.scheduleExpiry(input.transferId);
|
|
189
222
|
const entry = {
|
|
190
223
|
admission: input,
|
|
191
224
|
state,
|
|
@@ -309,7 +342,7 @@ export class ZLinkFormalRemoteActorAdmissionRegistry {
|
|
|
309
342
|
markCommitted(transferId: string, actor: ZLinkActor): void {
|
|
310
343
|
const entry = this.admissions.get(transferId);
|
|
311
344
|
if (entry === undefined) return;
|
|
312
|
-
if (entry.state !== 'admitted' && entry.state !== 'committed') {
|
|
345
|
+
if (entry.state !== 'admitted' && entry.state !== 'restoring' && entry.state !== 'committed') {
|
|
313
346
|
throw new Error(`Remote actor admission '${transferId}' is not ready to commit.`);
|
|
314
347
|
}
|
|
315
348
|
entry.state = 'committed';
|
|
@@ -320,7 +353,7 @@ export class ZLinkFormalRemoteActorAdmissionRegistry {
|
|
|
320
353
|
const entry = this.admissions.get(transferId);
|
|
321
354
|
if (
|
|
322
355
|
entry === undefined ||
|
|
323
|
-
entry.state !== 'admitted' ||
|
|
356
|
+
(entry.state !== 'admitted' && entry.state !== 'restoring') ||
|
|
324
357
|
entry.result === undefined ||
|
|
325
358
|
'error' in entry.result ||
|
|
326
359
|
!entry.result.accepted
|
|
@@ -354,7 +387,7 @@ export class ZLinkFormalRemoteActorAdmissionRegistry {
|
|
|
354
387
|
*/
|
|
355
388
|
delete(transferId: string): void {
|
|
356
389
|
const pending = this.admissions.get(transferId);
|
|
357
|
-
if (pending === undefined) return;
|
|
390
|
+
if (pending === undefined || pending.state === 'restoring') return;
|
|
358
391
|
clearTimeout(pending.timer);
|
|
359
392
|
this.admissions.delete(transferId);
|
|
360
393
|
this.failParked(pending);
|
|
@@ -369,20 +402,7 @@ function sameAdmission(
|
|
|
369
402
|
left: ZLinkFormalRemoteActorAdmission,
|
|
370
403
|
right: ZLinkFormalRemoteActorAdmission
|
|
371
404
|
): boolean {
|
|
372
|
-
return (
|
|
373
|
-
left.actorId === right.actorId &&
|
|
374
|
-
left.actorType === right.actorType &&
|
|
375
|
-
String(left.spotId) === String(right.spotId) &&
|
|
376
|
-
left.targetSpotGeneration === right.targetSpotGeneration &&
|
|
377
|
-
left.expectedMembershipEpoch === right.expectedMembershipEpoch &&
|
|
378
|
-
left.requestFingerprint === right.requestFingerprint &&
|
|
379
|
-
sameOperationId(left.completionOperationId, right.completionOperationId) &&
|
|
380
|
-
String(left.sourceSpotId ?? '') === String(right.sourceSpotId ?? '') &&
|
|
381
|
-
String(left.sourceActorNodeRid ?? '') === String(right.sourceActorNodeRid ?? '') &&
|
|
382
|
-
left.actorRef.actorId === right.actorRef.actorId &&
|
|
383
|
-
String(left.actorRef.nodeRid) === String(right.actorRef.nodeRid) &&
|
|
384
|
-
left.actorRef.objectGeneration === right.actorRef.objectGeneration
|
|
385
|
-
);
|
|
405
|
+
return left.actorType === right.actorType && sameProvisionalAdmission(left, right);
|
|
386
406
|
}
|
|
387
407
|
|
|
388
408
|
function sameProvisionalAdmission(
|
|
@@ -215,6 +215,7 @@ export interface ZLinkSpotManagerOptions {
|
|
|
215
215
|
operation: () => Promise<T>
|
|
216
216
|
) => Promise<T>;
|
|
217
217
|
readonly actorCountProvider?: (spotId: RoutingId) => number;
|
|
218
|
+
readonly releaseActorMembers?: (meshName: string, spotId: RoutingId) => Promise<void>;
|
|
218
219
|
readonly userSpotExecutionMode?: (
|
|
219
220
|
meshName: string,
|
|
220
221
|
spotType: Type<ZLinkSpot>
|
|
@@ -408,6 +409,7 @@ export class DefaultZLinkSpotManager {
|
|
|
408
409
|
nodeRid: options.nodeRid,
|
|
409
410
|
nodeRidProvider: options.nodeRidProvider,
|
|
410
411
|
actorCountProvider: options.actorCountProvider,
|
|
412
|
+
releaseActorMembers: options.releaseActorMembers,
|
|
411
413
|
userSpotExecutionMode: options.userSpotExecutionMode,
|
|
412
414
|
userSpotRelocationCoordinationMode: options.userSpotRelocationCoordinationMode,
|
|
413
415
|
channelClient: options.channelClient,
|
|
@@ -1620,6 +1622,7 @@ export class DefaultZLinkSpotManager {
|
|
|
1620
1622
|
readonly workOptions?: import('../execution/serial-execution-queue').ZLinkSerialWorkOptions;
|
|
1621
1623
|
readonly admissionTimeoutMs?: number;
|
|
1622
1624
|
readonly signal?: AbortSignal;
|
|
1625
|
+
readonly onAdmitted?: () => void;
|
|
1623
1626
|
}
|
|
1624
1627
|
): Promise<TReply> {
|
|
1625
1628
|
return await this.routedSpotPackets.request<TReply>(spotId, packetName, request, context);
|
|
@@ -3075,7 +3078,7 @@ export class DefaultZLinkSpotManager {
|
|
|
3075
3078
|
}
|
|
3076
3079
|
const outcome = admission.result ?? (await admission.resultTask);
|
|
3077
3080
|
if ('error' in outcome) throw outcome.error;
|
|
3078
|
-
if (!outcome.accepted || admission.state !== 'admitted') {
|
|
3081
|
+
if (!outcome.accepted || (admission.state !== 'admitted' && admission.state !== 'restoring')) {
|
|
3079
3082
|
throw new Error(`Actor Join relocation '${relocationId}' has no accepted admission.`);
|
|
3080
3083
|
}
|
|
3081
3084
|
const entrySpotId = this.options.entryNodeRidProvider?.() ?? this.options.entryNodeRid;
|
|
@@ -3135,6 +3138,11 @@ export class DefaultZLinkSpotManager {
|
|
|
3135
3138
|
return true;
|
|
3136
3139
|
}
|
|
3137
3140
|
|
|
3141
|
+
beginActorJoinRelocation(relocationId: string): () => void {
|
|
3142
|
+
this.formalRemoteActorAdmissions.beginRestore(relocationId);
|
|
3143
|
+
return () => this.formalRemoteActorAdmissions.finishRestore(relocationId);
|
|
3144
|
+
}
|
|
3145
|
+
|
|
3138
3146
|
async restoreCanonicalActorJoinRecovery(
|
|
3139
3147
|
recovery: CanonicalActorJoinRecovery,
|
|
3140
3148
|
signal?: AbortSignal
|
|
@@ -3147,7 +3155,11 @@ export class DefaultZLinkSpotManager {
|
|
|
3147
3155
|
);
|
|
3148
3156
|
}
|
|
3149
3157
|
const outcome = admission.result ?? (await admission.resultTask);
|
|
3150
|
-
if (
|
|
3158
|
+
if (
|
|
3159
|
+
'error' in outcome ||
|
|
3160
|
+
!outcome.accepted ||
|
|
3161
|
+
(admission.state !== 'admitted' && admission.state !== 'restoring')
|
|
3162
|
+
) {
|
|
3151
3163
|
throw new Error(
|
|
3152
3164
|
`Actor Join recovery '${recovery.request.handoffId}' has no accepted admission.`
|
|
3153
3165
|
);
|
|
@@ -101,6 +101,7 @@ export interface ZLinkSpotActivationLifecycleOptions {
|
|
|
101
101
|
readonly nodeRid?: RoutingId;
|
|
102
102
|
readonly nodeRidProvider?: (meshName: string) => RoutingId | undefined;
|
|
103
103
|
readonly actorCountProvider?: (spotId: RoutingId) => number;
|
|
104
|
+
readonly releaseActorMembers?: (meshName: string, spotId: RoutingId) => Promise<void>;
|
|
104
105
|
readonly userSpotExecutionMode?: (
|
|
105
106
|
meshName: string,
|
|
106
107
|
spotType: Type<ZLinkSpot>
|
|
@@ -215,7 +216,10 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
215
216
|
);
|
|
216
217
|
const serialExecutor = new ZLinkSpotSerialExecutor(serial, executionMode, spotId);
|
|
217
218
|
const actorHandlers = new ZLinkSpotActorHandlerRegistryRuntime();
|
|
218
|
-
const handlers = new DefaultZLinkSpotHandlerRegistry(
|
|
219
|
+
const handlers = new DefaultZLinkSpotHandlerRegistry(
|
|
220
|
+
actorHandlers,
|
|
221
|
+
this.options.providerResolver
|
|
222
|
+
);
|
|
219
223
|
applySpotHandlerRegistrations(
|
|
220
224
|
handlers,
|
|
221
225
|
implementation as unknown as Type<ZLinkSpot>,
|
|
@@ -381,7 +385,10 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
381
385
|
spotId
|
|
382
386
|
);
|
|
383
387
|
const actorHandlers = new ZLinkSpotActorHandlerRegistryRuntime();
|
|
384
|
-
const handlers = new DefaultZLinkSpotHandlerRegistry(
|
|
388
|
+
const handlers = new DefaultZLinkSpotHandlerRegistry(
|
|
389
|
+
actorHandlers,
|
|
390
|
+
this.options.providerResolver
|
|
391
|
+
);
|
|
385
392
|
const instanceHandlers = new DefaultZLinkInstanceSpotHandlerRegistry(handlers);
|
|
386
393
|
applySpotHandlerRegistrations(handlers, implementation as unknown as Type<ZLinkSpot>, {
|
|
387
394
|
packetHandlers: this.options.spotPacketHandlers
|
|
@@ -533,7 +540,10 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
533
540
|
);
|
|
534
541
|
const serialExecutor = new ZLinkSpotSerialExecutor(serial, executionMode, spotId);
|
|
535
542
|
const actorHandlers = new ZLinkSpotActorHandlerRegistryRuntime();
|
|
536
|
-
const handlers = new DefaultZLinkSpotHandlerRegistry(
|
|
543
|
+
const handlers = new DefaultZLinkSpotHandlerRegistry(
|
|
544
|
+
actorHandlers,
|
|
545
|
+
this.options.providerResolver
|
|
546
|
+
);
|
|
537
547
|
applySpotHandlerRegistrations(handlers, spotType, {
|
|
538
548
|
actorSendHandlers: this.options.spotActorSendHandlers,
|
|
539
549
|
actorRequestHandlers: this.options.spotActorRequestHandlers,
|
|
@@ -1049,10 +1059,12 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
1049
1059
|
} catch (error) {
|
|
1050
1060
|
// An OnClosing failure is diagnostic and cleanup continues. It is
|
|
1051
1061
|
// returned so host shutdown can classify its teardown outcome.
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1062
|
+
if (reason !== ZLinkSpotCloseReason.HostShutdown) {
|
|
1063
|
+
this.options.closeErrorSink?.reportRuntimeTaskException(
|
|
1064
|
+
`spot ${String(activation.spotId)} onClosing`,
|
|
1065
|
+
error
|
|
1066
|
+
);
|
|
1067
|
+
}
|
|
1056
1068
|
closingFailure = error;
|
|
1057
1069
|
}
|
|
1058
1070
|
}
|
|
@@ -1093,7 +1105,12 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
1093
1105
|
}
|
|
1094
1106
|
if (!state.nativeDisposed) {
|
|
1095
1107
|
await cleanup(
|
|
1096
|
-
() =>
|
|
1108
|
+
async () => {
|
|
1109
|
+
if (reason === ZLinkSpotCloseReason.HostShutdown) {
|
|
1110
|
+
await this.options.releaseActorMembers?.(locationMeshName, activation.spotId);
|
|
1111
|
+
}
|
|
1112
|
+
await activation.nativeSpot?.dispose();
|
|
1113
|
+
},
|
|
1097
1114
|
() => {
|
|
1098
1115
|
state.nativeDisposed = true;
|
|
1099
1116
|
}
|
|
@@ -1121,8 +1138,9 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
1121
1138
|
}
|
|
1122
1139
|
);
|
|
1123
1140
|
}
|
|
1124
|
-
if (errors.length
|
|
1125
|
-
|
|
1141
|
+
if (errors.length > 0) {
|
|
1142
|
+
if (closingFailure !== undefined) errors.unshift(closingFailure);
|
|
1143
|
+
if (errors.length === 1) throw errors[0];
|
|
1126
1144
|
throw new AggregateError(errors, `Spot '${activation.spotId}' cleanup failed.`);
|
|
1127
1145
|
}
|
|
1128
1146
|
return closingFailure;
|