@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.
Files changed (171) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Actors/ZLinkActor.d.ts +2 -0
  3. package/dist/contracts/Actors/ZLinkSessionBindingIdentity.d.ts +6 -0
  4. package/dist/contracts/Actors/ZLinkSessionBindingIdentity.js +2 -0
  5. package/dist/contracts/Actors/index.d.ts +1 -0
  6. package/dist/contracts/Actors/index.js +1 -0
  7. package/dist/contracts/Common/payload-slab.d.ts +4 -0
  8. package/dist/contracts/Common/payload-slab.js +30 -0
  9. package/dist/contracts/Handlers/Contexts.d.ts +1 -0
  10. package/dist/internal.d.ts +9 -0
  11. package/dist/internal.js +23 -1
  12. package/dist/runtime/actors/actor-client.d.ts +1 -1
  13. package/dist/runtime/actors/actor-client.js +32 -23
  14. package/dist/runtime/actors/actor-mailbox.d.ts +1 -1
  15. package/dist/runtime/actors/actor-runtime-state.d.ts +1 -1
  16. package/dist/runtime/actors/spot-actor-dispatch.d.ts +4 -2
  17. package/dist/runtime/actors/spot-actor-dispatch.js +2 -1
  18. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +1 -0
  19. package/dist/runtime/application-jobs/application-ingress-record-owner.js +3 -0
  20. package/dist/runtime/backend/contracts/index.d.ts +2 -0
  21. package/dist/runtime/backend/mesh-completion-table.d.ts +1 -0
  22. package/dist/runtime/backend/mesh-completion-table.js +1 -0
  23. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +5 -1
  24. package/dist/runtime/backend/node/node-raw-binding-port.d.ts +7 -2
  25. package/dist/runtime/backend/node/node-raw-binding-port.js +17 -11
  26. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +2 -2
  27. package/dist/runtime/backend/node/node-raw-mesh-backend.js +15 -8
  28. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +7 -6
  29. package/dist/runtime/channels/channel-dispatch-pipeline.js +1 -0
  30. package/dist/runtime/channels/channel-dispatchers.d.ts +7 -3
  31. package/dist/runtime/channels/channel-dispatchers.js +27 -19
  32. package/dist/runtime/channels/channel-envelope.js +543 -23
  33. package/dist/runtime/channels/channel-receive-loops.d.ts +9 -6
  34. package/dist/runtime/channels/channel-receive-loops.js +59 -18
  35. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +22 -3
  36. package/dist/runtime/channels/channel-socket-registry.d.ts +22 -4
  37. package/dist/runtime/diagnostics/runtime-metrics.d.ts +1 -1
  38. package/dist/runtime/diagnostics/runtime-metrics.js +2 -1
  39. package/dist/runtime/execution/serial-execution-queue.d.ts +26 -13
  40. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +27 -11
  41. package/dist/runtime/foundation/raw-service-mesh-runtime.js +29 -25
  42. package/dist/runtime/foundation/service-liveness-registry.d.ts +1 -1
  43. package/dist/runtime/foundation/service-mailbox.d.ts +3 -1
  44. package/dist/runtime/foundation/service-mailbox.js +4 -1
  45. package/dist/runtime/foundation/service-runtime-contracts.d.ts +3 -1
  46. package/dist/runtime/foundation/service-stateful-registry.d.ts +2 -0
  47. package/dist/runtime/foundation/service-stateful-registry.js +28 -12
  48. package/dist/runtime/foundation/service-stateful-runtime.d.ts +51 -19
  49. package/dist/runtime/foundation/service-stateful-runtime.js +54 -5
  50. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +3 -0
  51. package/dist/runtime/foundation/service-stateful-wire-codec.js +15 -0
  52. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  53. package/dist/runtime/foundation/service-wire-constants.generated.js +12 -0
  54. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +2 -0
  55. package/dist/runtime/foundation/service-wire-m6a-codec.js +17 -7
  56. package/dist/runtime/host/actor-placement-coordinator.d.ts +1 -1
  57. package/dist/runtime/host/actor-transfer-runtime.d.ts +3 -3
  58. package/dist/runtime/host/application-job-queue.d.ts +1 -1
  59. package/dist/runtime/host/index.d.ts +89 -36
  60. package/dist/runtime/host/index.js +101 -7
  61. package/dist/runtime/host/location-runtime-owner.d.ts +2 -2
  62. package/dist/runtime/host/service-relocation-host-runtime.d.ts +181 -44
  63. package/dist/runtime/host/service-relocation-host-runtime.js +47 -13
  64. package/dist/runtime/host/spot-address-transport.js +50 -42
  65. package/dist/runtime/locations/auto-connect-loop.d.ts +0 -1
  66. package/dist/runtime/locations/auto-connect-loop.js +25 -19
  67. package/dist/runtime/locations/auto-connect-planner.js +2 -5
  68. package/dist/runtime/locations/auto-connect-reconciler.d.ts +1 -0
  69. package/dist/runtime/locations/auto-connect-reconciler.js +35 -23
  70. package/dist/runtime/locations/in-memory-location-store.d.ts +0 -2
  71. package/dist/runtime/locations/in-memory-location-store.js +1 -38
  72. package/dist/runtime/locations/location-store-repository.d.ts +0 -1
  73. package/dist/runtime/locations/location-store-repository.js +13 -115
  74. package/dist/runtime/locations/runtime.d.ts +3 -3
  75. package/dist/runtime/locations/runtime.js +12 -16
  76. package/dist/runtime/messaging/creation-payload-codec.js +2 -2
  77. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +4 -0
  78. package/dist/runtime/protocol/service_wire_codec.generated.js +17 -7
  79. package/dist/runtime/spots/index.d.ts +20 -5
  80. package/dist/runtime/spots/index.js +14 -0
  81. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +3 -3
  82. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +1 -0
  83. package/dist/runtime/spots/spot-actor-packet-dispatch.js +13 -7
  84. package/dist/runtime/spots/spot-actor-packet-drain.d.ts +1 -0
  85. package/dist/runtime/spots/spot-actor-packet-drain.js +12 -5
  86. package/dist/runtime/spots/spot-entry-activation.d.ts +2 -1
  87. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +8 -6
  88. package/dist/runtime/spots/spot-node-runtime-manager.js +2 -0
  89. package/dist/runtime/spots/spot-route-packet-dispatch.js +7 -4
  90. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +3 -1
  91. package/dist/runtime/spots/spot-serial-executor.d.ts +2 -1
  92. package/dist/runtime/spots/spot-subscription-dispatch.js +3 -1
  93. package/dist/runtime/spots/spot-timer.d.ts +1 -1
  94. package/dist/runtime/streams/actor-session-binding-registry.d.ts +9 -3
  95. package/dist/runtime/streams/actor-session-binding-registry.js +17 -0
  96. package/dist/runtime/streams/index.d.ts +3 -3
  97. package/dist/runtime/streams/index.js +22 -2
  98. package/dist/runtime/streams/managed-stream.js +2 -1
  99. package/dist/runtime/streams/session-calls.d.ts +1 -1
  100. package/dist/runtime/streams/session-calls.js +3 -9
  101. package/dist/runtime/streams/session-context.d.ts +2 -2
  102. package/dist/runtime/streams/session-context.js +2 -2
  103. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -0
  104. package/dist/runtime/streams/stream-session-runtime.js +37 -12
  105. package/package.json +3 -3
  106. package/src/contracts/Actors/ZLinkActor.ts +6 -0
  107. package/src/contracts/Actors/ZLinkSessionBindingIdentity.ts +7 -0
  108. package/src/contracts/Actors/index.ts +1 -0
  109. package/src/contracts/Common/payload-slab.ts +29 -0
  110. package/src/contracts/Handlers/Contexts.ts +1 -0
  111. package/src/internal.ts +17 -0
  112. package/src/runtime/actors/actor-client.ts +48 -23
  113. package/src/runtime/actors/actor-mailbox.ts +1 -1
  114. package/src/runtime/actors/actor-runtime-state.ts +1 -1
  115. package/src/runtime/actors/spot-actor-dispatch.ts +4 -3
  116. package/src/runtime/application-jobs/application-ingress-record-owner.ts +4 -0
  117. package/src/runtime/backend/contracts/index.ts +2 -0
  118. package/src/runtime/backend/mesh-completion-table.ts +2 -0
  119. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +5 -1
  120. package/src/runtime/backend/node/node-raw-binding-port.ts +20 -7
  121. package/src/runtime/backend/node/node-raw-mesh-backend.ts +18 -10
  122. package/src/runtime/channels/channel-dispatch-pipeline.ts +6 -5
  123. package/src/runtime/channels/channel-dispatchers.ts +39 -19
  124. package/src/runtime/channels/channel-envelope.ts +547 -20
  125. package/src/runtime/channels/channel-receive-loops.ts +93 -36
  126. package/src/runtime/channels/channel-runtime-lifecycle.ts +2 -2
  127. package/src/runtime/channels/channel-socket-registry.ts +3 -3
  128. package/src/runtime/diagnostics/runtime-metrics.ts +3 -1
  129. package/src/runtime/execution/serial-execution-queue.ts +13 -13
  130. package/src/runtime/foundation/raw-service-mesh-runtime.ts +40 -39
  131. package/src/runtime/foundation/service-liveness-registry.ts +1 -1
  132. package/src/runtime/foundation/service-mailbox.ts +6 -1
  133. package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
  134. package/src/runtime/foundation/service-stateful-registry.ts +39 -14
  135. package/src/runtime/foundation/service-stateful-runtime.ts +87 -21
  136. package/src/runtime/foundation/service-stateful-wire-codec.ts +18 -0
  137. package/src/runtime/foundation/service-wire-constants.generated.ts +10 -0
  138. package/src/runtime/foundation/service-wire-m6a-codec.ts +29 -7
  139. package/src/runtime/host/actor-placement-coordinator.ts +1 -1
  140. package/src/runtime/host/actor-transfer-runtime.ts +3 -3
  141. package/src/runtime/host/application-job-queue.ts +1 -1
  142. package/src/runtime/host/index.ts +183 -44
  143. package/src/runtime/host/location-runtime-owner.ts +2 -2
  144. package/src/runtime/host/service-relocation-host-runtime.ts +101 -65
  145. package/src/runtime/host/spot-address-transport.ts +67 -61
  146. package/src/runtime/locations/auto-connect-loop.ts +24 -16
  147. package/src/runtime/locations/auto-connect-planner.ts +2 -5
  148. package/src/runtime/locations/auto-connect-reconciler.ts +37 -24
  149. package/src/runtime/locations/in-memory-location-store.ts +1 -74
  150. package/src/runtime/locations/location-store-repository.ts +32 -153
  151. package/src/runtime/locations/runtime.ts +16 -28
  152. package/src/runtime/messaging/creation-payload-codec.ts +3 -3
  153. package/src/runtime/protocol/service_wire_codec.generated.ts +18 -8
  154. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
  155. package/src/runtime/spots/index.ts +28 -4
  156. package/src/runtime/spots/spot-actor-admission-coordinator.ts +1 -1
  157. package/src/runtime/spots/spot-actor-packet-dispatch.ts +16 -6
  158. package/src/runtime/spots/spot-actor-packet-drain.ts +21 -6
  159. package/src/runtime/spots/spot-entry-activation.ts +1 -1
  160. package/src/runtime/spots/spot-node-runtime-manager.ts +8 -6
  161. package/src/runtime/spots/spot-route-packet-dispatch.ts +8 -4
  162. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +3 -1
  163. package/src/runtime/spots/spot-serial-executor.ts +1 -1
  164. package/src/runtime/spots/spot-subscription-dispatch.ts +3 -1
  165. package/src/runtime/spots/spot-timer.ts +1 -1
  166. package/src/runtime/streams/actor-session-binding-registry.ts +30 -3
  167. package/src/runtime/streams/index.ts +30 -4
  168. package/src/runtime/streams/managed-stream.ts +2 -1
  169. package/src/runtime/streams/session-calls.ts +9 -14
  170. package/src/runtime/streams/session-context.ts +6 -11
  171. package/src/runtime/streams/stream-session-runtime.ts +49 -20
