@zlink-systems/framework 0.29.1 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Configuration/Builders.d.ts +1 -2
- package/dist/contracts/Configuration/Configs.d.ts +0 -5
- package/dist/contracts/Configuration/RegistrationBuilders.js +6 -4
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -6
- package/dist/contracts/Configuration/RegistrationValidators.js +4 -4
- package/dist/contracts/Configuration/index.d.ts +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.js +3 -1
- package/dist/runtime/actors/actor-handoff.d.ts +3 -2
- package/dist/runtime/actors/actor-handoff.js +9 -4
- package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +3 -1
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +6 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +3 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.js +5 -0
- package/dist/runtime/application-jobs/contracts.d.ts +5 -1
- package/dist/runtime/backend/contracts/index.d.ts +10 -19
- package/dist/runtime/backend/mesh-completion-table.d.ts +6 -4
- package/dist/runtime/backend/mesh-completion-table.js +28 -18
- package/dist/runtime/backend/mesh-dispatch-pump.js +21 -25
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +6 -1
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +3 -3
- package/dist/runtime/backend/node/node-backend-adapter-support.js +24 -29
- package/dist/runtime/backend/node/node-mesh-backend-adapter.d.ts +1 -9
- package/dist/runtime/backend/node/node-mesh-backend-adapter.js +1 -1
- package/dist/runtime/backend/node/node-raw-binding-port.js +11 -6
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +10 -12
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +64 -98
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +10 -5
- package/dist/runtime/backend/raw-binding-port.d.ts +9 -2
- package/dist/runtime/channels/channel-receive-loops.js +3 -3
- package/dist/runtime/channels/channel-runtime-lifecycle.js +2 -1
- package/dist/runtime/channels/channel-socket-registry.d.ts +10 -3
- package/dist/runtime/channels/channel-socket-registry.js +59 -82
- package/dist/runtime/diagnostics/message-flow.d.ts +1 -0
- package/dist/runtime/diagnostics/message-flow.js +3 -3
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +15 -1
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +193 -64
- package/dist/runtime/foundation/service-liveness-registry.d.ts +20 -8
- package/dist/runtime/foundation/service-liveness-registry.js +57 -44
- package/dist/runtime/foundation/service-mailbox.d.ts +3 -0
- package/dist/runtime/foundation/service-mailbox.js +2 -1
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +7 -6
- package/dist/runtime/foundation/service-stateful-runtime.js +34 -23
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +5 -2
- package/dist/runtime/foundation/service-stateful-wire-codec.js +43 -61
- package/dist/runtime/foundation/service-topology-registry.d.ts +5 -3
- package/dist/runtime/foundation/service-topology-registry.js +9 -4
- package/dist/runtime/host/actor-packet-relay.js +7 -7
- package/dist/runtime/host/actor-runtime-options-factory.js +1 -1
- package/dist/runtime/host/application-job-queue.d.ts +11 -4
- package/dist/runtime/host/application-job-queue.js +66 -10
- package/dist/runtime/host/entry-actor-runtime.js +1 -1
- package/dist/runtime/host/index.js +15 -11
- package/dist/runtime/host/instance-activation-authority.d.ts +2 -1
- package/dist/runtime/host/instance-activation-authority.js +89 -25
- package/dist/runtime/host/service-relocation-host-runtime.js +2 -2
- package/dist/runtime/host/spot-address-transport.d.ts +1 -0
- package/dist/runtime/host/spot-address-transport.js +25 -12
- package/dist/runtime/host/spot-runtime-options-factory.js +2 -2
- package/dist/runtime/host/user-spot-creation-coordinator.d.ts +1 -0
- package/dist/runtime/host/user-spot-creation-coordinator.js +1 -0
- package/dist/runtime/locations/domain-store-contract.d.ts +2 -2
- package/dist/runtime/locations/in-memory-authority-store.d.ts +4 -2
- package/dist/runtime/locations/in-memory-authority-store.js +80 -8
- package/dist/runtime/locations/in-memory-location-store.d.ts +2 -2
- package/dist/runtime/locations/in-memory-location-store.js +19 -3
- package/dist/runtime/locations/internal-location-contracts.d.ts +3 -0
- package/dist/runtime/locations/location-store-repository.d.ts +3 -2
- package/dist/runtime/locations/location-store-repository.js +165 -22
- package/dist/runtime/locations/resolvers.d.ts +2 -1
- package/dist/runtime/locations/resolvers.js +10 -1
- package/dist/runtime/messaging/submission-result.d.ts +1 -1
- package/dist/runtime/messaging/submission-result.js +2 -2
- package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +2 -0
- package/dist/runtime/spots/index.d.ts +4 -3
- package/dist/runtime/spots/index.js +14 -14
- package/dist/runtime/spots/spot-activation.d.ts +2 -1
- package/dist/runtime/spots/spot-activation.js +4 -4
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +2 -1
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +11 -10
- package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +4 -1
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +7 -5
- package/dist/runtime/spots/spot-actor-packet-drain.js +2 -0
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -0
- package/dist/runtime/spots/spot-entry-activation.js +3 -1
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +2 -1
- package/dist/runtime/spots/spot-node-runtime-manager.js +4 -11
- package/dist/runtime/spots/spot-routing-internal.d.ts +6 -0
- package/dist/runtime/spots/spot-runtime-ports.d.ts +2 -1
- package/dist/runtime/streams/stream-session-runtime.js +1 -1
- package/package.json +3 -3
- package/src/contracts/Configuration/Builders.ts +1 -2
- package/src/contracts/Configuration/Configs.ts +0 -6
- package/src/contracts/Configuration/RegistrationBuilders.ts +8 -12
- package/src/contracts/Configuration/RegistrationTypes.ts +1 -6
- package/src/contracts/Configuration/RegistrationValidators.ts +9 -10
- package/src/contracts/Configuration/index.ts +1 -6
- package/src/internal.ts +1 -0
- package/src/runtime/actors/actor-handoff.ts +13 -4
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +12 -2
- package/src/runtime/application-jobs/application-job-queue-scope.ts +6 -1
- package/src/runtime/application-jobs/contracts.ts +14 -1
- package/src/runtime/backend/contracts/index.ts +10 -18
- package/src/runtime/backend/mesh-completion-table.ts +36 -19
- package/src/runtime/backend/mesh-dispatch-pump.ts +19 -22
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +12 -5
- package/src/runtime/backend/node/node-backend-adapter-support.ts +31 -29
- package/src/runtime/backend/node/node-mesh-backend-adapter.ts +3 -10
- package/src/runtime/backend/node/node-raw-binding-port.ts +19 -10
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +81 -111
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +12 -8
- package/src/runtime/backend/raw-binding-port.ts +12 -2
- package/src/runtime/channels/channel-receive-loops.ts +3 -3
- package/src/runtime/channels/channel-runtime-lifecycle.ts +7 -1
- package/src/runtime/channels/channel-socket-registry.ts +84 -130
- package/src/runtime/diagnostics/message-flow.ts +1 -1
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +268 -70
- package/src/runtime/foundation/service-liveness-registry.ts +68 -59
- package/src/runtime/foundation/service-mailbox.ts +7 -1
- package/src/runtime/foundation/service-stateful-runtime.ts +61 -35
- package/src/runtime/foundation/service-stateful-wire-codec.ts +55 -79
- package/src/runtime/foundation/service-topology-registry.ts +13 -7
- package/src/runtime/host/actor-packet-relay.ts +7 -0
- package/src/runtime/host/actor-runtime-options-factory.ts +1 -0
- package/src/runtime/host/application-job-queue.ts +77 -10
- package/src/runtime/host/entry-actor-runtime.ts +1 -0
- package/src/runtime/host/index.ts +24 -5
- package/src/runtime/host/instance-activation-authority.ts +132 -27
- package/src/runtime/host/service-relocation-host-runtime.ts +2 -0
- package/src/runtime/host/spot-address-transport.ts +45 -22
- package/src/runtime/host/spot-runtime-options-factory.ts +2 -0
- package/src/runtime/host/user-spot-creation-coordinator.ts +8 -0
- package/src/runtime/locations/domain-store-contract.ts +6 -2
- package/src/runtime/locations/in-memory-authority-store.ts +113 -9
- package/src/runtime/locations/in-memory-location-store.ts +25 -3
- package/src/runtime/locations/internal-location-contracts.ts +4 -0
- package/src/runtime/locations/location-store-repository.ts +220 -15
- package/src/runtime/locations/resolvers.ts +25 -2
- package/src/runtime/messaging/submission-result.ts +2 -2
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +2 -0
- package/src/runtime/spots/index.ts +16 -0
- package/src/runtime/spots/spot-activation.ts +5 -0
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +13 -0
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +10 -0
- package/src/runtime/spots/spot-actor-packet-drain.ts +2 -0
- package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +1 -0
- package/src/runtime/spots/spot-entry-activation.ts +3 -0
- package/src/runtime/spots/spot-node-runtime-manager.ts +7 -12
- package/src/runtime/spots/spot-routing-internal.ts +14 -0
- package/src/runtime/spots/spot-runtime-ports.ts +2 -0
- package/src/runtime/streams/stream-session-runtime.ts +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { UINT64_MAX } from '@zlink-systems/stream-wire';
|
|
2
2
|
export interface ServiceProbe {
|
|
3
3
|
readonly nodeRoutingId: string;
|
|
4
|
-
readonly connectionId: string;
|
|
4
|
+
readonly connectionId: string | bigint;
|
|
5
5
|
readonly probeId: bigint;
|
|
6
6
|
}
|
|
7
7
|
|
|
@@ -10,20 +10,52 @@ export interface ServiceLivenessTick {
|
|
|
10
10
|
readonly timedOutNodes: readonly string[];
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
export const DEFAULT_SERVICE_PROBE_INTERVAL_MS = 5_000;
|
|
14
|
+
export const DEFAULT_SERVICE_PEER_TIMEOUT_MS = 15_000;
|
|
15
|
+
|
|
16
|
+
export class ServiceLivenessConnection {
|
|
15
17
|
deadlineMs: number;
|
|
16
18
|
nextProbeMs: number;
|
|
17
19
|
outstandingProbe?: bigint;
|
|
18
|
-
ready: boolean;
|
|
19
|
-
}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
constructor(
|
|
22
|
+
readonly connectionId: string | bigint,
|
|
23
|
+
nowMs: number,
|
|
24
|
+
private readonly probeIntervalMs = DEFAULT_SERVICE_PROBE_INTERVAL_MS,
|
|
25
|
+
private readonly peerTimeoutMs = DEFAULT_SERVICE_PEER_TIMEOUT_MS
|
|
26
|
+
) {
|
|
27
|
+
this.deadlineMs = nowMs + peerTimeoutMs;
|
|
28
|
+
this.nextProbeMs = nowMs;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
readonly recordReceived = (nowMs = performance.now()): void => {
|
|
32
|
+
this.deadlineMs = Math.max(this.deadlineMs, nowMs + this.peerTimeoutMs);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
isExpired(nowMs: number): boolean {
|
|
36
|
+
return nowMs >= this.deadlineMs;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
tryGetProbe(nowMs: number, allocateProbeId: () => bigint): bigint | undefined {
|
|
40
|
+
if (nowMs < this.nextProbeMs) return undefined;
|
|
41
|
+
this.outstandingProbe ??= allocateProbeId();
|
|
42
|
+
do {
|
|
43
|
+
this.nextProbeMs += this.probeIntervalMs;
|
|
44
|
+
} while (this.nextProbeMs <= nowMs);
|
|
45
|
+
return this.outstandingProbe;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
acknowledge(probeId: bigint, nowMs: number): boolean {
|
|
49
|
+
this.recordReceived(nowMs);
|
|
50
|
+
if (this.outstandingProbe !== probeId) return false;
|
|
51
|
+
this.outstandingProbe = undefined;
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
23
55
|
|
|
24
56
|
/** Uses monotonic milliseconds and never treats application traffic as a probe ACK. */
|
|
25
57
|
export class ServiceLivenessRegistry {
|
|
26
|
-
private readonly peers = new Map<string,
|
|
58
|
+
private readonly peers = new Map<string, ServiceLivenessConnection>();
|
|
27
59
|
private nextProbeId = 1n;
|
|
28
60
|
|
|
29
61
|
constructor(
|
|
@@ -40,33 +72,31 @@ export class ServiceLivenessRegistry {
|
|
|
40
72
|
}
|
|
41
73
|
}
|
|
42
74
|
|
|
43
|
-
admit(
|
|
75
|
+
admit(
|
|
76
|
+
nodeRoutingId: string,
|
|
77
|
+
connectionId: string | bigint,
|
|
78
|
+
nowMs: number
|
|
79
|
+
): ServiceLivenessConnection {
|
|
44
80
|
requireIdentity(nodeRoutingId, 'nodeRoutingId');
|
|
45
|
-
requireIdentity(connectionId, 'connectionId');
|
|
81
|
+
if (typeof connectionId === 'string') requireIdentity(connectionId, 'connectionId');
|
|
82
|
+
else if (connectionId === 0n) throw new TypeError('connectionId must be nonzero.');
|
|
46
83
|
const current = this.peers.get(nodeRoutingId);
|
|
47
|
-
if (current?.connectionId === connectionId) return;
|
|
48
|
-
|
|
84
|
+
if (current?.connectionId === connectionId) return current;
|
|
85
|
+
const admitted = new ServiceLivenessConnection(
|
|
49
86
|
connectionId,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
87
|
+
nowMs,
|
|
88
|
+
this.probeIntervalMs,
|
|
89
|
+
this.peerTimeoutMs
|
|
90
|
+
);
|
|
91
|
+
this.peers.set(nodeRoutingId, admitted);
|
|
92
|
+
return admitted;
|
|
54
93
|
}
|
|
55
94
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
current === undefined ||
|
|
60
|
-
current.connectionId !== connectionId ||
|
|
61
|
-
current.ready ||
|
|
62
|
-
current.outstandingProbe !== undefined
|
|
63
|
-
)
|
|
64
|
-
return false;
|
|
65
|
-
current.nextProbeMs = Math.min(current.nextProbeMs, nowMs);
|
|
66
|
-
return true;
|
|
95
|
+
recordReceived(connection: ServiceLivenessConnection, nowMs: number): void {
|
|
96
|
+
connection.recordReceived(nowMs);
|
|
67
97
|
}
|
|
68
98
|
|
|
69
|
-
disconnect(nodeRoutingId: string, connectionId: string): boolean {
|
|
99
|
+
disconnect(nodeRoutingId: string, connectionId: string | bigint): boolean {
|
|
70
100
|
const current = this.peers.get(nodeRoutingId);
|
|
71
101
|
if (current === undefined || current.connectionId !== connectionId) return false;
|
|
72
102
|
this.peers.delete(nodeRoutingId);
|
|
@@ -75,27 +105,18 @@ export class ServiceLivenessRegistry {
|
|
|
75
105
|
|
|
76
106
|
acknowledge(
|
|
77
107
|
nodeRoutingId: string,
|
|
78
|
-
connectionId: string,
|
|
108
|
+
connectionId: string | bigint,
|
|
79
109
|
probeId: bigint,
|
|
80
110
|
nowMs: number
|
|
81
111
|
): boolean {
|
|
82
112
|
const current = this.peers.get(nodeRoutingId);
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
current.connectionId !== connectionId ||
|
|
86
|
-
current.outstandingProbe !== probeId
|
|
87
|
-
) {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
current.outstandingProbe = undefined;
|
|
91
|
-
current.deadlineMs = nowMs + this.peerTimeoutMs;
|
|
92
|
-
current.ready = true;
|
|
93
|
-
return true;
|
|
113
|
+
if (current === undefined || current.connectionId !== connectionId) return false;
|
|
114
|
+
return current.acknowledge(probeId, nowMs);
|
|
94
115
|
}
|
|
95
116
|
|
|
96
117
|
acknowledgeProbe(
|
|
97
118
|
nodeRoutingId: string,
|
|
98
|
-
connectionId: string,
|
|
119
|
+
connectionId: string | bigint,
|
|
99
120
|
probeId: bigint
|
|
100
121
|
): ServiceProbe | undefined {
|
|
101
122
|
const current = this.peers.get(nodeRoutingId);
|
|
@@ -109,21 +130,14 @@ export class ServiceLivenessRegistry {
|
|
|
109
130
|
const probes: ServiceProbe[] = [];
|
|
110
131
|
const timedOutNodes: string[] = [];
|
|
111
132
|
for (const [nodeRoutingId, peer] of this.peers) {
|
|
112
|
-
if (peer.
|
|
133
|
+
if (peer.isExpired(nowMs)) {
|
|
113
134
|
timedOutNodes.push(nodeRoutingId);
|
|
114
135
|
this.peers.delete(nodeRoutingId);
|
|
115
136
|
continue;
|
|
116
137
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
nodeRoutingId,
|
|
121
|
-
connectionId: peer.connectionId,
|
|
122
|
-
probeId: peer.outstandingProbe
|
|
123
|
-
});
|
|
124
|
-
do {
|
|
125
|
-
peer.nextProbeMs += this.probeIntervalMs;
|
|
126
|
-
} while (peer.nextProbeMs <= nowMs);
|
|
138
|
+
const probeId = peer.tryGetProbe(nowMs, this.allocateProbeId);
|
|
139
|
+
if (probeId !== undefined)
|
|
140
|
+
probes.push({ nodeRoutingId, connectionId: peer.connectionId, probeId });
|
|
127
141
|
}
|
|
128
142
|
timedOutNodes.sort();
|
|
129
143
|
return { probes, timedOutNodes };
|
|
@@ -133,16 +147,11 @@ export class ServiceLivenessRegistry {
|
|
|
133
147
|
return this.peers.size;
|
|
134
148
|
}
|
|
135
149
|
|
|
136
|
-
|
|
137
|
-
const current = this.peers.get(nodeRoutingId);
|
|
138
|
-
return current?.connectionId === connectionId && current.ready;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
private allocateProbeId(): bigint {
|
|
150
|
+
private readonly allocateProbeId = (): bigint => {
|
|
142
151
|
const result = this.nextProbeId++;
|
|
143
152
|
if (this.nextProbeId > UINT64_MAX) this.nextProbeId = 1n;
|
|
144
153
|
return result;
|
|
145
|
-
}
|
|
154
|
+
};
|
|
146
155
|
}
|
|
147
156
|
|
|
148
157
|
function requireIdentity(value: string, field: string): void {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ApplicationJobRecordLease } from '../application-jobs/application-ingress-record-owner';
|
|
2
|
+
import type { ReceiveRecord } from './service-runtime-contracts';
|
|
2
3
|
|
|
3
4
|
export type ServiceMailboxDomain = 'application' | 'infrastructure';
|
|
4
5
|
|
|
@@ -23,6 +24,8 @@ export interface ServiceMailboxRecord {
|
|
|
23
24
|
readonly stateful?: unknown;
|
|
24
25
|
/** Host queue permit plus its ordinary Framework-owned ingress record. */
|
|
25
26
|
readonly applicationJob?: ApplicationJobRecordLease;
|
|
27
|
+
/** Unregistered raw-pull terminal, retained by the existing mailbox owner. */
|
|
28
|
+
readonly completion?: ReceiveRecord;
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
export interface ServiceMailboxClaim {
|
|
@@ -85,7 +88,10 @@ export class ServiceMailbox {
|
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
tryEnqueue(record: ServiceMailboxRecord): boolean {
|
|
88
|
-
if (
|
|
91
|
+
if (
|
|
92
|
+
record.owner.length === 0 ||
|
|
93
|
+
(record.parts.length === 0 && record.completion === undefined)
|
|
94
|
+
) {
|
|
89
95
|
throw new TypeError('Mailbox records require an owner and retained payload.');
|
|
90
96
|
}
|
|
91
97
|
const target = this.domain(record.domain);
|
|
@@ -90,6 +90,7 @@ import {
|
|
|
90
90
|
type ServiceBoundSessionActorAuthority,
|
|
91
91
|
type ServiceDirectSpotRouteFence,
|
|
92
92
|
type ServiceInstanceActivationTarget,
|
|
93
|
+
type ServiceInstanceColdActivationTarget,
|
|
93
94
|
type ServiceInstanceRouteFence,
|
|
94
95
|
type ServiceMessageFollowRoute,
|
|
95
96
|
type ServiceRetiredBoundSessionRouteFence,
|
|
@@ -313,7 +314,12 @@ export interface ServiceInstanceActivationAuthority {
|
|
|
313
314
|
* operation completes; the binding callback itself never blocks.
|
|
314
315
|
*/
|
|
315
316
|
export interface ServiceAsyncInstanceActivationAuthority {
|
|
316
|
-
read(
|
|
317
|
+
read(
|
|
318
|
+
target: ServiceInstanceActivationTarget,
|
|
319
|
+
instanceIntent?: true,
|
|
320
|
+
activation?: ServiceInstanceActivationRecoveryEnvelope,
|
|
321
|
+
acceptsLocal?: (route: ServiceInstanceRouteFence) => boolean
|
|
322
|
+
): Promise<ServiceInstanceAuthorityRead>;
|
|
317
323
|
reserve(
|
|
318
324
|
activation: Omit<ServiceInstanceActivationRecoveryEnvelope, 'targetMeshName'>,
|
|
319
325
|
signal?: AbortSignal
|
|
@@ -883,7 +889,7 @@ export class ServiceStatefulRuntime {
|
|
|
883
889
|
const record = {
|
|
884
890
|
kind: 'instanceSpot' as const,
|
|
885
891
|
activation: 'missing' as const,
|
|
886
|
-
target,
|
|
892
|
+
target: { ...target, targetMeshName: envelope.targetMeshName },
|
|
887
893
|
sourceNodeGeneration: envelope.sourceNodeGeneration,
|
|
888
894
|
sourceNodeRid: envelope.sourceNodeRid,
|
|
889
895
|
...(envelope.sourceSpotId === undefined ? {} : { sourceSpotId: envelope.sourceSpotId }),
|
|
@@ -902,7 +908,7 @@ export class ServiceStatefulRuntime {
|
|
|
902
908
|
sourceRoutingId: envelope.sourceNodeRid,
|
|
903
909
|
parts: [
|
|
904
910
|
encodeInstanceSpotActivationHeader(
|
|
905
|
-
target,
|
|
911
|
+
record.target,
|
|
906
912
|
envelope.sourceNodeGeneration,
|
|
907
913
|
envelope.sourceNodeRid,
|
|
908
914
|
envelope.sourceSpotId,
|
|
@@ -1442,7 +1448,7 @@ export class ServiceStatefulRuntime {
|
|
|
1442
1448
|
}
|
|
1443
1449
|
|
|
1444
1450
|
async sendToMissingInstanceSpot(
|
|
1445
|
-
target:
|
|
1451
|
+
target: ServiceInstanceColdActivationTarget,
|
|
1446
1452
|
payload: ServiceApplicationPayload,
|
|
1447
1453
|
deadlineUnixMs: bigint,
|
|
1448
1454
|
sourceSpotId?: string,
|
|
@@ -1458,7 +1464,7 @@ export class ServiceStatefulRuntime {
|
|
|
1458
1464
|
}
|
|
1459
1465
|
|
|
1460
1466
|
async sendToMissingInstanceSpotFrame(
|
|
1461
|
-
target:
|
|
1467
|
+
target: ServiceInstanceColdActivationTarget,
|
|
1462
1468
|
payloadFrame: Buffer,
|
|
1463
1469
|
deadlineUnixMs: bigint,
|
|
1464
1470
|
sourceSpotId?: string,
|
|
@@ -1523,7 +1529,7 @@ export class ServiceStatefulRuntime {
|
|
|
1523
1529
|
}
|
|
1524
1530
|
|
|
1525
1531
|
requestToMissingInstanceSpot(
|
|
1526
|
-
target:
|
|
1532
|
+
target: ServiceInstanceColdActivationTarget,
|
|
1527
1533
|
payload: ServiceApplicationPayload,
|
|
1528
1534
|
timeoutMs: number,
|
|
1529
1535
|
sourceSpotId?: string,
|
|
@@ -1541,7 +1547,7 @@ export class ServiceStatefulRuntime {
|
|
|
1541
1547
|
}
|
|
1542
1548
|
|
|
1543
1549
|
requestToMissingInstanceSpotFrame(
|
|
1544
|
-
target:
|
|
1550
|
+
target: ServiceInstanceColdActivationTarget,
|
|
1545
1551
|
payloadFrame: Buffer,
|
|
1546
1552
|
deadlineUnixMs: bigint,
|
|
1547
1553
|
sourceSpotId?: string,
|
|
@@ -2941,6 +2947,24 @@ export class ServiceStatefulRuntime {
|
|
|
2941
2947
|
return activation.spot;
|
|
2942
2948
|
}
|
|
2943
2949
|
|
|
2950
|
+
private localReadyInstance(
|
|
2951
|
+
target: ServiceInstanceActivationTarget,
|
|
2952
|
+
route: ServiceInstanceRouteFence
|
|
2953
|
+
): ServiceSpotState | undefined {
|
|
2954
|
+
const local = this.registry.spot(target.targetSpotId);
|
|
2955
|
+
if (
|
|
2956
|
+
local !== undefined &&
|
|
2957
|
+
(local.kind !== 'instance' || local.stableType !== target.stableType)
|
|
2958
|
+
) {
|
|
2959
|
+
throw new ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
2960
|
+
}
|
|
2961
|
+
return local !== undefined &&
|
|
2962
|
+
local.state === 'ready' &&
|
|
2963
|
+
routeMatchesLocal(route, local, this.nodeRid, this.nodeGeneration)
|
|
2964
|
+
? local
|
|
2965
|
+
: undefined;
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2944
2968
|
private activateMissingInstanceAsync(
|
|
2945
2969
|
record: Extract<
|
|
2946
2970
|
ServiceStatefulWireRecord,
|
|
@@ -2961,7 +2985,20 @@ export class ServiceStatefulRuntime {
|
|
|
2961
2985
|
...activation,
|
|
2962
2986
|
stableType: record.target.stableType
|
|
2963
2987
|
}));
|
|
2964
|
-
const operation = ready.then((value) => {
|
|
2988
|
+
const operation = ready.then(async (value) => {
|
|
2989
|
+
if (pending !== undefined) {
|
|
2990
|
+
await this.asyncInstanceAuthority?.read(
|
|
2991
|
+
record.target,
|
|
2992
|
+
undefined,
|
|
2993
|
+
{
|
|
2994
|
+
...record,
|
|
2995
|
+
targetMeshName: record.target.targetMeshName,
|
|
2996
|
+
...(metadataFrame === undefined ? {} : { metadataFrame }),
|
|
2997
|
+
applicationPayloadFrame: payloadFrame
|
|
2998
|
+
},
|
|
2999
|
+
(route) => this.localReadyInstance(record.target, route) !== undefined
|
|
3000
|
+
);
|
|
3001
|
+
}
|
|
2965
3002
|
if (value.stableType !== record.target.stableType) {
|
|
2966
3003
|
throw new ZLinkFrameworkException(
|
|
2967
3004
|
ZLinkFrameworkErrorKind.TypeMismatch,
|
|
@@ -3010,8 +3047,19 @@ export class ServiceStatefulRuntime {
|
|
|
3010
3047
|
throw new Error('Async Instance activation authority is not registered.');
|
|
3011
3048
|
}
|
|
3012
3049
|
|
|
3050
|
+
const activationRequest = {
|
|
3051
|
+
...record,
|
|
3052
|
+
targetMeshName: record.target.targetMeshName,
|
|
3053
|
+
...(metadataFrame === undefined ? {} : { metadataFrame }),
|
|
3054
|
+
applicationPayloadFrame: payloadFrame
|
|
3055
|
+
};
|
|
3056
|
+
const current = await authority.read(
|
|
3057
|
+
target,
|
|
3058
|
+
true,
|
|
3059
|
+
activationRequest,
|
|
3060
|
+
(route) => this.localReadyInstance(target, route) !== undefined
|
|
3061
|
+
);
|
|
3013
3062
|
const local = this.registry.spot(target.targetSpotId);
|
|
3014
|
-
const current = await authority.read(target);
|
|
3015
3063
|
if (
|
|
3016
3064
|
current.kind === 'creating' &&
|
|
3017
3065
|
current.authority?.allocation.state === 'active' &&
|
|
@@ -3061,17 +3109,9 @@ export class ServiceStatefulRuntime {
|
|
|
3061
3109
|
if (current.route.targetNodeGeneration !== this.nodeGeneration) {
|
|
3062
3110
|
throw new ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
3063
3111
|
}
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
) {
|
|
3068
|
-
throw new ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
3069
|
-
}
|
|
3070
|
-
if (
|
|
3071
|
-
local !== undefined &&
|
|
3072
|
-
routeMatchesLocal(current.route, local, this.nodeRid, this.nodeGeneration)
|
|
3073
|
-
) {
|
|
3074
|
-
return { spot: local, route: current.route };
|
|
3112
|
+
const readyLocal = this.localReadyInstance(target, current.route);
|
|
3113
|
+
if (readyLocal !== undefined) {
|
|
3114
|
+
return { spot: readyLocal, route: current.route };
|
|
3075
3115
|
}
|
|
3076
3116
|
return await this.reconcileReadyInstanceProjection(target, current.route, authority);
|
|
3077
3117
|
}
|
|
@@ -3113,21 +3153,7 @@ export class ServiceStatefulRuntime {
|
|
|
3113
3153
|
const deadline = operationDeadline(record.deadlineUnixMs);
|
|
3114
3154
|
let reserved: ServiceInstanceAuthorityReserve;
|
|
3115
3155
|
try {
|
|
3116
|
-
reserved = await authority.reserve(
|
|
3117
|
-
{
|
|
3118
|
-
target,
|
|
3119
|
-
sourceNodeRid: record.sourceNodeRid,
|
|
3120
|
-
sourceNodeGeneration: record.sourceNodeGeneration,
|
|
3121
|
-
...(record.sourceSpotId === undefined ? {} : { sourceSpotId: record.sourceSpotId }),
|
|
3122
|
-
operationKind: record.operationKind,
|
|
3123
|
-
operation: record.operation,
|
|
3124
|
-
...(record.replyRouteId === undefined ? {} : { replyRouteId: record.replyRouteId }),
|
|
3125
|
-
deadlineUnixMs: record.deadlineUnixMs,
|
|
3126
|
-
...(metadataFrame === undefined ? {} : { metadataFrame }),
|
|
3127
|
-
applicationPayloadFrame: payloadFrame
|
|
3128
|
-
},
|
|
3129
|
-
deadline.signal
|
|
3130
|
-
);
|
|
3156
|
+
reserved = await authority.reserve(activationRequest, deadline.signal);
|
|
3131
3157
|
} finally {
|
|
3132
3158
|
deadline.close();
|
|
3133
3159
|
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
encodeInstanceRouteV1,
|
|
15
15
|
encodeSpotRequestCommand,
|
|
16
16
|
encodeSpotSendCommand,
|
|
17
|
+
type InstanceRouteV1,
|
|
17
18
|
type ServiceWireDecoderContext
|
|
18
19
|
} from '../protocol/service_wire_codec.generated';
|
|
19
20
|
import {
|
|
@@ -82,8 +83,6 @@ import {
|
|
|
82
83
|
import { APPLICATION_PAYLOAD_VERSION, ServiceWireProtocolError } from './service-wire-m6a-codec';
|
|
83
84
|
const MESSAGE_FOLLOW_MAX_BODY_BYTES = 16 * 1024 * 1024;
|
|
84
85
|
const MESSAGE_FOLLOW_VERSION = 1;
|
|
85
|
-
const INSTANCE_ROUTE_VERSION = 1;
|
|
86
|
-
const INSTANCE_ACTIVATION_VERSION = 2;
|
|
87
86
|
|
|
88
87
|
const PREFIX_SIZE = SERVICE_WIRE_PREFIX_SIZE;
|
|
89
88
|
const MAGIC_0 = SERVICE_WIRE_MAGIC[0];
|
|
@@ -946,6 +945,10 @@ export interface ServiceInstanceActivationTarget {
|
|
|
946
945
|
readonly descriptorVersion: string;
|
|
947
946
|
}
|
|
948
947
|
|
|
948
|
+
export interface ServiceInstanceColdActivationTarget extends ServiceInstanceActivationTarget {
|
|
949
|
+
readonly targetMeshName: string;
|
|
950
|
+
}
|
|
951
|
+
|
|
949
952
|
export interface ServiceUserSpotReservationFence {
|
|
950
953
|
readonly reservationId: string;
|
|
951
954
|
readonly expectedStoreVersion: string;
|
|
@@ -1105,7 +1108,7 @@ export type ServiceStatefulWireRecord =
|
|
|
1105
1108
|
| {
|
|
1106
1109
|
readonly kind: 'instanceSpot';
|
|
1107
1110
|
readonly activation: 'missing';
|
|
1108
|
-
readonly target:
|
|
1111
|
+
readonly target: ServiceInstanceColdActivationTarget;
|
|
1109
1112
|
readonly sourceNodeGeneration: bigint;
|
|
1110
1113
|
readonly sourceNodeRid: string;
|
|
1111
1114
|
readonly sourceSpotId?: string;
|
|
@@ -1435,7 +1438,7 @@ export function encodeInstanceSpotHeader(
|
|
|
1435
1438
|
}
|
|
1436
1439
|
|
|
1437
1440
|
export function encodeInstanceSpotActivationHeader(
|
|
1438
|
-
target:
|
|
1441
|
+
target: ServiceInstanceColdActivationTarget,
|
|
1439
1442
|
sourceNodeGeneration: bigint,
|
|
1440
1443
|
sourceNodeRid: string,
|
|
1441
1444
|
sourceSpotId: string | undefined,
|
|
@@ -1454,25 +1457,28 @@ export function encodeInstanceSpotActivationHeader(
|
|
|
1454
1457
|
if (operationKind === 'send' && replyRouteId !== undefined) {
|
|
1455
1458
|
throw new RangeError('Instance Spot send must not carry a reply route.');
|
|
1456
1459
|
}
|
|
1457
|
-
const
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1460
|
+
const encodedRoute = encodeInstanceRouteV1(
|
|
1461
|
+
{
|
|
1462
|
+
routeKind: 'coldActivation',
|
|
1463
|
+
targetNodeRid: toGeneratedRoutingId(target.targetNodeRid, 'targetNodeRid'),
|
|
1464
|
+
targetNodeGeneration: target.targetNodeGeneration,
|
|
1465
|
+
targetSpotId: target.targetSpotId,
|
|
1466
|
+
targetMeshName: target.targetMeshName,
|
|
1467
|
+
stableType: target.stableType,
|
|
1468
|
+
targetDescriptorVersion: target.descriptorVersion,
|
|
1469
|
+
deadlineUnixMs
|
|
1470
|
+
},
|
|
1471
|
+
STATEFUL_MESSAGE_CONTEXT
|
|
1463
1472
|
);
|
|
1464
1473
|
return concat(
|
|
1465
1474
|
prefix(M6bServiceWireCommand.instanceSpot, hasMetadata ? M6bServiceWireFlag.metadata : 0),
|
|
1466
|
-
|
|
1467
|
-
u16(targetBody.byteLength),
|
|
1468
|
-
targetBody,
|
|
1475
|
+
encodedRoute,
|
|
1469
1476
|
u64Any(sourceNodeGeneration),
|
|
1470
1477
|
rid(sourceNodeRid, 'sourceNodeRid'),
|
|
1471
1478
|
optionalRid(sourceSpotId),
|
|
1472
1479
|
Buffer.of(operationKind === 'send' ? 1 : 2),
|
|
1473
1480
|
u64Any(operation.high),
|
|
1474
1481
|
u64Any(operation.low),
|
|
1475
|
-
u64(deadlineUnixMs),
|
|
1476
1482
|
...(operationKind === 'request' ? [u64(requirePositive(replyRouteId, 'replyRouteId'))] : [])
|
|
1477
1483
|
);
|
|
1478
1484
|
}
|
|
@@ -1741,53 +1747,31 @@ export function decodeStatefulHeader(
|
|
|
1741
1747
|
fail(`Invalid command flags '${command.flags}'.`);
|
|
1742
1748
|
}
|
|
1743
1749
|
const routeStart = reader.offset;
|
|
1744
|
-
|
|
1745
|
-
if (version !== INSTANCE_ROUTE_VERSION && version !== INSTANCE_ACTIVATION_VERSION)
|
|
1746
|
-
fail('Unsupported Instance route version.');
|
|
1750
|
+
reader.u8('instanceRoute.kind');
|
|
1747
1751
|
const routeLength = reader.u16('instanceRoute.length');
|
|
1748
1752
|
const routeEnd = reader.offset + routeLength;
|
|
1749
|
-
const
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
generatedReadyRoute?.routeKind === 'ready'
|
|
1761
|
-
? {
|
|
1762
|
-
targetNodeRid: fromGeneratedRoutingId(
|
|
1763
|
-
generatedReadyRoute.targetNodeRid,
|
|
1764
|
-
'targetNodeRid'
|
|
1765
|
-
),
|
|
1766
|
-
targetNodeGeneration: generatedReadyRoute.targetNodeGeneration,
|
|
1767
|
-
targetSpotId: generatedReadyRoute.targetSpotId
|
|
1768
|
-
}
|
|
1769
|
-
: {
|
|
1770
|
-
targetNodeRid: reader.rid('targetNodeRid'),
|
|
1771
|
-
targetNodeGeneration: reader.nonZeroU64('targetNodeGeneration'),
|
|
1772
|
-
targetSpotId: reader.rid('targetSpotId')
|
|
1773
|
-
};
|
|
1774
|
-
const route: ServiceInstanceRouteFence | undefined =
|
|
1775
|
-
generatedReadyRoute?.routeKind === 'ready'
|
|
1776
|
-
? {
|
|
1777
|
-
...commonTarget,
|
|
1778
|
-
...generatedReadyRoute.authority
|
|
1779
|
-
}
|
|
1753
|
+
const generatedRoute = decodeCanonicalInstanceRoute(
|
|
1754
|
+
reader.bytes.subarray(routeStart, routeEnd)
|
|
1755
|
+
);
|
|
1756
|
+
const commonTarget = {
|
|
1757
|
+
targetNodeRid: fromGeneratedRoutingId(generatedRoute.targetNodeRid, 'targetNodeRid'),
|
|
1758
|
+
targetNodeGeneration: generatedRoute.targetNodeGeneration,
|
|
1759
|
+
targetSpotId: generatedRoute.targetSpotId
|
|
1760
|
+
};
|
|
1761
|
+
const route =
|
|
1762
|
+
generatedRoute.routeKind === 'ready'
|
|
1763
|
+
? { ...commonTarget, ...generatedRoute.authority }
|
|
1780
1764
|
: undefined;
|
|
1781
|
-
const target
|
|
1782
|
-
|
|
1765
|
+
const target =
|
|
1766
|
+
generatedRoute.routeKind === 'coldActivation'
|
|
1783
1767
|
? {
|
|
1784
1768
|
...commonTarget,
|
|
1785
|
-
|
|
1786
|
-
|
|
1769
|
+
targetMeshName: generatedRoute.targetMeshName,
|
|
1770
|
+
stableType: generatedRoute.stableType,
|
|
1771
|
+
descriptorVersion: generatedRoute.targetDescriptorVersion
|
|
1787
1772
|
}
|
|
1788
1773
|
: undefined;
|
|
1789
|
-
|
|
1790
|
-
if (reader.offset !== routeEnd) fail('Invalid Instance route body length.');
|
|
1774
|
+
reader.offset = routeEnd;
|
|
1791
1775
|
const sourceNodeGeneration = reader.nonZeroU64('sourceNodeGeneration');
|
|
1792
1776
|
const sourceNodeRid = reader.rid('sourceNodeRid');
|
|
1793
1777
|
const sourceSpotId = reader.optionalRid('sourceSpotId');
|
|
@@ -1799,21 +1783,21 @@ export function decodeStatefulHeader(
|
|
|
1799
1783
|
};
|
|
1800
1784
|
const operationKind = operationValue === 1 ? ('send' as const) : ('request' as const);
|
|
1801
1785
|
if (
|
|
1802
|
-
|
|
1786
|
+
generatedRoute.routeKind === 'ready' &&
|
|
1803
1787
|
((operationKind === 'send' && (operation.high !== 0n || operation.low !== 0n)) ||
|
|
1804
1788
|
(operationKind === 'request' && operation.high === 0n && operation.low === 0n))
|
|
1805
1789
|
) {
|
|
1806
1790
|
fail('Invalid Instance operation identity.');
|
|
1807
1791
|
}
|
|
1808
1792
|
if (
|
|
1809
|
-
|
|
1793
|
+
generatedRoute.routeKind === 'coldActivation' &&
|
|
1810
1794
|
operation.high === 0n &&
|
|
1811
1795
|
operation.low === 0n
|
|
1812
1796
|
) {
|
|
1813
1797
|
fail('Instance activation requires a non-zero operation identity.');
|
|
1814
1798
|
}
|
|
1815
1799
|
const deadlineUnixMs =
|
|
1816
|
-
|
|
1800
|
+
generatedRoute.routeKind === 'coldActivation' ? generatedRoute.deadlineUnixMs : undefined;
|
|
1817
1801
|
const replyRouteId =
|
|
1818
1802
|
operationKind === 'request' ? reader.nonZeroU64('replyRouteId') : undefined;
|
|
1819
1803
|
reader.end();
|
|
@@ -1826,12 +1810,12 @@ export function decodeStatefulHeader(
|
|
|
1826
1810
|
operation,
|
|
1827
1811
|
...(replyRouteId === undefined ? {} : { replyRouteId })
|
|
1828
1812
|
};
|
|
1829
|
-
return
|
|
1813
|
+
return generatedRoute.routeKind === 'ready'
|
|
1830
1814
|
? {
|
|
1831
1815
|
...common,
|
|
1832
1816
|
activation: 'ready',
|
|
1833
1817
|
route: route!,
|
|
1834
|
-
instanceIntent:
|
|
1818
|
+
instanceIntent: generatedRoute.instanceIntent === 'true'
|
|
1835
1819
|
}
|
|
1836
1820
|
: {
|
|
1837
1821
|
...common,
|
|
@@ -2387,11 +2371,6 @@ function text8(value: string, name: string): Buffer {
|
|
|
2387
2371
|
return sized8(value, name);
|
|
2388
2372
|
}
|
|
2389
2373
|
|
|
2390
|
-
function text16(value: string, name: string): Buffer {
|
|
2391
|
-
const bytes = encodeCanonicalServiceWireText(value, name, 0xffff, outOfRange);
|
|
2392
|
-
return concat(u16(bytes.byteLength), bytes);
|
|
2393
|
-
}
|
|
2394
|
-
|
|
2395
2374
|
function optionalRid(value: string | undefined): Buffer {
|
|
2396
2375
|
return value === undefined ? Buffer.of(0) : rid(value, 'sourceSpotId');
|
|
2397
2376
|
}
|
|
@@ -2448,6 +2427,15 @@ function concat(...parts: readonly Uint8Array[]): Buffer {
|
|
|
2448
2427
|
return Buffer.concat(parts.map((part) => Buffer.from(part)));
|
|
2449
2428
|
}
|
|
2450
2429
|
|
|
2430
|
+
function decodeCanonicalInstanceRoute(bytes: Uint8Array): InstanceRouteV1 {
|
|
2431
|
+
try {
|
|
2432
|
+
return decodeInstanceRouteV1(bytes, STATEFUL_MESSAGE_CONTEXT);
|
|
2433
|
+
} catch (error) {
|
|
2434
|
+
if (error instanceof RangeError) throw new ServiceWireProtocolError(error.message);
|
|
2435
|
+
throw error;
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2451
2439
|
function fail(message: string): never {
|
|
2452
2440
|
throw new ServiceWireProtocolError(message);
|
|
2453
2441
|
}
|
|
@@ -3093,21 +3081,9 @@ class FrozenReader {
|
|
|
3093
3081
|
|
|
3094
3082
|
private instanceRoute(): void {
|
|
3095
3083
|
const start = this.offset;
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
if (kind === INSTANCE_ROUTE_VERSION) {
|
|
3100
|
-
decodeInstanceRouteV1(this.bytes.subarray(start, this.offset), STATEFUL_MESSAGE_CONTEXT);
|
|
3101
|
-
return;
|
|
3102
|
-
}
|
|
3103
|
-
body.rid8('targetNodeRid');
|
|
3104
|
-
body.nonZeroU64('targetNodeGeneration');
|
|
3105
|
-
body.text8('targetSpotId');
|
|
3106
|
-
body.text8('targetMeshName');
|
|
3107
|
-
body.text8('stableType');
|
|
3108
|
-
body.text8('targetDescriptorVersion');
|
|
3109
|
-
body.nonZeroU64('deadlineUnixMs');
|
|
3110
|
-
body.end('Instance route');
|
|
3084
|
+
this.u8('instanceRouteKind');
|
|
3085
|
+
this.body16('Instance route');
|
|
3086
|
+
decodeCanonicalInstanceRoute(this.bytes.subarray(start, this.offset));
|
|
3111
3087
|
}
|
|
3112
3088
|
|
|
3113
3089
|
private relocationObject(): void {
|