@zlink-systems/framework 0.31.0 → 0.32.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/Actors/ZLinkActor.d.ts +2 -0
- package/dist/contracts/Actors/ZLinkSessionBindingIdentity.d.ts +6 -0
- package/dist/contracts/Actors/ZLinkSessionBindingIdentity.js +2 -0
- package/dist/contracts/Actors/index.d.ts +1 -0
- package/dist/contracts/Actors/index.js +1 -0
- package/dist/contracts/Common/payload-slab.d.ts +4 -0
- package/dist/contracts/Common/payload-slab.js +30 -0
- package/dist/contracts/Handlers/Contexts.d.ts +1 -0
- package/dist/internal.d.ts +9 -0
- package/dist/internal.js +23 -1
- package/dist/runtime/actors/actor-client.d.ts +1 -1
- package/dist/runtime/actors/actor-client.js +32 -23
- package/dist/runtime/actors/actor-mailbox.d.ts +1 -1
- package/dist/runtime/actors/actor-runtime-state.d.ts +1 -1
- package/dist/runtime/actors/spot-actor-dispatch.d.ts +4 -2
- package/dist/runtime/actors/spot-actor-dispatch.js +2 -1
- package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +1 -0
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +3 -0
- package/dist/runtime/backend/contracts/index.d.ts +2 -0
- package/dist/runtime/backend/mesh-completion-table.d.ts +1 -0
- package/dist/runtime/backend/mesh-completion-table.js +1 -0
- package/dist/runtime/backend/node/node-mesh-backend-adapter.js +5 -1
- package/dist/runtime/backend/node/node-raw-binding-port.d.ts +7 -2
- package/dist/runtime/backend/node/node-raw-binding-port.js +17 -11
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +2 -2
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +15 -8
- package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +7 -6
- package/dist/runtime/channels/channel-dispatch-pipeline.js +1 -0
- package/dist/runtime/channels/channel-dispatchers.d.ts +7 -3
- package/dist/runtime/channels/channel-dispatchers.js +27 -19
- package/dist/runtime/channels/channel-envelope.js +543 -23
- package/dist/runtime/channels/channel-receive-loops.d.ts +9 -6
- package/dist/runtime/channels/channel-receive-loops.js +59 -18
- package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +22 -3
- package/dist/runtime/channels/channel-socket-registry.d.ts +22 -4
- package/dist/runtime/diagnostics/runtime-metrics.d.ts +1 -1
- package/dist/runtime/diagnostics/runtime-metrics.js +2 -1
- package/dist/runtime/execution/serial-execution-queue.d.ts +26 -13
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +27 -11
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +29 -25
- package/dist/runtime/foundation/service-liveness-registry.d.ts +1 -1
- package/dist/runtime/foundation/service-mailbox.d.ts +3 -1
- package/dist/runtime/foundation/service-mailbox.js +4 -1
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +3 -1
- package/dist/runtime/foundation/service-stateful-registry.d.ts +2 -0
- package/dist/runtime/foundation/service-stateful-registry.js +28 -12
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +51 -19
- package/dist/runtime/foundation/service-stateful-runtime.js +54 -5
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +3 -0
- package/dist/runtime/foundation/service-stateful-wire-codec.js +15 -0
- package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
- package/dist/runtime/foundation/service-wire-constants.generated.js +12 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +2 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.js +17 -7
- package/dist/runtime/host/actor-placement-coordinator.d.ts +1 -1
- package/dist/runtime/host/actor-transfer-runtime.d.ts +3 -3
- package/dist/runtime/host/application-job-queue.d.ts +1 -1
- package/dist/runtime/host/index.d.ts +89 -36
- package/dist/runtime/host/index.js +101 -7
- package/dist/runtime/host/location-runtime-owner.d.ts +2 -2
- package/dist/runtime/host/service-relocation-host-runtime.d.ts +181 -44
- package/dist/runtime/host/service-relocation-host-runtime.js +47 -13
- package/dist/runtime/host/spot-address-transport.js +50 -42
- package/dist/runtime/locations/auto-connect-loop.d.ts +0 -1
- package/dist/runtime/locations/auto-connect-loop.js +25 -19
- package/dist/runtime/locations/auto-connect-planner.js +2 -5
- package/dist/runtime/locations/auto-connect-reconciler.d.ts +1 -0
- package/dist/runtime/locations/auto-connect-reconciler.js +35 -23
- package/dist/runtime/locations/in-memory-location-store.d.ts +0 -2
- package/dist/runtime/locations/in-memory-location-store.js +1 -38
- package/dist/runtime/locations/location-store-repository.d.ts +0 -1
- package/dist/runtime/locations/location-store-repository.js +13 -115
- package/dist/runtime/locations/runtime.d.ts +3 -3
- package/dist/runtime/locations/runtime.js +12 -16
- package/dist/runtime/messaging/creation-payload-codec.js +2 -2
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +4 -0
- package/dist/runtime/protocol/service_wire_codec.generated.js +17 -7
- package/dist/runtime/spots/index.d.ts +20 -5
- package/dist/runtime/spots/index.js +14 -0
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +3 -3
- package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +1 -0
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +13 -7
- package/dist/runtime/spots/spot-actor-packet-drain.d.ts +1 -0
- package/dist/runtime/spots/spot-actor-packet-drain.js +12 -5
- package/dist/runtime/spots/spot-entry-activation.d.ts +2 -1
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +8 -6
- package/dist/runtime/spots/spot-node-runtime-manager.js +2 -0
- package/dist/runtime/spots/spot-route-packet-dispatch.js +7 -4
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +3 -1
- package/dist/runtime/spots/spot-serial-executor.d.ts +2 -1
- package/dist/runtime/spots/spot-subscription-dispatch.js +3 -1
- package/dist/runtime/spots/spot-timer.d.ts +1 -1
- package/dist/runtime/streams/actor-session-binding-registry.d.ts +9 -3
- package/dist/runtime/streams/actor-session-binding-registry.js +17 -0
- package/dist/runtime/streams/index.d.ts +3 -3
- package/dist/runtime/streams/index.js +22 -2
- package/dist/runtime/streams/managed-stream.js +2 -1
- package/dist/runtime/streams/session-calls.d.ts +1 -1
- package/dist/runtime/streams/session-calls.js +3 -9
- package/dist/runtime/streams/session-context.d.ts +2 -2
- package/dist/runtime/streams/session-context.js +2 -2
- package/dist/runtime/streams/stream-session-runtime.d.ts +1 -0
- package/dist/runtime/streams/stream-session-runtime.js +37 -12
- package/package.json +3 -3
- package/src/contracts/Actors/ZLinkActor.ts +6 -0
- package/src/contracts/Actors/ZLinkSessionBindingIdentity.ts +7 -0
- package/src/contracts/Actors/index.ts +1 -0
- package/src/contracts/Common/payload-slab.ts +29 -0
- package/src/contracts/Handlers/Contexts.ts +1 -0
- package/src/internal.ts +17 -0
- package/src/runtime/actors/actor-client.ts +48 -23
- package/src/runtime/actors/actor-mailbox.ts +1 -1
- package/src/runtime/actors/actor-runtime-state.ts +1 -1
- package/src/runtime/actors/spot-actor-dispatch.ts +4 -3
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +4 -0
- package/src/runtime/backend/contracts/index.ts +2 -0
- package/src/runtime/backend/mesh-completion-table.ts +2 -0
- package/src/runtime/backend/node/node-mesh-backend-adapter.ts +5 -1
- package/src/runtime/backend/node/node-raw-binding-port.ts +20 -7
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +18 -10
- package/src/runtime/channels/channel-dispatch-pipeline.ts +6 -5
- package/src/runtime/channels/channel-dispatchers.ts +39 -19
- package/src/runtime/channels/channel-envelope.ts +547 -20
- package/src/runtime/channels/channel-receive-loops.ts +93 -36
- package/src/runtime/channels/channel-runtime-lifecycle.ts +2 -2
- package/src/runtime/channels/channel-socket-registry.ts +3 -3
- package/src/runtime/diagnostics/runtime-metrics.ts +3 -1
- package/src/runtime/execution/serial-execution-queue.ts +13 -13
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +40 -39
- package/src/runtime/foundation/service-liveness-registry.ts +1 -1
- package/src/runtime/foundation/service-mailbox.ts +6 -1
- package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
- package/src/runtime/foundation/service-stateful-registry.ts +39 -14
- package/src/runtime/foundation/service-stateful-runtime.ts +87 -21
- package/src/runtime/foundation/service-stateful-wire-codec.ts +18 -0
- package/src/runtime/foundation/service-wire-constants.generated.ts +10 -0
- package/src/runtime/foundation/service-wire-m6a-codec.ts +29 -7
- package/src/runtime/host/actor-placement-coordinator.ts +1 -1
- package/src/runtime/host/actor-transfer-runtime.ts +3 -3
- package/src/runtime/host/application-job-queue.ts +1 -1
- package/src/runtime/host/index.ts +183 -44
- package/src/runtime/host/location-runtime-owner.ts +2 -2
- package/src/runtime/host/service-relocation-host-runtime.ts +101 -65
- package/src/runtime/host/spot-address-transport.ts +67 -61
- package/src/runtime/locations/auto-connect-loop.ts +24 -16
- package/src/runtime/locations/auto-connect-planner.ts +2 -5
- package/src/runtime/locations/auto-connect-reconciler.ts +37 -24
- package/src/runtime/locations/in-memory-location-store.ts +1 -74
- package/src/runtime/locations/location-store-repository.ts +32 -153
- package/src/runtime/locations/runtime.ts +16 -28
- package/src/runtime/messaging/creation-payload-codec.ts +3 -3
- package/src/runtime/protocol/service_wire_codec.generated.ts +18 -8
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
- package/src/runtime/spots/index.ts +28 -4
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +1 -1
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +16 -6
- package/src/runtime/spots/spot-actor-packet-drain.ts +21 -6
- package/src/runtime/spots/spot-entry-activation.ts +1 -1
- package/src/runtime/spots/spot-node-runtime-manager.ts +8 -6
- package/src/runtime/spots/spot-route-packet-dispatch.ts +8 -4
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +3 -1
- package/src/runtime/spots/spot-serial-executor.ts +1 -1
- package/src/runtime/spots/spot-subscription-dispatch.ts +3 -1
- package/src/runtime/spots/spot-timer.ts +1 -1
- package/src/runtime/streams/actor-session-binding-registry.ts +30 -3
- package/src/runtime/streams/index.ts +30 -4
- package/src/runtime/streams/managed-stream.ts +2 -1
- package/src/runtime/streams/session-calls.ts +9 -14
- package/src/runtime/streams/session-context.ts +6 -11
- package/src/runtime/streams/stream-session-runtime.ts +49 -20
|
@@ -6,7 +6,6 @@ import type { ZLinkDomainLocationStore as ZLinkLocationStore } from './domain-st
|
|
|
6
6
|
import type { ZLinkOwnerLeaseTracker } from './lease-tracker';
|
|
7
7
|
import type { ZLinkAutoConnectLocal } from './auto-connect-types';
|
|
8
8
|
import type { ZLinkAutoConnectReconciler } from './auto-connect-reconciler';
|
|
9
|
-
import { ZLinkStateLane } from '../execution/state-lane';
|
|
10
9
|
|
|
11
10
|
export interface ZLinkAutoConnectLoopOptions {
|
|
12
11
|
readonly reconciler: ZLinkAutoConnectReconciler;
|
|
@@ -19,7 +18,6 @@ export interface ZLinkAutoConnectLoopOptions {
|
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
export class ZLinkAutoConnectLoop {
|
|
22
|
-
private readonly lane = new ZLinkStateLane();
|
|
23
21
|
private readonly reconciler: ZLinkAutoConnectReconciler;
|
|
24
22
|
private readonly options: Required<ZLinkLocationOptionOverrides>;
|
|
25
23
|
private readonly meshName: string;
|
|
@@ -46,15 +44,19 @@ export class ZLinkAutoConnectLoop {
|
|
|
46
44
|
}
|
|
47
45
|
|
|
48
46
|
async start(signal?: AbortSignal): Promise<void> {
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
|
|
47
|
+
if (this.controller !== undefined) return;
|
|
48
|
+
// Reserve the lifecycle before yielding so stop also owns the first publication.
|
|
49
|
+
const controller = new AbortController();
|
|
50
|
+
this.controller = controller;
|
|
51
|
+
try {
|
|
52
|
+
await this.tick(signal);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
if (this.controller === controller) {
|
|
55
|
+
await this.prepareTransportShutdown();
|
|
56
|
+
}
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
this.scheduleNext(controller);
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
async requestPeerReconcile(meshName: string, _peerRid: string): Promise<void> {
|
|
@@ -91,8 +93,14 @@ export class ZLinkAutoConnectLoop {
|
|
|
91
93
|
|
|
92
94
|
async tick(signal?: AbortSignal): Promise<void> {
|
|
93
95
|
const controller = this.controller;
|
|
96
|
+
const tickSignal =
|
|
97
|
+
controller === undefined
|
|
98
|
+
? signal
|
|
99
|
+
: signal === undefined
|
|
100
|
+
? controller.signal
|
|
101
|
+
: AbortSignal.any([signal, controller.signal]);
|
|
94
102
|
await this.enqueueTick(async () => {
|
|
95
|
-
if (
|
|
103
|
+
if (tickSignal?.aborted !== true) await this.tickCore(tickSignal);
|
|
96
104
|
});
|
|
97
105
|
}
|
|
98
106
|
|
|
@@ -144,15 +152,15 @@ export class ZLinkAutoConnectLoop {
|
|
|
144
152
|
return this.lastTickFailed;
|
|
145
153
|
}
|
|
146
154
|
|
|
147
|
-
private scheduleNext(): void {
|
|
148
|
-
if (this.controller
|
|
155
|
+
private scheduleNext(controller: AbortController): void {
|
|
156
|
+
if (this.controller !== controller || controller.signal.aborted) {
|
|
149
157
|
return;
|
|
150
158
|
}
|
|
151
159
|
this.timer = this.setTimer(() => {
|
|
152
160
|
this.timer = undefined;
|
|
153
|
-
void this.tick(
|
|
161
|
+
void this.tick(controller.signal)
|
|
154
162
|
.catch(() => undefined)
|
|
155
|
-
.finally(() => this.scheduleNext());
|
|
163
|
+
.finally(() => this.scheduleNext(controller));
|
|
156
164
|
}, this.options.pollingIntervalMs);
|
|
157
165
|
}
|
|
158
166
|
}
|
|
@@ -130,14 +130,11 @@ function targetOf(peer: ZLinkPeerLocation): ZLinkAutoConnectTarget {
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
function isAutoConnectSelf(local: ZLinkAutoConnectLocal, peer: ZLinkPeerLocation): boolean {
|
|
133
|
-
|
|
133
|
+
return (
|
|
134
134
|
local.nodeRid !== undefined &&
|
|
135
135
|
peer.nodeRid !== undefined &&
|
|
136
136
|
routingIdsEqual(local.nodeRid, peer.nodeRid)
|
|
137
|
-
)
|
|
138
|
-
return true;
|
|
139
|
-
}
|
|
140
|
-
return peer.endpoint === local.endpoint;
|
|
137
|
+
);
|
|
141
138
|
}
|
|
142
139
|
|
|
143
140
|
function shouldDialAutoConnectPeer(local: ZLinkAutoConnectLocal, peer: ZLinkPeerLocation): boolean {
|
|
@@ -101,12 +101,7 @@ export class ZLinkAutoConnectReconciler {
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
async tick(signal?: AbortSignal): Promise<void> {
|
|
104
|
-
|
|
105
|
-
await this.publishLocal(signal);
|
|
106
|
-
} catch {
|
|
107
|
-
await this.recordStoreFailure();
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
104
|
+
if (!(await this.publishLocalForTick(signal))) return;
|
|
110
105
|
|
|
111
106
|
if (!this.reconcilePeers) {
|
|
112
107
|
await this.lane.run(() => {
|
|
@@ -125,8 +120,9 @@ export class ZLinkAutoConnectReconciler {
|
|
|
125
120
|
},
|
|
126
121
|
signal
|
|
127
122
|
);
|
|
123
|
+
signal?.throwIfAborted();
|
|
128
124
|
} catch {
|
|
129
|
-
await this.recordStoreFailure();
|
|
125
|
+
await this.recordStoreFailure(signal);
|
|
130
126
|
return;
|
|
131
127
|
}
|
|
132
128
|
|
|
@@ -144,16 +140,7 @@ export class ZLinkAutoConnectReconciler {
|
|
|
144
140
|
await this.lane.run(() => {
|
|
145
141
|
this.localPublished = false;
|
|
146
142
|
});
|
|
147
|
-
|
|
148
|
-
const republished = await this.publishLocal(signal);
|
|
149
|
-
if (!republished) {
|
|
150
|
-
await this.recordStoreFailure();
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
} catch {
|
|
154
|
-
await this.recordStoreFailure();
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
143
|
+
if (!(await this.publishLocalForTick(signal))) return;
|
|
157
144
|
}
|
|
158
145
|
|
|
159
146
|
if (await this.lane.run(() => this.storeFailedValue)) {
|
|
@@ -323,21 +310,44 @@ export class ZLinkAutoConnectReconciler {
|
|
|
323
310
|
this.executor.disconnect(target);
|
|
324
311
|
}
|
|
325
312
|
|
|
313
|
+
private async publishLocalForTick(signal?: AbortSignal): Promise<boolean> {
|
|
314
|
+
let published: boolean;
|
|
315
|
+
try {
|
|
316
|
+
published = await this.publishLocal(signal);
|
|
317
|
+
signal?.throwIfAborted();
|
|
318
|
+
} catch {
|
|
319
|
+
await this.recordStoreFailure(signal);
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
if (!published) {
|
|
323
|
+
await this.recordStoreFailure(signal);
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
|
|
326
329
|
private async publishLocal(signal?: AbortSignal): Promise<boolean> {
|
|
330
|
+
signal?.throwIfAborted();
|
|
327
331
|
const prepared = await this.lane.run(() => this.preparePublishLocalCore());
|
|
328
|
-
if (prepared === undefined)
|
|
332
|
+
if (prepared === undefined) {
|
|
333
|
+
return this.localRow === undefined || (await this.lane.run(() => this.localPublished));
|
|
334
|
+
}
|
|
329
335
|
const claimed = await this.runtime.writePeer(
|
|
330
336
|
prepared.row,
|
|
331
337
|
ZLinkLocationWriteIntent.NewClaim,
|
|
332
338
|
signal
|
|
333
339
|
);
|
|
334
340
|
if (claimed.status === ZLinkLocationWriteStatus.Stored) {
|
|
335
|
-
return await this.lane.run(() =>
|
|
341
|
+
return await this.lane.run(() => {
|
|
342
|
+
signal?.throwIfAborted();
|
|
343
|
+
return this.completePublishClaimCore(claimed.generation);
|
|
344
|
+
});
|
|
336
345
|
}
|
|
337
346
|
|
|
338
|
-
const renewal = await this.lane.run(() =>
|
|
339
|
-
|
|
340
|
-
|
|
347
|
+
const renewal = await this.lane.run(() => {
|
|
348
|
+
signal?.throwIfAborted();
|
|
349
|
+
return this.preparePublishRenewalCore(prepared.row, claimed.status);
|
|
350
|
+
});
|
|
341
351
|
if (renewal !== undefined) {
|
|
342
352
|
const renewed = await this.runtime.writePeer(
|
|
343
353
|
{
|
|
@@ -348,6 +358,7 @@ export class ZLinkAutoConnectReconciler {
|
|
|
348
358
|
signal
|
|
349
359
|
);
|
|
350
360
|
return await this.lane.run(() => {
|
|
361
|
+
signal?.throwIfAborted();
|
|
351
362
|
this.localPublished = renewed.status === ZLinkLocationWriteStatus.Stored;
|
|
352
363
|
return this.localPublished;
|
|
353
364
|
});
|
|
@@ -397,8 +408,10 @@ export class ZLinkAutoConnectReconciler {
|
|
|
397
408
|
: undefined;
|
|
398
409
|
}
|
|
399
410
|
|
|
400
|
-
private async recordStoreFailure(): Promise<void> {
|
|
401
|
-
const retryTargets = await this.lane.run(() =>
|
|
411
|
+
private async recordStoreFailure(signal?: AbortSignal): Promise<void> {
|
|
412
|
+
const retryTargets = await this.lane.run(() =>
|
|
413
|
+
signal?.aborted === true ? undefined : this.beginStoreFailureCore()
|
|
414
|
+
);
|
|
402
415
|
if (retryTargets === undefined) return;
|
|
403
416
|
for (const [key, target] of retryTargets) {
|
|
404
417
|
await this.connectTarget(target, async () => {
|
|
@@ -1054,52 +1054,7 @@ export class ZLinkInMemoryLocationStore
|
|
|
1054
1054
|
) {
|
|
1055
1055
|
return 0n;
|
|
1056
1056
|
}
|
|
1057
|
-
|
|
1058
|
-
let removed = Number(await this.authority.removeAllByOwner(owner, signal));
|
|
1059
|
-
for (const [key, row] of [...this.meshNodes.rows]) {
|
|
1060
|
-
if (row.ownerId !== owner.ownerId) continue;
|
|
1061
|
-
this.meshNodes.rows.delete(key);
|
|
1062
|
-
this.releaseEntrySpotIdentity(row);
|
|
1063
|
-
this.bump(ZLinkLocationKind.Peer, row.meshName);
|
|
1064
|
-
removed++;
|
|
1065
|
-
}
|
|
1066
|
-
removed += this.removeByOwner(
|
|
1067
|
-
this.peers,
|
|
1068
|
-
ownerId,
|
|
1069
|
-
(row) => row.ownerId,
|
|
1070
|
-
ZLinkLocationKind.Peer,
|
|
1071
|
-
(row) => row.meshName
|
|
1072
|
-
);
|
|
1073
|
-
removed += this.removeByOwner(
|
|
1074
|
-
this.spots,
|
|
1075
|
-
ownerId,
|
|
1076
|
-
(row) => row.ownerId,
|
|
1077
|
-
ZLinkLocationKind.Spot,
|
|
1078
|
-
(row) => row.meshName
|
|
1079
|
-
);
|
|
1080
|
-
removed += this.removeByOwner(
|
|
1081
|
-
this.actors,
|
|
1082
|
-
ownerId,
|
|
1083
|
-
(row) => row.ownerId,
|
|
1084
|
-
ZLinkLocationKind.Actor,
|
|
1085
|
-
() => undefined
|
|
1086
|
-
);
|
|
1087
|
-
removed += this.removeByOwner(
|
|
1088
|
-
this.routes,
|
|
1089
|
-
ownerId,
|
|
1090
|
-
(row) => row.ownerId,
|
|
1091
|
-
ZLinkLocationKind.Route,
|
|
1092
|
-
() => undefined
|
|
1093
|
-
);
|
|
1094
|
-
removed += this.removeByOwner(
|
|
1095
|
-
this.clientServers,
|
|
1096
|
-
ownerId,
|
|
1097
|
-
(row) => row.ownerId,
|
|
1098
|
-
ZLinkLocationKind.ClientServer,
|
|
1099
|
-
(row) => row.channelName
|
|
1100
|
-
);
|
|
1101
|
-
removed += this.removeFanoutByOwner(owner);
|
|
1102
|
-
return BigInt(removed);
|
|
1057
|
+
return this.authority.removeAllByOwner(owner, signal);
|
|
1103
1058
|
}
|
|
1104
1059
|
|
|
1105
1060
|
private claimEntrySpotIdentity(
|
|
@@ -1247,24 +1202,6 @@ export class ZLinkInMemoryLocationStore
|
|
|
1247
1202
|
return stored(owner.leaseGeneration, this.now());
|
|
1248
1203
|
}
|
|
1249
1204
|
|
|
1250
|
-
private removeByOwner<TRow>(
|
|
1251
|
-
table: RowTable<TRow>,
|
|
1252
|
-
ownerId: string,
|
|
1253
|
-
ownerOf: (row: TRow) => string,
|
|
1254
|
-
kind: ZLinkLocationKind,
|
|
1255
|
-
meshOf: (row: TRow) => string | undefined
|
|
1256
|
-
): number {
|
|
1257
|
-
let removed = 0;
|
|
1258
|
-
for (const [key, row] of [...table.rows.entries()]) {
|
|
1259
|
-
if (ownerOf(row) === ownerId) {
|
|
1260
|
-
table.rows.delete(key);
|
|
1261
|
-
this.bump(kind, meshOf(row));
|
|
1262
|
-
removed++;
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
return removed;
|
|
1266
|
-
}
|
|
1267
|
-
|
|
1268
1205
|
private liveOwnerLease(ownerId: string, now: Date): InMemoryOwnerLease | undefined {
|
|
1269
1206
|
const lease = this.leases.get(ownerId);
|
|
1270
1207
|
return lease !== undefined && lease.leaseExpiresAt.getTime() > now.getTime()
|
|
@@ -1279,16 +1216,6 @@ export class ZLinkInMemoryLocationStore
|
|
|
1279
1216
|
}
|
|
1280
1217
|
}
|
|
1281
1218
|
|
|
1282
|
-
private removeFanoutByOwner(owner: ZLinkLocationOwnerToken): number {
|
|
1283
|
-
let removed = 0;
|
|
1284
|
-
for (const [key, row] of this.fanoutPublishers.rows) {
|
|
1285
|
-
if (row.ownerId !== owner.ownerId) continue;
|
|
1286
|
-
this.fanoutPublishers.rows.delete(key);
|
|
1287
|
-
removed++;
|
|
1288
|
-
}
|
|
1289
|
-
return removed;
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
1219
|
private bumpScope(scope: ZLinkLocationChangeStampScope): void {
|
|
1293
1220
|
const key = stampKey(scope);
|
|
1294
1221
|
this.stamps.set(key, (this.stamps.get(key) ?? 0n) + 1n);
|
|
@@ -206,12 +206,6 @@ interface OwnerCleanupCandidate {
|
|
|
206
206
|
readonly scanVersion: ZLinkStoreVersion;
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
-
interface OwnerCleanupRecord {
|
|
210
|
-
readonly descriptor: OwnedStoreRecord;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const MAX_OWNER_CLEANUP_BATCH_ROWS = 2_047;
|
|
214
|
-
|
|
215
209
|
/**
|
|
216
210
|
* Maps framework domain records to the minimal provider SPI.
|
|
217
211
|
*
|
|
@@ -1335,11 +1329,18 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1335
1329
|
key: ZLinkAuthorityKey,
|
|
1336
1330
|
expectedStoreVersion: string,
|
|
1337
1331
|
signal?: AbortSignal,
|
|
1338
|
-
request?: ZLinkEndedOwnerReleaseIntent
|
|
1332
|
+
request?: ZLinkEndedOwnerReleaseIntent,
|
|
1333
|
+
requiredOwner?: ZLinkLocationOwnerToken
|
|
1339
1334
|
): Promise<boolean> {
|
|
1340
1335
|
return (
|
|
1341
|
-
(await this.tryReleaseEndedReservation(
|
|
1342
|
-
|
|
1336
|
+
(await this.tryReleaseEndedReservation(
|
|
1337
|
+
key,
|
|
1338
|
+
expectedStoreVersion,
|
|
1339
|
+
signal,
|
|
1340
|
+
request,
|
|
1341
|
+
undefined,
|
|
1342
|
+
requiredOwner
|
|
1343
|
+
)) === 'reclaimed'
|
|
1343
1344
|
);
|
|
1344
1345
|
}
|
|
1345
1346
|
|
|
@@ -1348,7 +1349,8 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1348
1349
|
expectedStoreVersion: string,
|
|
1349
1350
|
signal?: AbortSignal,
|
|
1350
1351
|
request?: ZLinkEndedOwnerReleaseIntent,
|
|
1351
|
-
deadlineUnixMs?: bigint
|
|
1352
|
+
deadlineUnixMs?: bigint,
|
|
1353
|
+
requiredOwner?: ZLinkLocationOwnerToken
|
|
1352
1354
|
): Promise<'notReclaimable' | 'conflict' | 'reclaimed'> {
|
|
1353
1355
|
for (;;) {
|
|
1354
1356
|
throwIfOperationExpired(signal, deadlineUnixMs);
|
|
@@ -1383,6 +1385,13 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1383
1385
|
this.provider.read(capacityRowKey, signal)
|
|
1384
1386
|
]);
|
|
1385
1387
|
const ownerLive = sameLiveOwner(lease, snapshot);
|
|
1388
|
+
if (
|
|
1389
|
+
requiredOwner !== undefined &&
|
|
1390
|
+
(!ownerLive ||
|
|
1391
|
+
requiredOwner.ownerId !== snapshot.ownerId ||
|
|
1392
|
+
requiredOwner.leaseGeneration !== snapshot.ownerLeaseGeneration)
|
|
1393
|
+
)
|
|
1394
|
+
return 'notReclaimable';
|
|
1386
1395
|
let members: EndedSpotMember[] = [];
|
|
1387
1396
|
if (snapshot.allocation.state === 'active') {
|
|
1388
1397
|
if (ownerLive) return 'notReclaimable';
|
|
@@ -2852,50 +2861,7 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2852
2861
|
const leaseKey = ownerKey(owner.ownerId);
|
|
2853
2862
|
const lease = await this.provider.read(leaseKey, signal);
|
|
2854
2863
|
if (liveOwnerLeaseGeneration(lease) !== owner.leaseGeneration) return 0n;
|
|
2855
|
-
|
|
2856
|
-
const candidates: OwnerCleanupCandidate[] = [];
|
|
2857
|
-
for (const prefix of [
|
|
2858
|
-
'mesh-node\0',
|
|
2859
|
-
'client-server\0',
|
|
2860
|
-
'fanout-publisher\0',
|
|
2861
|
-
`${PREFIX}spot:`,
|
|
2862
|
-
`${PREFIX}actor:`,
|
|
2863
|
-
`${PREFIX}route:`
|
|
2864
|
-
]) {
|
|
2865
|
-
for (;;) {
|
|
2866
|
-
const prefixCandidates: OwnerCleanupCandidate[] = [];
|
|
2867
|
-
let cursor: ZLinkStoreScanCursor | undefined;
|
|
2868
|
-
let expired = false;
|
|
2869
|
-
do {
|
|
2870
|
-
const result = await this.provider.scan({ prefix, cursor, limit: 1_000 }, signal);
|
|
2871
|
-
if (result.kind === 'expired') {
|
|
2872
|
-
expired = true;
|
|
2873
|
-
break;
|
|
2874
|
-
}
|
|
2875
|
-
for (const item of result.value.items) {
|
|
2876
|
-
prefixCandidates.push({ key: item.key, scanVersion: item.value.version });
|
|
2877
|
-
}
|
|
2878
|
-
cursor = result.value.nextCursor;
|
|
2879
|
-
} while (cursor !== undefined);
|
|
2880
|
-
if (expired) {
|
|
2881
|
-
// Snapshot scan expiry invalidates every page from this prefix.
|
|
2882
|
-
// Restart from its first page instead of silently leaving rows
|
|
2883
|
-
// behind after a partial scan.
|
|
2884
|
-
continue;
|
|
2885
|
-
}
|
|
2886
|
-
candidates.push(...prefixCandidates);
|
|
2887
|
-
break;
|
|
2888
|
-
}
|
|
2889
|
-
}
|
|
2890
|
-
for (let offset = 0; offset < candidates.length; offset += MAX_OWNER_CLEANUP_BATCH_ROWS) {
|
|
2891
|
-
removed += await this.removeOwnerCleanupBatch(
|
|
2892
|
-
owner,
|
|
2893
|
-
leaseKey,
|
|
2894
|
-
candidates.slice(offset, offset + MAX_OWNER_CLEANUP_BATCH_ROWS),
|
|
2895
|
-
signal
|
|
2896
|
-
);
|
|
2897
|
-
}
|
|
2898
|
-
return removed + (await super.removeAllByOwner(owner));
|
|
2864
|
+
return this.removeOwnedAuthorities(owner, signal);
|
|
2899
2865
|
}
|
|
2900
2866
|
|
|
2901
2867
|
private async removeOwnedAuthorities(
|
|
@@ -2978,91 +2944,20 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2978
2944
|
signal
|
|
2979
2945
|
);
|
|
2980
2946
|
if (aborted.kind === 'aborted') removed += 1n;
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
const currentRows = await Promise.all(
|
|
2994
|
-
candidates.map((candidate) => this.provider.read(candidate.key, signal))
|
|
2995
|
-
);
|
|
2996
|
-
const unchangedOwnedRows: OwnerCleanupCandidate[] = [];
|
|
2997
|
-
for (let index = 0; index < candidates.length; index += 1) {
|
|
2998
|
-
const candidate = candidates[index]!;
|
|
2999
|
-
const current = currentRows[index]!;
|
|
3000
|
-
if (
|
|
3001
|
-
current.kind === 'missing' ||
|
|
3002
|
-
current.value.version.value !== candidate.scanVersion.value
|
|
3003
|
-
) {
|
|
3004
|
-
continue;
|
|
3005
|
-
}
|
|
3006
|
-
const record = decodeJson<OwnerCleanupRecord>(current.value.bytes);
|
|
3007
|
-
const descriptor = record.descriptor;
|
|
3008
|
-
if (
|
|
3009
|
-
descriptor.ownerId !== owner.ownerId ||
|
|
3010
|
-
descriptorOwnerLeaseGeneration(descriptor) !== owner.leaseGeneration
|
|
3011
|
-
) {
|
|
3012
|
-
continue;
|
|
2947
|
+
else if (aborted.kind === 'stale') {
|
|
2948
|
+
if (
|
|
2949
|
+
await this.releaseEndedReservationRequest(
|
|
2950
|
+
{ value: encodedAuthority } as ZLinkAuthorityKey,
|
|
2951
|
+
current.value.version.value,
|
|
2952
|
+
signal,
|
|
2953
|
+
undefined,
|
|
2954
|
+
owner
|
|
2955
|
+
)
|
|
2956
|
+
)
|
|
2957
|
+
removed += 1n;
|
|
3013
2958
|
}
|
|
3014
|
-
unchangedOwnedRows.push({
|
|
3015
|
-
key: candidate.key,
|
|
3016
|
-
scanVersion: current.value.version
|
|
3017
|
-
});
|
|
3018
|
-
}
|
|
3019
|
-
if (unchangedOwnedRows.length === 0) return 0n;
|
|
3020
|
-
|
|
3021
|
-
const currentLease = await this.provider.read(leaseKey, signal);
|
|
3022
|
-
if (
|
|
3023
|
-
currentLease.kind === 'missing' ||
|
|
3024
|
-
liveOwnerLeaseGeneration(currentLease) !== owner.leaseGeneration
|
|
3025
|
-
) {
|
|
3026
|
-
return 0n;
|
|
3027
2959
|
}
|
|
3028
|
-
|
|
3029
|
-
{
|
|
3030
|
-
conditions: [
|
|
3031
|
-
{ kind: 'version', key: leaseKey, expected: currentLease.value.version },
|
|
3032
|
-
...unchangedOwnedRows.map((row) => ({
|
|
3033
|
-
kind: 'version' as const,
|
|
3034
|
-
key: row.key,
|
|
3035
|
-
expected: row.scanVersion
|
|
3036
|
-
}))
|
|
3037
|
-
],
|
|
3038
|
-
mutations: unchangedOwnedRows.map((row) => ({
|
|
3039
|
-
kind: 'delete' as const,
|
|
3040
|
-
key: row.key
|
|
3041
|
-
}))
|
|
3042
|
-
},
|
|
3043
|
-
signal
|
|
3044
|
-
);
|
|
3045
|
-
if (result.kind === 'applied') return BigInt(unchangedOwnedRows.length);
|
|
3046
|
-
|
|
3047
|
-
// A row may have changed while the page was being prepared. Split the
|
|
3048
|
-
// bounded batch so unaffected rows can still be removed atomically, while
|
|
3049
|
-
// the changed row is discarded by the next version re-read. A changed
|
|
3050
|
-
// owner lease causes every recursive branch to stop at the fence above.
|
|
3051
|
-
if (unchangedOwnedRows.length === 1) return 0n;
|
|
3052
|
-
const midpoint = Math.ceil(unchangedOwnedRows.length / 2);
|
|
3053
|
-
const left = await this.removeOwnerCleanupBatch(
|
|
3054
|
-
owner,
|
|
3055
|
-
leaseKey,
|
|
3056
|
-
unchangedOwnedRows.slice(0, midpoint),
|
|
3057
|
-
signal
|
|
3058
|
-
);
|
|
3059
|
-
const right = await this.removeOwnerCleanupBatch(
|
|
3060
|
-
owner,
|
|
3061
|
-
leaseKey,
|
|
3062
|
-
unchangedOwnedRows.slice(midpoint),
|
|
3063
|
-
signal
|
|
3064
|
-
);
|
|
3065
|
-
return left + right;
|
|
2960
|
+
return removed;
|
|
3066
2961
|
}
|
|
3067
2962
|
|
|
3068
2963
|
private async updateDescriptor<T extends OwnedDescriptor>(
|
|
@@ -3769,7 +3664,6 @@ type OwnedDescriptor =
|
|
|
3769
3664
|
|
|
3770
3665
|
type LeaseOwnedLocation = ZLinkSpotLocation | ZLinkActorLocation;
|
|
3771
3666
|
type StoredLocation = LeaseOwnedLocation | ZLinkRouteLocation;
|
|
3772
|
-
type OwnedStoreRecord = OwnedDescriptor | StoredLocation;
|
|
3773
3667
|
|
|
3774
3668
|
function validateProviderAggregateRequest(request: ZLinkAggregatePrepareRequest): void {
|
|
3775
3669
|
requireText(request.aggregateId.value, 'aggregate ID');
|
|
@@ -5060,21 +4954,6 @@ function locationOwnerGeneration(value: LeaseOwnedLocation): bigint {
|
|
|
5060
4954
|
return value.leaseGeneration;
|
|
5061
4955
|
}
|
|
5062
4956
|
|
|
5063
|
-
function descriptorOwnerLeaseGeneration(value: OwnedStoreRecord): bigint | undefined {
|
|
5064
|
-
if ('leaseGeneration' in value) {
|
|
5065
|
-
return typeof value.leaseGeneration === 'bigint'
|
|
5066
|
-
? value.leaseGeneration
|
|
5067
|
-
: BigInt(value.leaseGeneration);
|
|
5068
|
-
}
|
|
5069
|
-
if ('generation' in value) {
|
|
5070
|
-
return typeof value.generation === 'bigint' ? value.generation : BigInt(value.generation);
|
|
5071
|
-
}
|
|
5072
|
-
return undefined;
|
|
5073
|
-
}
|
|
5074
|
-
|
|
5075
|
-
// Location runtime §10: a write whose result was lost is confirmed by reading
|
|
5076
|
-
// the same key. The stored row already is this write when it differs only in
|
|
5077
|
-
// the time the Store stamped, as for every other descriptor kind.
|
|
5078
4957
|
function sameMeshDescriptor(
|
|
5079
4958
|
left: ZLinkMeshNodeDescriptor,
|
|
5080
4959
|
right: ZLinkMeshNodeDescriptor
|
|
@@ -220,7 +220,7 @@ export class ZLinkLocationRuntime implements ZLinkLocationRuntimeQuery {
|
|
|
220
220
|
return this.ownerToken;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
/** Location runtime §5: a
|
|
223
|
+
/** Location runtime §5: a descriptor publication ends within the renew timeout. */
|
|
224
224
|
async writeDescriptor<T>(
|
|
225
225
|
action: (signal?: AbortSignal) => Promise<T>,
|
|
226
226
|
signal?: AbortSignal
|
|
@@ -386,7 +386,7 @@ export class ZLinkLocationRuntime implements ZLinkLocationRuntimeQuery {
|
|
|
386
386
|
async cleanupOwner(signal?: AbortSignal): Promise<void> {
|
|
387
387
|
const pending = this.heartbeatRenewal;
|
|
388
388
|
try {
|
|
389
|
-
await
|
|
389
|
+
await (pending ?? Promise.resolve());
|
|
390
390
|
} catch (error) {
|
|
391
391
|
if (!isAbortError(error)) throw error;
|
|
392
392
|
} finally {
|
|
@@ -396,25 +396,14 @@ export class ZLinkLocationRuntime implements ZLinkLocationRuntimeQuery {
|
|
|
396
396
|
return;
|
|
397
397
|
}
|
|
398
398
|
try {
|
|
399
|
-
const owner = this.ownerToken ??
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
const currentLease = await this.stores.ownerLeaseStore.readOwnerLease(
|
|
408
|
-
this.ownerId,
|
|
409
|
-
cleanupSignal
|
|
410
|
-
);
|
|
411
|
-
if (currentLease.kind === 'found') {
|
|
412
|
-
await this.stores.ownerLeaseStore.releaseOwnerLease(currentLease.token, cleanupSignal);
|
|
413
|
-
}
|
|
414
|
-
},
|
|
415
|
-
undefined,
|
|
416
|
-
signal
|
|
417
|
-
);
|
|
399
|
+
const owner = this.ownerToken ?? this.lastOwnerToken;
|
|
400
|
+
signal?.throwIfAborted();
|
|
401
|
+
if (owner !== undefined) {
|
|
402
|
+
await this.stores.locationStore.removeAllByOwner(owner, signal);
|
|
403
|
+
signal?.throwIfAborted();
|
|
404
|
+
await this.stores.ownerLeaseStore.releaseOwnerLease(owner, signal);
|
|
405
|
+
signal?.throwIfAborted();
|
|
406
|
+
}
|
|
418
407
|
this.ownerToken = undefined;
|
|
419
408
|
this.lastOwnerToken = undefined;
|
|
420
409
|
this.ownerCleanupComplete = true;
|
|
@@ -516,7 +505,7 @@ export class ZLinkLocationRuntime implements ZLinkLocationRuntimeQuery {
|
|
|
516
505
|
}
|
|
517
506
|
try {
|
|
518
507
|
if (!this.started) {
|
|
519
|
-
|
|
508
|
+
this.lastOwnerToken = claim.token;
|
|
520
509
|
return false;
|
|
521
510
|
}
|
|
522
511
|
this.lastOwnerToken = this.ownerToken;
|
|
@@ -765,7 +754,10 @@ export class ZLinkLocationRuntime implements ZLinkLocationRuntimeQuery {
|
|
|
765
754
|
const normalizedEndpoint = normalizeEndpoint(peer.endpoint);
|
|
766
755
|
const stamped = { ...peer, endpoint: normalizedEndpoint, ownerId: this.ownerId };
|
|
767
756
|
const result = await this.guardWrite(() =>
|
|
768
|
-
this.
|
|
757
|
+
this.writeDescriptor(
|
|
758
|
+
(writeSignal) => this.stores.peerStore.updatePeer(stamped, intent, writeSignal),
|
|
759
|
+
signal
|
|
760
|
+
)
|
|
769
761
|
);
|
|
770
762
|
const key: ZLinkPeerLocationKey = {
|
|
771
763
|
autoConnectType: peer.autoConnectType,
|
|
@@ -1353,11 +1345,7 @@ export class ZLinkLocationRuntime implements ZLinkLocationRuntimeQuery {
|
|
|
1353
1345
|
}
|
|
1354
1346
|
}
|
|
1355
1347
|
|
|
1356
|
-
|
|
1357
|
-
result: ZLinkLocationWriteResult,
|
|
1358
|
-
kind: ZLinkLocationKind,
|
|
1359
|
-
key: string
|
|
1360
|
-
): void {
|
|
1348
|
+
notifyIfStale(result: ZLinkLocationWriteResult, kind: ZLinkLocationKind, key: string): void {
|
|
1361
1349
|
if (result.status !== ZLinkLocationWriteStatus.IgnoredStale) {
|
|
1362
1350
|
return;
|
|
1363
1351
|
}
|
|
@@ -6,7 +6,7 @@ import { ZLinkBufferMessage as RuntimeMessage } from '../backend/runtime-message
|
|
|
6
6
|
import type { ZLinkMessageSerializer } from '../../contracts';
|
|
7
7
|
import {
|
|
8
8
|
decodeApplicationPayloadView,
|
|
9
|
-
|
|
9
|
+
encodeOwnedApplicationPayload
|
|
10
10
|
} from '../foundation/service-wire-m6a-codec';
|
|
11
11
|
import {
|
|
12
12
|
decodeFrameworkPayloadMessage,
|
|
@@ -23,7 +23,7 @@ export function encodeFrameworkCreationPayload(
|
|
|
23
23
|
): Buffer {
|
|
24
24
|
const message = encodeFrameworkPayloadMessage(payload ?? null, registry);
|
|
25
25
|
try {
|
|
26
|
-
return
|
|
26
|
+
return encodeOwnedApplicationPayload({
|
|
27
27
|
packetName: CREATION_PACKET_NAME,
|
|
28
28
|
contentType: frameworkPayloadContentType(message),
|
|
29
29
|
payload: message.data()
|
|
@@ -42,7 +42,7 @@ export function decodeFrameworkCreationPayload<T>(
|
|
|
42
42
|
if (application.packetName !== CREATION_PACKET_NAME) {
|
|
43
43
|
throw new RangeError('Creation payload has an unexpected packet name.');
|
|
44
44
|
}
|
|
45
|
-
//
|
|
45
|
+
// Creation frames use owned storage and stay alive through synchronous decode.
|
|
46
46
|
const message = RuntimeMessage.fromOwned(application.payload as Buffer);
|
|
47
47
|
try {
|
|
48
48
|
return decodeFrameworkPayloadMessage<T>(
|