@@ -2,9 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ZLinkAutoConnectLoop = void 0;
4
4
  const Options_1 = require("../../contracts/Locations/Options");
5
- const state_lane_1 = require("../execution/state-lane");
6
5
  class ZLinkAutoConnectLoop {
7
- lane = new state_lane_1.ZLinkStateLane();
8
6
  reconciler;
9
7
  options;
10
8
  meshName;
@@ -29,18 +27,21 @@ class ZLinkAutoConnectLoop {
29
27
  this.clearTimer = options.clearTimer ?? ((handle) => clearTimeout(handle));
30
28
  }
31
29
  async start(signal) {
32
- if (await this.lane.run(() => this.controller !== undefined))
30
+ if (this.controller !== undefined)
33
31
  return;
34
- await this.tick(signal);
35
- const started = await this.lane.run(() => {
36
- if (this.controller !== undefined)
37
- return false;
38
- this.controller = new AbortController();
39
- return true;
40
- });
41
- if (!started)
42
- return;
43
- this.scheduleNext();
32
+ // Reserve the lifecycle before yielding so stop also owns the first publication.
33
+ const controller = new AbortController();
34
+ this.controller = controller;
35
+ try {
36
+ await this.tick(signal);
37
+ }
38
+ catch (error) {
39
+ if (this.controller === controller) {
40
+ await this.prepareTransportShutdown();
41
+ }
42
+ throw error;
43
+ }
44
+ this.scheduleNext(controller);
44
45
  }
45
46
  async requestPeerReconcile(meshName, _peerRid) {
46
47
  const controller = this.controller;
@@ -74,9 +75,14 @@ class ZLinkAutoConnectLoop {
74
75
  }
75
76
  async tick(signal) {
76
77
  const controller = this.controller;
78
+ const tickSignal = controller === undefined
79
+ ? signal
80
+ : signal === undefined
81
+ ? controller.signal
82
+ : AbortSignal.any([signal, controller.signal]);
77
83
  await this.enqueueTick(async () => {
78
- if (controller?.signal.aborted !== true)
79
- await this.tickCore(signal ?? controller?.signal);
84
+ if (tickSignal?.aborted !== true)
85
+ await this.tickCore(tickSignal);
80
86
  });
81
87
  }
82
88
  enqueueTick(operation) {
@@ -118,15 +124,15 @@ class ZLinkAutoConnectLoop {
118
124
  this.lastTickFailed = this.reconciler.storeFailed;
119
125
  return this.lastTickFailed;
120
126
  }
121
- scheduleNext() {
122
- if (this.controller === undefined || this.controller.signal.aborted) {
127
+ scheduleNext(controller) {
128
+ if (this.controller !== controller || controller.signal.aborted) {
123
129
  return;
124
130
  }
125
131
  this.timer = this.setTimer(() => {
126
132
  this.timer = undefined;
127
- void this.tick(this.controller?.signal)
133
+ void this.tick(controller.signal)
128
134
  .catch(() => undefined)
129
- .finally(() => this.scheduleNext());
135
+ .finally(() => this.scheduleNext(controller));
130
136
  }, this.options.pollingIntervalMs);
131
137
  }
132
138
  }
@@ -94,12 +94,9 @@ function targetOf(peer) {
94
94
  };
95
95
  }
96
96
  function isAutoConnectSelf(local, peer) {
97
- if (local.nodeRid !== undefined &&
97
+ return (local.nodeRid !== undefined &&
98
98
  peer.nodeRid !== undefined &&
99
- (0, routing_id_1.routingIdsEqual)(local.nodeRid, peer.nodeRid)) {
100
- return true;
101
- }
102
- return peer.endpoint === local.endpoint;
99
+ (0, routing_id_1.routingIdsEqual)(local.nodeRid, peer.nodeRid));
103
100
  }
104
101
  function shouldDialAutoConnectPeer(local, peer) {
105
102
  switch (local.autoConnectType) {
@@ -47,6 +47,7 @@ export declare class ZLinkAutoConnectReconciler {
47
47
  disconnectPeers(): void;
48
48
  unpublishLocal(signal?: AbortSignal): Promise<void>;
49
49
  private disconnectIfNeeded;
50
+ private publishLocalForTick;
50
51
  private publishLocal;
51
52
  private prepareUnpublishLocalCore;
52
53
  private preparePublishLocalCore;
@@ -66,13 +66,8 @@ class ZLinkAutoConnectReconciler {
66
66
  return this.meshMemberRidHexes.has(encodeRoutingIdHex(nodeRid));
67
67
  }
68
68
  async tick(signal) {
69
- try {
70
- await this.publishLocal(signal);
71
- }
72
- catch {
73
- await this.recordStoreFailure();
69
+ if (!(await this.publishLocalForTick(signal)))
74
70
  return;
75
- }
76
71
  if (!this.reconcilePeers) {
77
72
  await this.lane.run(() => {
78
73
  this.storeFailedValue = false;
@@ -86,9 +81,10 @@ class ZLinkAutoConnectReconciler {
86
81
  autoConnectType: this.local.autoConnectType,
87
82
  meshName: this.local.meshName
88
83
  }, signal);
84
+ signal?.throwIfAborted();
89
85
  }
90
86
  catch {
91
- await this.recordStoreFailure();
87
+ await this.recordStoreFailure(signal);
92
88
  return;
93
89
  }
94
90
  // A restarted Store can accept commands and return an empty live set
@@ -103,17 +99,8 @@ class ZLinkAutoConnectReconciler {
103
99
  await this.lane.run(() => {
104
100
  this.localPublished = false;
105
101
  });
106
- try {
107
- const republished = await this.publishLocal(signal);
108
- if (!republished) {
109
- await this.recordStoreFailure();
110
- return;
111
- }
112
- }
113
- catch {
114
- await this.recordStoreFailure();
102
+ if (!(await this.publishLocalForTick(signal)))
115
103
  return;
116
- }
117
104
  }
118
105
  if (await this.lane.run(() => this.storeFailedValue)) {
119
106
  await this.lane.run(() => {
@@ -267,21 +254,46 @@ class ZLinkAutoConnectReconciler {
267
254
  return;
268
255
  this.executor.disconnect(target);
269
256
  }
257
+ async publishLocalForTick(signal) {
258
+ let published;
259
+ try {
260
+ published = await this.publishLocal(signal);
261
+ signal?.throwIfAborted();
262
+ }
263
+ catch {
264
+ await this.recordStoreFailure(signal);
265
+ return false;
266
+ }
267
+ if (!published) {
268
+ await this.recordStoreFailure(signal);
269
+ return false;
270
+ }
271
+ return true;
272
+ }
270
273
  async publishLocal(signal) {
274
+ signal?.throwIfAborted();
271
275
  const prepared = await this.lane.run(() => this.preparePublishLocalCore());
272
- if (prepared === undefined)
273
- return await this.lane.run(() => this.localPublished);
276
+ if (prepared === undefined) {
277
+ return this.localRow === undefined || (await this.lane.run(() => this.localPublished));
278
+ }
274
279
  const claimed = await this.runtime.writePeer(prepared.row, internal_location_contracts_1.ZLinkLocationWriteIntent.NewClaim, signal);
275
280
  if (claimed.status === internal_location_contracts_1.ZLinkLocationWriteStatus.Stored) {
276
- return await this.lane.run(() => this.completePublishClaimCore(claimed.generation));
281
+ return await this.lane.run(() => {
282
+ signal?.throwIfAborted();
283
+ return this.completePublishClaimCore(claimed.generation);
284
+ });
277
285
  }
278
- const renewal = await this.lane.run(() => this.preparePublishRenewalCore(prepared.row, claimed.status));
286
+ const renewal = await this.lane.run(() => {
287
+ signal?.throwIfAborted();
288
+ return this.preparePublishRenewalCore(prepared.row, claimed.status);
289
+ });
279
290
  if (renewal !== undefined) {
280
291
  const renewed = await this.runtime.writePeer({
281
292
  ...prepared.row,
282
293
  generation: renewal
283
294
  }, internal_location_contracts_1.ZLinkLocationWriteIntent.Renew, signal);
284
295
  return await this.lane.run(() => {
296
+ signal?.throwIfAborted();
285
297
  this.localPublished = renewed.status === internal_location_contracts_1.ZLinkLocationWriteStatus.Stored;
286
298
  return this.localPublished;
287
299
  });
@@ -317,8 +329,8 @@ class ZLinkAutoConnectReconciler {
317
329
  ? this.localGeneration
318
330
  : undefined;
319
331
  }
320
- async recordStoreFailure() {
321
- const retryTargets = await this.lane.run(() => this.beginStoreFailureCore());
332
+ async recordStoreFailure(signal) {
333
+ const retryTargets = await this.lane.run(() => signal?.aborted === true ? undefined : this.beginStoreFailureCore());
322
334
  if (retryTargets === undefined)
323
335
  return;
324
336
  for (const [key, target] of retryTargets) {
@@ -71,9 +71,7 @@ export declare class ZLinkInMemoryLocationStore implements ZLinkDomainLocationSt
71
71
  private write;
72
72
  private transitionActorTransfer;
73
73
  private remove;
74
- private removeByOwner;
75
74
  private liveOwnerLease;
76
75
  private bump;
77
- private removeFanoutByOwner;
78
76
  private bumpScope;
79
77
  }
@@ -596,23 +596,7 @@ class ZLinkInMemoryLocationStore {
596
596
  lease.leaseExpiresAt.getTime() <= this.now().getTime()) {
597
597
  return 0n;
598
598
  }
599
- const ownerId = owner.ownerId;
600
- let removed = Number(await this.authority.removeAllByOwner(owner, signal));
601
- for (const [key, row] of [...this.meshNodes.rows]) {
602
- if (row.ownerId !== owner.ownerId)
603
- continue;
604
- this.meshNodes.rows.delete(key);
605
- this.releaseEntrySpotIdentity(row);
606
- this.bump(internal_location_contracts_1.ZLinkLocationKind.Peer, row.meshName);
607
- removed++;
608
- }
609
- removed += this.removeByOwner(this.peers, ownerId, (row) => row.ownerId, internal_location_contracts_1.ZLinkLocationKind.Peer, (row) => row.meshName);
610
- removed += this.removeByOwner(this.spots, ownerId, (row) => row.ownerId, internal_location_contracts_1.ZLinkLocationKind.Spot, (row) => row.meshName);
611
- removed += this.removeByOwner(this.actors, ownerId, (row) => row.ownerId, internal_location_contracts_1.ZLinkLocationKind.Actor, () => undefined);
612
- removed += this.removeByOwner(this.routes, ownerId, (row) => row.ownerId, internal_location_contracts_1.ZLinkLocationKind.Route, () => undefined);
613
- removed += this.removeByOwner(this.clientServers, ownerId, (row) => row.ownerId, internal_location_contracts_1.ZLinkLocationKind.ClientServer, (row) => row.channelName);
614
- removed += this.removeFanoutByOwner(owner);
615
- return BigInt(removed);
599
+ return this.authority.removeAllByOwner(owner, signal);
616
600
  }
617
601
  claimEntrySpotIdentity(descriptor, descriptorKey) {
618
602
  if (descriptor.entrySpotId === undefined)
@@ -710,17 +694,6 @@ class ZLinkInMemoryLocationStore {
710
694
  this.bump(kind, meshName);
711
695
  return stored(owner.leaseGeneration, this.now());
712
696
  }
713
- removeByOwner(table, ownerId, ownerOf, kind, meshOf) {
714
- let removed = 0;
715
- for (const [key, row] of [...table.rows.entries()]) {
716
- if (ownerOf(row) === ownerId) {
717
- table.rows.delete(key);
718
- this.bump(kind, meshOf(row));
719
- removed++;
720
- }
721
- }
722
- return removed;
723
- }
724
697
  liveOwnerLease(ownerId, now) {
725
698
  const lease = this.leases.get(ownerId);
726
699
  return lease !== undefined && lease.leaseExpiresAt.getTime() > now.getTime()
@@ -733,16 +706,6 @@ class ZLinkInMemoryLocationStore {
733
706
  this.bumpScope({ kind });
734
707
  }
735
708
  }
736
- removeFanoutByOwner(owner) {
737
- let removed = 0;
738
- for (const [key, row] of this.fanoutPublishers.rows) {
739
- if (row.ownerId !== owner.ownerId)
740
- continue;
741
- this.fanoutPublishers.rows.delete(key);
742
- removed++;
743
- }
744
- return removed;
745
- }
746
709
  bumpScope(scope) {
747
710
  const key = stampKey(scope);
748
711
  this.stamps.set(key, (this.stamps.get(key) ?? 0n) + 1n);
@@ -104,7 +104,6 @@ export declare class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationS
104
104
  removeAllByOwner(owner: ZLinkLocationOwnerToken, signal?: AbortSignal): Promise<bigint>;
105
105
  private removeAllByOwnerRequest;
106
106
  private removeOwnedAuthorities;
107
- private removeOwnerCleanupBatch;
108
107
  private updateDescriptor;
109
108
  private writeDescriptorWithReconciliation;
110
109
  private removeDescriptor;
@@ -37,7 +37,6 @@ const MAX_GENERATION = 0x7fffffffffffffffn;
37
37
  const MAX_U64 = stream_wire_1.UINT64_MAX;
38
38
  const CREATION_TERMINAL_RETENTION_MS = 5 * 60 * 1000;
39
39
  const MAX_DESCRIPTOR_WRITE_RETRIES = 3;
40
- const MAX_OWNER_CLEANUP_BATCH_ROWS = 2_047;
41
40
  /**
42
41
  * Maps framework domain records to the minimal provider SPI.
43
42
  *
@@ -924,11 +923,10 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
924
923
  async releaseEndedReservation(key, expectedStoreVersion, signal, request) {
925
924
  return this.observeStore('release', () => this.releaseEndedReservationRequest(key, expectedStoreVersion, signal, request));
926
925
  }
927
- async releaseEndedReservationRequest(key, expectedStoreVersion, signal, request) {
928
- return ((await this.tryReleaseEndedReservation(key, expectedStoreVersion, signal, request)) ===
929
- 'reclaimed');
926
+ async releaseEndedReservationRequest(key, expectedStoreVersion, signal, request, requiredOwner) {
927
+ return ((await this.tryReleaseEndedReservation(key, expectedStoreVersion, signal, request, undefined, requiredOwner)) === 'reclaimed');
930
928
  }
931
- async tryReleaseEndedReservation(key, expectedStoreVersion, signal, request, deadlineUnixMs) {
929
+ async tryReleaseEndedReservation(key, expectedStoreVersion, signal, request, deadlineUnixMs, requiredOwner) {
932
930
  for (;;) {
933
931
  throwIfOperationExpired(signal, deadlineUnixMs);
934
932
  const rowKey = authorityKey(key.value);
@@ -953,6 +951,11 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
953
951
  this.provider.read(capacityRowKey, signal)
954
952
  ]);
955
953
  const ownerLive = sameLiveOwner(lease, snapshot);
954
+ if (requiredOwner !== undefined &&
955
+ (!ownerLive ||
956
+ requiredOwner.ownerId !== snapshot.ownerId ||
957
+ requiredOwner.leaseGeneration !== snapshot.ownerLeaseGeneration))
958
+ return 'notReclaimable';
956
959
  let members = [];
957
960
  if (snapshot.allocation.state === 'active') {
958
961
  if (ownerLive)
@@ -1908,45 +1911,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
1908
1911
  const lease = await this.provider.read(leaseKey, signal);
1909
1912
  if (liveOwnerLeaseGeneration(lease) !== owner.leaseGeneration)
1910
1913
  return 0n;
1911
- let removed = await this.removeOwnedAuthorities(owner, signal);
1912
- const candidates = [];
1913
- for (const prefix of [
1914
- 'mesh-node\0',
1915
- 'client-server\0',
1916
- 'fanout-publisher\0',
1917
- `${PREFIX}spot:`,
1918
- `${PREFIX}actor:`,
1919
- `${PREFIX}route:`
1920
- ]) {
1921
- for (;;) {
1922
- const prefixCandidates = [];
1923
- let cursor;
1924
- let expired = false;
1925
- do {
1926
- const result = await this.provider.scan({ prefix, cursor, limit: 1_000 }, signal);
1927
- if (result.kind === 'expired') {
1928
- expired = true;
1929
- break;
1930
- }
1931
- for (const item of result.value.items) {
1932
- prefixCandidates.push({ key: item.key, scanVersion: item.value.version });
1933
- }
1934
- cursor = result.value.nextCursor;
1935
- } while (cursor !== undefined);
1936
- if (expired) {
1937
- // Snapshot scan expiry invalidates every page from this prefix.
1938
- // Restart from its first page instead of silently leaving rows
1939
- // behind after a partial scan.
1940
- continue;
1941
- }
1942
- candidates.push(...prefixCandidates);
1943
- break;
1944
- }
1945
- }
1946
- for (let offset = 0; offset < candidates.length; offset += MAX_OWNER_CLEANUP_BATCH_ROWS) {
1947
- removed += await this.removeOwnerCleanupBatch(owner, leaseKey, candidates.slice(offset, offset + MAX_OWNER_CLEANUP_BATCH_ROWS), signal);
1948
- }
1949
- return removed + (await super.removeAllByOwner(owner));
1914
+ return this.removeOwnedAuthorities(owner, signal);
1950
1915
  }
1951
1916
  async removeOwnedAuthorities(owner, signal) {
1952
1917
  const candidates = [];
@@ -2014,65 +1979,12 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
2014
1979
  }, signal);
2015
1980
  if (aborted.kind === 'aborted')
2016
1981
  removed += 1n;
2017
- }
2018
- return removed;
2019
- }
2020
- async removeOwnerCleanupBatch(owner, leaseKey, candidates, signal) {
2021
- if (candidates.length === 0)
2022
- return 0n;
2023
- const currentRows = await Promise.all(candidates.map((candidate) => this.provider.read(candidate.key, signal)));
2024
- const unchangedOwnedRows = [];
2025
- for (let index = 0; index < candidates.length; index += 1) {
2026
- const candidate = candidates[index];
2027
- const current = currentRows[index];
2028
- if (current.kind === 'missing' ||
2029
- current.value.version.value !== candidate.scanVersion.value) {
2030
- continue;
2031
- }
2032
- const record = decodeJson(current.value.bytes);
2033
- const descriptor = record.descriptor;
2034
- if (descriptor.ownerId !== owner.ownerId ||
2035
- descriptorOwnerLeaseGeneration(descriptor) !== owner.leaseGeneration) {
2036
- continue;
1982
+ else if (aborted.kind === 'stale') {
1983
+ if (await this.releaseEndedReservationRequest({ value: encodedAuthority }, current.value.version.value, signal, undefined, owner))
1984
+ removed += 1n;
2037
1985
  }
2038
- unchangedOwnedRows.push({
2039
- key: candidate.key,
2040
- scanVersion: current.value.version
2041
- });
2042
- }
2043
- if (unchangedOwnedRows.length === 0)
2044
- return 0n;
2045
- const currentLease = await this.provider.read(leaseKey, signal);
2046
- if (currentLease.kind === 'missing' ||
2047
- liveOwnerLeaseGeneration(currentLease) !== owner.leaseGeneration) {
2048
- return 0n;
2049
1986
  }
2050
- const result = await this.provider.write({
2051
- conditions: [
2052
- { kind: 'version', key: leaseKey, expected: currentLease.value.version },
2053
- ...unchangedOwnedRows.map((row) => ({
2054
- kind: 'version',
2055
- key: row.key,
2056
- expected: row.scanVersion
2057
- }))
2058
- ],
2059
- mutations: unchangedOwnedRows.map((row) => ({
2060
- kind: 'delete',
2061
- key: row.key
2062
- }))
2063
- }, signal);
2064
- if (result.kind === 'applied')
2065
- return BigInt(unchangedOwnedRows.length);
2066
- // A row may have changed while the page was being prepared. Split the
2067
- // bounded batch so unaffected rows can still be removed atomically, while
2068
- // the changed row is discarded by the next version re-read. A changed
2069
- // owner lease causes every recursive branch to stop at the fence above.
2070
- if (unchangedOwnedRows.length === 1)
2071
- return 0n;
2072
- const midpoint = Math.ceil(unchangedOwnedRows.length / 2);
2073
- const left = await this.removeOwnerCleanupBatch(owner, leaseKey, unchangedOwnedRows.slice(0, midpoint), signal);
2074
- const right = await this.removeOwnerCleanupBatch(owner, leaseKey, unchangedOwnedRows.slice(midpoint), signal);
2075
- return left + right;
1987
+ return removed;
2076
1988
  }
2077
1989
  async updateDescriptor(rowKey, descriptor, intent, revive, same, canRenew, signal) {
2078
1990
  const leaseKey = ownerKey(descriptor.ownerId);
@@ -3546,20 +3458,6 @@ function matchesRoute(value, filter) {
3546
3458
  function locationOwnerGeneration(value) {
3547
3459
  return value.leaseGeneration;
3548
3460
  }
3549
- function descriptorOwnerLeaseGeneration(value) {
3550
- if ('leaseGeneration' in value) {
3551
- return typeof value.leaseGeneration === 'bigint'
3552
- ? value.leaseGeneration
3553
- : BigInt(value.leaseGeneration);
3554
- }
3555
- if ('generation' in value) {
3556
- return typeof value.generation === 'bigint' ? value.generation : BigInt(value.generation);
3557
- }
3558
- return undefined;
3559
- }
3560
- // Location runtime §10: a write whose result was lost is confirmed by reading
3561
- // the same key. The stored row already is this write when it differs only in
3562
- // the time the Store stamped, as for every other descriptor kind.
3563
3461
  function sameMeshDescriptor(left, right) {
3564
3462
  return descriptorFingerprint(left, ['updatedAt']) === descriptorFingerprint(right, ['updatedAt']);
3565
3463
  }
@@ -1,6 +1,6 @@
1
1
  import { type ZLinkLocationOptionOverrides } from '../../contracts/Locations/Options';
2
2
  import type { RoutingId } from '../../contracts/Common';
3
- import { ZLinkLocationAutoConnectType, ZLinkLocationWriteIntent, ZLinkLocationWriteStatus, type ZLinkLocationRuntimeQuery, type ZLinkLocationOwnerToken, type ZLinkOwnerLeaseRenewed, type ZLinkActorLocation, type ZLinkActorLocationFilter, type ZLinkActorLocationKey, type ZLinkLocationKey, type ZLinkLocationPage, type ZLinkLocationRuntimeStatus, type ZLinkLocationServiceSummary, type ZLinkLocationServiceSummaryFilter, type ZLinkMeshNodeDescriptor, type ZLinkLocationTopologyEntry, type ZLinkLocationTopologyFilter, type ZLinkLocationWriteResult, type ZLinkPageRequest, type ZLinkPeerLocation, type ZLinkPeerLocationFilter, type ZLinkPeerLocationKey, type ZLinkRouteLocation, type ZLinkRouteLocationFilter, type ZLinkRouteLocationKey, type ZLinkSpotLocation, type ZLinkSpotLocationFilter, type ZLinkSpotLocationKey } from './internal-location-contracts';
3
+ import { ZLinkLocationAutoConnectType, ZLinkLocationKind, ZLinkLocationWriteIntent, ZLinkLocationWriteStatus, type ZLinkLocationRuntimeQuery, type ZLinkLocationOwnerToken, type ZLinkOwnerLeaseRenewed, type ZLinkActorLocation, type ZLinkActorLocationFilter, type ZLinkActorLocationKey, type ZLinkLocationKey, type ZLinkLocationPage, type ZLinkLocationRuntimeStatus, type ZLinkLocationServiceSummary, type ZLinkLocationServiceSummaryFilter, type ZLinkMeshNodeDescriptor, type ZLinkLocationTopologyEntry, type ZLinkLocationTopologyFilter, type ZLinkLocationWriteResult, type ZLinkPageRequest, type ZLinkPeerLocation, type ZLinkPeerLocationFilter, type ZLinkPeerLocationKey, type ZLinkRouteLocation, type ZLinkRouteLocationFilter, type ZLinkRouteLocationKey, type ZLinkSpotLocation, type ZLinkSpotLocationFilter, type ZLinkSpotLocationKey } from './internal-location-contracts';
4
4
  import type { ZLinkLocationObjectEntry, ZLinkLocationObjectFilter } from '../../contracts/Locations/RuntimeQuery';
5
5
  import type { ZLinkActorLocationStore, ZLinkAuthorityStore, ZLinkClientServerLocationStore, ZLinkFanoutLocationStore, ZLinkOwnerLeaseStore, ZLinkPeerLocationStore, ZLinkRouteLocationStore, ZLinkSpotLocationStore } from './internal-store-contracts';
6
6
  import type { ZLinkDomainLocationStore } from './domain-store-contract';
@@ -95,7 +95,7 @@ export declare class ZLinkLocationRuntime implements ZLinkLocationRuntimeQuery {
95
95
  get isStarted(): boolean;
96
96
  get nodeRid(): RoutingId | undefined;
97
97
  get currentOwnerToken(): ZLinkLocationOwnerToken | undefined;
98
- /** Location runtime §5: a startup Store request ends within the renew timeout. */
98
+ /** Location runtime §5: a descriptor publication ends within the renew timeout. */
99
99
  writeDescriptor<T>(action: (signal?: AbortSignal) => Promise<T>, signal?: AbortSignal): Promise<T>;
100
100
  closeOwnerLeaseAdmission(error: unknown): void;
101
101
  reclaimOwnerAuthorities(signal?: AbortSignal): Promise<void>;
@@ -149,7 +149,7 @@ export declare class ZLinkLocationRuntime implements ZLinkLocationRuntimeQuery {
149
149
  private scheduleHeartbeat;
150
150
  private guardWrite;
151
151
  private guardStatusWrite;
152
- private notifyIfStale;
152
+ notifyIfStale(result: ZLinkLocationWriteResult, kind: ZLinkLocationKind, key: string): void;
153
153
  private notifyIfStaleStatus;
154
154
  private recordFailure;
155
155
  private recordOwnerLeaseRenewFailure;
@@ -99,7 +99,7 @@ class ZLinkLocationRuntime {
99
99
  get currentOwnerToken() {
100
100
  return this.ownerToken;
101
101
  }
102
- /** Location runtime §5: a startup Store request ends within the renew timeout. */
102
+ /** Location runtime §5: a descriptor publication ends within the renew timeout. */
103
103
  async writeDescriptor(action, signal) {
104
104
  try {
105
105
  return await withTimeout(action, this.options.ownerLeaseRenewTimeoutMs, signal);
@@ -226,7 +226,7 @@ class ZLinkLocationRuntime {
226
226
  async cleanupOwner(signal) {
227
227
  const pending = this.heartbeatRenewal;
228
228
  try {
229
- await withTimeout(() => pending ?? Promise.resolve(), undefined, signal);
229
+ await (pending ?? Promise.resolve());
230
230
  }
231
231
  catch (error) {
232
232
  if (!(0, abort_1.isAbortError)(error))
@@ -240,18 +240,14 @@ class ZLinkLocationRuntime {
240
240
  return;
241
241
  }
242
242
  try {
243
- const owner = this.ownerToken ??
244
- this.lastOwnerToken ?? {
245
- ownerId: this.ownerId,
246
- leaseGeneration: 0n
247
- };
248
- await withTimeout(async (cleanupSignal) => {
249
- await this.stores.locationStore.removeAllByOwner(owner, cleanupSignal);
250
- const currentLease = await this.stores.ownerLeaseStore.readOwnerLease(this.ownerId, cleanupSignal);
251
- if (currentLease.kind === 'found') {
252
- await this.stores.ownerLeaseStore.releaseOwnerLease(currentLease.token, cleanupSignal);
253
- }
254
- }, undefined, signal);
243
+ const owner = this.ownerToken ?? this.lastOwnerToken;
244
+ signal?.throwIfAborted();
245
+ if (owner !== undefined) {
246
+ await this.stores.locationStore.removeAllByOwner(owner, signal);
247
+ signal?.throwIfAborted();
248
+ await this.stores.ownerLeaseStore.releaseOwnerLease(owner, signal);
249
+ signal?.throwIfAborted();
250
+ }
255
251
  this.ownerToken = undefined;
256
252
  this.lastOwnerToken = undefined;
257
253
  this.ownerCleanupComplete = true;
@@ -334,7 +330,7 @@ class ZLinkLocationRuntime {
334
330
  }
335
331
  try {
336
332
  if (!this.started) {
337
- // stop owns confirmation and release under the host shutdown signal.
333
+ this.lastOwnerToken = claim.token;
338
334
  return false;
339
335
  }
340
336
  this.lastOwnerToken = this.ownerToken;
@@ -500,7 +496,7 @@ class ZLinkLocationRuntime {
500
496
  // row was stored under.
501
497
  const normalizedEndpoint = (0, EndpointNotation_1.normalizeEndpoint)(peer.endpoint);
502
498
  const stamped = { ...peer, endpoint: normalizedEndpoint, ownerId: this.ownerId };
503
- const result = await this.guardWrite(() => this.stores.peerStore.updatePeer(stamped, intent, signal));
499
+ const result = await this.guardWrite(() => this.writeDescriptor((writeSignal) => this.stores.peerStore.updatePeer(stamped, intent, writeSignal), signal));
504
500
  const key = {
505
501
  autoConnectType: peer.autoConnectType,
506
502
  meshName: peer.meshName,
@@ -10,7 +10,7 @@ const CREATION_PACKET_NAME = 'ZLinkFrameworkCreationRequest';
10
10
  function encodeFrameworkCreationPayload(payload, registry) {
11
11
  const message = (0, payload_codec_1.encodeFrameworkPayloadMessage)(payload ?? null, registry);
12
12
  try {
13
- return (0, service_wire_m6a_codec_1.encodeApplicationPayload)({
13
+ return (0, service_wire_m6a_codec_1.encodeOwnedApplicationPayload)({
14
14
  packetName: CREATION_PACKET_NAME,
15
15
  contentType: (0, payload_codec_1.frameworkPayloadContentType)(message),
16
16
  payload: message.data()
@@ -26,7 +26,7 @@ function decodeFrameworkCreationPayload(payload, registry) {
26
26
  if (application.packetName !== CREATION_PACKET_NAME) {
27
27
  throw new RangeError('Creation payload has an unexpected packet name.');
28
28
  }
29
- // The M6A view decoder returns a Buffer over the retained input storage.
29
+ // Creation frames use owned storage and stay alive through synchronous decode.
30
30
  const message = runtime_message_1.ZLinkBufferMessage.fromOwned(application.payload);
31
31
  try {
32
32
  return (0, payload_codec_1.decodeFrameworkPayloadMessage)(message, registry, undefined, application.contentType);
@@ -859,6 +859,10 @@ export type RequestSpecificTail = {
859
859
  readonly terminalResult: "ok";
860
860
  readonly bindingGeneration: NonzeroU64;
861
861
  readonly authorityOwnerGeneration: NonzeroU64;
862
+ } | {
863
+ readonly originalOperationKind: "streamBind";
864
+ readonly terminalResult: "rejected";
865
+ readonly rejectionMessage: NonemptyText16;
862
866
  } | {
863
867
  readonly originalOperationKind: "userSpotCreate";
864
868
  readonly terminalResult: "ok";