@zlink-systems/framework 0.19.0 → 0.20.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 (70) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Configuration/Builders.d.ts +0 -2
  3. package/dist/contracts/Configuration/Configs.d.ts +1 -0
  4. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -2
  5. package/dist/contracts/Locations/Authority.d.ts +1 -7
  6. package/dist/runtime/actors/actor-authority-publication.js +25 -22
  7. package/dist/runtime/actors/actor-creation.js +30 -9
  8. package/dist/runtime/actors/actor-runtime-state.d.ts +3 -0
  9. package/dist/runtime/actors/index.d.ts +3 -0
  10. package/dist/runtime/actors/index.js +14 -3
  11. package/dist/runtime/admission.d.ts +2 -0
  12. package/dist/runtime/admission.js +11 -5
  13. package/dist/runtime/backend/contracts/index.d.ts +4 -1
  14. package/dist/runtime/backend/node/node-mesh-backend-adapter.d.ts +1 -0
  15. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +1 -1
  16. package/dist/runtime/backend/node/node-raw-binding-port.d.ts +2 -1
  17. package/dist/runtime/backend/node/node-raw-binding-port.js +12 -5
  18. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +1 -1
  19. package/dist/runtime/backend/node/node-socket-backend-adapter.js +6 -0
  20. package/dist/runtime/channels/channel-socket-options.js +7 -0
  21. package/dist/runtime/channels/channel-socket-registry.js +3 -0
  22. package/dist/runtime/foundation/service-stateful-runtime.d.ts +1 -1
  23. package/dist/runtime/foundation/service-stateful-runtime.js +1 -5
  24. package/dist/runtime/host/actor-placement-coordinator.d.ts +14 -5
  25. package/dist/runtime/host/actor-placement-coordinator.js +159 -47
  26. package/dist/runtime/host/index.d.ts +2 -1
  27. package/dist/runtime/host/index.js +77 -120
  28. package/dist/runtime/host/location-runtime-owner.js +4 -2
  29. package/dist/runtime/host/remote-actor-join-receiver.js +12 -3
  30. package/dist/runtime/locations/creation-operation-id.d.ts +4 -0
  31. package/dist/runtime/locations/creation-operation-id.js +12 -0
  32. package/dist/runtime/locations/in-memory-authority-store.js +8 -22
  33. package/dist/runtime/locations/location-store-repository.js +36 -59
  34. package/dist/runtime/locations/opaque-record-key.d.ts +5 -0
  35. package/dist/runtime/locations/opaque-record-key.js +16 -0
  36. package/dist/runtime/locations/runtime.d.ts +7 -0
  37. package/dist/runtime/locations/runtime.js +130 -42
  38. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +1672 -0
  39. package/dist/runtime/protocol/service_wire_codec.generated.js +9169 -0
  40. package/dist/runtime/spots/spot-node-runtime-manager.js +2 -2
  41. package/package.json +2 -2
  42. package/src/contracts/Configuration/Builders.ts +0 -2
  43. package/src/contracts/Configuration/Configs.ts +1 -0
  44. package/src/contracts/Configuration/RegistrationTypes.ts +1 -2
  45. package/src/contracts/Locations/Authority.ts +1 -8
  46. package/src/runtime/actors/actor-authority-publication.ts +25 -22
  47. package/src/runtime/actors/actor-creation.ts +45 -11
  48. package/src/runtime/actors/actor-runtime-state.ts +4 -0
  49. package/src/runtime/actors/index.ts +32 -4
  50. package/src/runtime/admission.ts +8 -5
  51. package/src/runtime/backend/contracts/index.ts +4 -1
  52. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +2 -1
  53. package/src/runtime/backend/node/node-raw-binding-port.ts +16 -5
  54. package/src/runtime/backend/node/node-raw-mesh-backend.ts +1 -1
  55. package/src/runtime/backend/node/node-socket-backend-adapter.ts +7 -0
  56. package/src/runtime/channels/channel-socket-options.ts +9 -0
  57. package/src/runtime/channels/channel-socket-registry.ts +4 -0
  58. package/src/runtime/foundation/service-stateful-runtime.ts +2 -6
  59. package/src/runtime/host/actor-placement-coordinator.ts +216 -77
  60. package/src/runtime/host/index.ts +95 -135
  61. package/src/runtime/host/location-runtime-owner.ts +4 -2
  62. package/src/runtime/host/remote-actor-join-receiver.ts +15 -3
  63. package/src/runtime/locations/creation-operation-id.ts +11 -0
  64. package/src/runtime/locations/in-memory-authority-store.ts +7 -29
  65. package/src/runtime/locations/location-store-repository.ts +71 -69
  66. package/src/runtime/locations/opaque-record-key.ts +26 -0
  67. package/src/runtime/locations/runtime.ts +154 -60
  68. package/src/runtime/protocol/service_wire_codec.generated.ts +8302 -0
  69. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
  70. package/src/runtime/spots/spot-node-runtime-manager.ts +2 -2
@@ -77,8 +77,6 @@ export interface ZLinkMeshChannelServerBuilder {
77
77
  export interface ZLinkMeshNodeSocketConfig {
78
78
  sendHighWaterMark: number;
79
79
  receiveHighWaterMark: number;
80
- mailboxMessageBudget: number;
81
- mailboxByteBudget: number;
82
80
  receiveTimeoutMs?: number;
83
81
  sendTimeoutMs?: number;
84
82
  }
@@ -6,6 +6,7 @@ export interface ZLinkSocketConfig {
6
6
  weight?: number;
7
7
  sendHighWaterMark?: number;
8
8
  receiveHighWaterMark?: number;
9
+ receiveTimeoutMs?: number;
9
10
  sendTimeoutMs?: number;
10
11
  }
11
12
  export interface ZLinkRouteConfig {
@@ -165,8 +165,6 @@ export interface ZLinkClientCapabilityOptions {
165
165
  readonly manualConnections?: readonly string[];
166
166
  readonly sendHighWaterMark?: number;
167
167
  readonly receiveHighWaterMark?: number;
168
- readonly mailboxMessageBudget?: number;
169
- readonly mailboxByteBudget?: number;
170
168
  readonly sendTimeoutMs?: number;
171
169
  readonly maxMessageSize?: number;
172
170
  }
@@ -359,6 +357,7 @@ export interface ZLinkSpotRouterCapabilityOptions {
359
357
  readonly routingId?: string;
360
358
  readonly sendHighWaterMark?: number;
361
359
  readonly receiveHighWaterMark?: number;
360
+ readonly receiveTimeoutMs?: number;
362
361
  readonly sendTimeoutMs?: number;
363
362
  }
364
363
  export interface ZLinkSpotRouterPeerConnectionOptions {
@@ -128,11 +128,9 @@ export interface ZLinkCreationOperationIdentity {
128
128
  readonly sourceNodeGeneration: bigint;
129
129
  readonly operationId: ZLinkCreationOperationId;
130
130
  }
131
- export type ZLinkCreationTerminalState = 'created' | 'rejected' | 'failed';
132
131
  export interface ZLinkCreationTerminalPublication {
133
132
  readonly operation: ZLinkCreationOperationIdentity;
134
133
  readonly terminalEnvelope: Uint8Array;
135
- readonly terminalEnvelopeSha256: Uint8Array;
136
134
  /**
137
135
  * The original operation deadline. Providers retain the terminal for five
138
136
  * minutes after this absolute instant.
@@ -140,12 +138,8 @@ export interface ZLinkCreationTerminalPublication {
140
138
  readonly operationDeadline: Date;
141
139
  }
142
140
  export interface ZLinkCreationTerminalRecord {
143
- readonly state: ZLinkCreationTerminalState;
144
141
  readonly operation: ZLinkCreationOperationIdentity;
145
- readonly reservationId: string;
146
- readonly objectKind: ZLinkPlacementObjectKind;
147
142
  readonly terminalEnvelope: Uint8Array;
148
- readonly terminalEnvelopeSha256: Uint8Array;
149
143
  readonly expiresAt: Date;
150
144
  readonly storeNow: Date;
151
145
  }
@@ -154,7 +148,7 @@ export type ZLinkCreationTerminalReadResult = {
154
148
  readonly storeNow: Date;
155
149
  } | {
156
150
  readonly kind: 'found';
157
- readonly record: ZLinkCreationTerminalRecord;
151
+ readonly terminalEnvelope: Uint8Array;
158
152
  };
159
153
  export interface ZLinkObjectReserveRequest {
160
154
  readonly key: ZLinkObjectCreationKey;
@@ -8,8 +8,10 @@ exports.rewriteActorAuthorityRoute = rewriteActorAuthorityRoute;
8
8
  exports.rewriteActorAuthorityOwner = rewriteActorAuthorityOwner;
9
9
  exports.isActorAuthorityPayload = isActorAuthorityPayload;
10
10
  const node_crypto_1 = require("node:crypto");
11
+ const creation_operation_id_1 = require("../locations/creation-operation-id");
11
12
  const actor_authority_payload_codec_1 = require("./actor-authority-payload-codec");
12
13
  const service_relocation_runtime_1 = require("../foundation/service-relocation-runtime");
14
+ const service_wire_codec_generated_1 = require("../protocol/service_wire_codec.generated");
13
15
  const CREATION_OPERATION_TIMEOUT_MS = 30_000;
14
16
  /**
15
17
  * Publishes the authority record that owns durable Actor lifecycle state.
@@ -45,12 +47,20 @@ async function publishInitialActorAuthority(store, identity, signal) {
45
47
  throw new Error(`Actor '${identity.actor.actorId}' authority reservation failed with '${reserved.kind}'.`);
46
48
  }
47
49
  try {
48
- const terminalEnvelope = Buffer.from(JSON.stringify({
49
- status: 'created',
50
- actorId: identity.actor.actorId,
51
- actorGeneration: identity.actor.objectGeneration.toString()
52
- }), 'utf8');
53
- const operationBytes = (0, node_crypto_1.randomBytes)(16);
50
+ const terminalEnvelope = Buffer.from((0, service_wire_codec_generated_1.encodeCreationOperationTerminalV1)({
51
+ terminalResult: 'ok',
52
+ failureCode: 'none',
53
+ hasCreation: 'true',
54
+ creation: {
55
+ createResult: 'created',
56
+ actor: {
57
+ actorId: identity.actor.actorId,
58
+ objectGeneration: identity.actor.objectGeneration
59
+ }
60
+ },
61
+ hasApplicationPayload: 'false'
62
+ }, { runtimePredicates: {} }));
63
+ const operationId = (0, creation_operation_id_1.randomOperationId)();
54
64
  const completed = await store.completeCreation({
55
65
  key: { kind: 'actor', globalId: identity.actor.actorId },
56
66
  reservationId: reserved.reservationId,
@@ -63,13 +73,9 @@ async function publishInitialActorAuthority(store, identity, signal) {
63
73
  operation: {
64
74
  sourceNodeRid: identity.actor.nodeRid,
65
75
  sourceNodeGeneration: identity.ownerNodeGeneration,
66
- operationId: {
67
- high: operationBytes.readBigUInt64BE(0),
68
- low: operationBytes.readBigUInt64BE(8)
69
- }
76
+ operationId
70
77
  },
71
78
  terminalEnvelope,
72
- terminalEnvelopeSha256: (0, node_crypto_1.createHash)('sha256').update(terminalEnvelope).digest(),
73
79
  operationDeadline: new Date(Date.now() + CREATION_OPERATION_TIMEOUT_MS)
74
80
  }
75
81
  }
@@ -81,17 +87,14 @@ async function publishInitialActorAuthority(store, identity, signal) {
81
87
  return completed.ready;
82
88
  }
83
89
  catch (error) {
84
- try {
85
- await store.abort({
86
- key: { kind: 'actor', globalId: identity.actor.actorId },
87
- reservationId: reserved.reservationId,
88
- expectedStoreVersion: reserved.creating.storeVersion.value,
89
- target
90
- }, signal);
91
- }
92
- catch {
93
- // A completed creation cannot be aborted; the validated authority remains.
94
- }
90
+ const aborted = await store.abort({
91
+ key: { kind: 'actor', globalId: identity.actor.actorId },
92
+ reservationId: reserved.reservationId,
93
+ expectedStoreVersion: reserved.creating.storeVersion.value,
94
+ target
95
+ }, signal);
96
+ if (aborted.kind === 'stale')
97
+ throw error;
95
98
  throw error;
96
99
  }
97
100
  }
@@ -25,7 +25,7 @@ class ZLinkActorCreationCoordinator {
25
25
  state.clearAfterDestroy();
26
26
  }, () => this.createActorAfterClaim(actorId, actorType, state, createRequest, true, signal));
27
27
  if (activation.activated !== undefined) {
28
- if (activation.activated.status === 'rejected') {
28
+ if (activation.activated.status !== 'created') {
29
29
  await lifecycle.releaseActor(actorType, actorId);
30
30
  return activation.activated;
31
31
  }
@@ -61,16 +61,24 @@ class ZLinkActorCreationCoordinator {
61
61
  const factory = await this.createFactory(actorType);
62
62
  const context = state.ensureContext(() => new actor_context_1.DefaultZLinkActorContext(state, this.options.joinCoordinator, this.options.boundSessionFactory, this.options.messageSerializers, this.options.actorMeshNameProvider));
63
63
  const nativeActorNode = this.options.nativeActorNode ?? this.options.nativeActorNodeProvider?.();
64
+ let actor;
65
+ try {
66
+ actor = await factory.create(context, signal);
67
+ }
68
+ catch (error) {
69
+ await this.discardStagingActor(state, nativeActorNode);
70
+ return { status: 'failed', error };
71
+ }
72
+ let meshName;
73
+ let nodeRid;
64
74
  try {
65
- const actor = await factory.create(context, signal);
66
75
  if (actor.context !== context || actor.context.actorId !== context.actorId) {
67
76
  throw new configuration_1.ZLinkConfigurationException(`Actor factory '${actorType}' must return an Actor bound to the exact supplied context.`);
68
77
  }
69
- const meshName = state.meshName ?? '';
78
+ meshName = state.meshName ?? '';
70
79
  if (meshName.length === 0 && state.nativeActorRef === undefined) {
71
80
  throw new configuration_1.ZLinkConfigurationException(`Actor '${actorId}' has no RouteMesh identity.`);
72
81
  }
73
- let nodeRid;
74
82
  if (nativeActorNode !== undefined) {
75
83
  const actorRef = state.ensureNativeActorRef(nativeActorNode, createRequest.nativeRequest);
76
84
  nodeRid = (0, actor_runtime_state_1.toFrameworkRoutingId)(actorRef.nodeRid);
@@ -78,13 +86,26 @@ class ZLinkActorCreationCoordinator {
78
86
  else {
79
87
  nodeRid = this.options.actorCreatedNodeRidProvider?.();
80
88
  }
81
- const response = nodeRid === undefined
89
+ }
90
+ catch (error) {
91
+ await this.discardStagingActor(state, nativeActorNode);
92
+ throw error;
93
+ }
94
+ let response;
95
+ try {
96
+ response = nodeRid === undefined
82
97
  ? { accepted: true }
83
98
  : await this.options.actorCreatedNotifier?.(nodeRid, actor, createRequest.callbackRequest, signal) ?? { accepted: true };
84
- if (!response.accepted) {
85
- await this.discardStagingActor(state, nativeActorNode);
86
- return { status: 'rejected', reply: response.reply };
87
- }
99
+ }
100
+ catch (error) {
101
+ await this.discardStagingActor(state, nativeActorNode);
102
+ return { status: 'failed', error };
103
+ }
104
+ if (!response.accepted) {
105
+ await this.discardStagingActor(state, nativeActorNode);
106
+ return { status: 'rejected', reply: response.reply };
107
+ }
108
+ try {
88
109
  state.bindActor(actor, context);
89
110
  if (nativeActorNode !== undefined) {
90
111
  const actorRef = state.nativeActorRef;
@@ -72,6 +72,9 @@ export type ZLinkActorCreationAttemptResult = {
72
72
  } | {
73
73
  readonly status: 'rejected';
74
74
  readonly reply?: unknown;
75
+ } | {
76
+ readonly status: 'failed';
77
+ readonly error: unknown;
75
78
  };
76
79
  export declare class ZLinkActorRuntimeState {
77
80
  readonly actorId: string;
@@ -76,4 +76,7 @@ export type ZLinkActorLocalCreateResult = {
76
76
  } | {
77
77
  readonly status: 'rejected';
78
78
  readonly reply?: unknown;
79
+ } | {
80
+ readonly status: 'failed';
81
+ readonly error: unknown;
79
82
  };
@@ -235,6 +235,9 @@ class DefaultZLinkActorManager {
235
235
  ? { status: 'rejected' }
236
236
  : { status: 'rejected', reply: result.reply };
237
237
  }
238
+ if (result.status === 'failed') {
239
+ throw actorApplicationFailure(actorId, result.error);
240
+ }
238
241
  return result.reply === undefined
239
242
  ? { status: result.status, actor: result.actorRef }
240
243
  : { status: result.status, actor: result.actorRef, reply: result.reply };
@@ -453,7 +456,7 @@ class DefaultZLinkActorManager {
453
456
  const operation = state.getOrStartCreation(actorType, failIfExists, () => this.creation.createActor(actorId, actorType, state, createRequest, claimLocation, signal));
454
457
  if (operation.created) {
455
458
  void operation.task.then((result) => {
456
- if (result.status === 'rejected') {
459
+ if (result.status !== 'created') {
457
460
  this.discardFailedState(actorId, state, operation.task);
458
461
  }
459
462
  }, () => this.discardFailedState(actorId, state, operation.task));
@@ -470,7 +473,9 @@ class DefaultZLinkActorManager {
470
473
  };
471
474
  }
472
475
  if (operation.created) {
473
- return { status: 'rejected', reply: result.reply };
476
+ return result.status === 'failed'
477
+ ? { status: 'failed', error: result.error }
478
+ : { status: 'rejected', reply: result.reply };
474
479
  }
475
480
  }
476
481
  catch (error) {
@@ -610,10 +615,16 @@ class ZLinkActorCreateCallRuntime {
610
615
  class ZLinkActorGetOrCreateCallRuntime extends ZLinkActorCreateCallRuntime {
611
616
  }
612
617
  function requireCreatedActor(result, actorId) {
613
- if (result.status !== 'rejected')
618
+ if (result.status === 'existing' || result.status === 'created')
614
619
  return result.actor;
620
+ if (result.status === 'failed') {
621
+ throw actorApplicationFailure(actorId, result.error);
622
+ }
615
623
  throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.ActorCreateRejected, `Actor '${actorId}' create request was rejected.`);
616
624
  }
625
+ function actorApplicationFailure(actorId, error) {
626
+ return (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.ActorCreateFailed, `Actor '${actorId}' creation failed: ${error instanceof Error ? error.message : String(error)}`, false, error);
627
+ }
617
628
  async function waitForCreationRetry(signal) {
618
629
  (0, abort_1.throwIfAborted)(signal);
619
630
  await new Promise((resolve, reject) => {
@@ -1,6 +1,8 @@
1
1
  import { ZLinkFrameworkInternalErrorKind } from './framework-errors-internal';
2
2
  export declare class ZLinkRuntimeAdmissionGate {
3
+ private readonly ownerAdmissionOpen;
3
4
  private readonly meshes;
5
+ constructor(ownerAdmissionOpen?: () => boolean);
4
6
  get acceptsNewWork(): boolean;
5
7
  register(meshName: string): void;
6
8
  accepts(meshName: string): boolean;
@@ -3,8 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ZLinkRuntimeAdmissionGate = void 0;
4
4
  const framework_errors_internal_1 = require("./framework-errors-internal");
5
5
  class ZLinkRuntimeAdmissionGate {
6
+ ownerAdmissionOpen;
6
7
  meshes = new Map();
8
+ constructor(ownerAdmissionOpen = () => true) {
9
+ this.ownerAdmissionOpen = ownerAdmissionOpen;
10
+ }
7
11
  get acceptsNewWork() {
12
+ if (!this.ownerAdmissionOpen())
13
+ return false;
8
14
  for (const state of this.meshes.values()) {
9
15
  if (state.sealed)
10
16
  return false;
@@ -24,7 +30,7 @@ class ZLinkRuntimeAdmissionGate {
24
30
  }
25
31
  }
26
32
  accepts(meshName) {
27
- return !this.requireState(meshName).sealed;
33
+ return this.ownerAdmissionOpen() && !this.requireState(meshName).sealed;
28
34
  }
29
35
  pending(meshName) {
30
36
  return this.requireState(meshName).active;
@@ -42,7 +48,7 @@ class ZLinkRuntimeAdmissionGate {
42
48
  }
43
49
  claim(meshName, operation) {
44
50
  const state = this.requireState(meshName);
45
- if (!state.sealed) {
51
+ if (this.ownerAdmissionOpen() && !state.sealed) {
46
52
  state.active += 1;
47
53
  let closed = false;
48
54
  return {
@@ -59,7 +65,7 @@ class ZLinkRuntimeAdmissionGate {
59
65
  }
60
66
  };
61
67
  }
62
- throw (0, framework_errors_internal_1.createInternalFrameworkException)(state.sealedReason, `${operation} was rejected because the framework is draining.`);
68
+ throw (0, framework_errors_internal_1.createInternalFrameworkException)(state.sealedReason, `${operation} was rejected because framework admission is closed.`);
63
69
  }
64
70
  async run(meshName, operation, work) {
65
71
  const claim = this.claim(meshName, operation);
@@ -106,7 +112,7 @@ class ZLinkRuntimeAdmissionGate {
106
112
  }
107
113
  throw (0, framework_errors_internal_1.createInternalFrameworkException)(meshName === undefined
108
114
  ? this.firstSealedReason()
109
- : this.requireState(meshName).sealedReason, `${operation} was rejected because the framework is draining.`);
115
+ : this.requireState(meshName).sealedReason, `${operation} was rejected because framework admission is closed.`);
110
116
  }
111
117
  requireActorCreate(actorId, meshName) {
112
118
  if (meshName === undefined) {
@@ -121,7 +127,7 @@ class ZLinkRuntimeAdmissionGate {
121
127
  : this.requireState(meshName).sealedReason;
122
128
  throw (0, framework_errors_internal_1.createInternalFrameworkException)(reason === framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RuntimeShutdown
123
129
  ? framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RuntimeShutdown
124
- : framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.ActorCreateRejected, `Actor '${actorId}' create request was rejected because the framework is draining.`);
130
+ : framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.ActorCreateRejected, `Actor '${actorId}' create request was rejected because framework admission is closed.`);
125
131
  }
126
132
  requireState(meshName) {
127
133
  const state = this.meshes.get(meshName);
@@ -83,7 +83,7 @@ export interface ZLinkBackendMeshNode {
83
83
  registerUserSpotOperationHandler(handler: ServiceUserSpotOperationHandler): void;
84
84
  requestUserSpotCreate(targetNodeRid: string, request: Omit<ServiceUserSpotCreateRecord, 'kind' | 'correlation' | 'operation'>, timeoutMs: number): Promise<ServiceUserSpotOperationResult>;
85
85
  requestUserSpotClose(targetNodeRid: string, request: Omit<ServiceUserSpotCloseRecord, 'kind' | 'correlation' | 'operation'>, timeoutMs: number): Promise<ServiceUserSpotOperationResult>;
86
- requestActorCreate(targetNodeRid: string, request: Omit<ServiceActorCreateRecord, 'kind' | 'correlation' | 'operation'>, timeoutMs: number): Promise<ServiceUserSpotOperationResult>;
86
+ requestActorCreate(targetNodeRid: string, request: Omit<ServiceActorCreateRecord, 'kind' | 'correlation'>, timeoutMs: number): Promise<ServiceUserSpotOperationResult>;
87
87
  connectPeer(options: {
88
88
  readonly endpoint: string;
89
89
  readonly expectedRid?: unknown;
@@ -311,6 +311,7 @@ export interface ZLinkBackendDealerSocket extends ZLinkBackendConnectableSocket
311
311
  peerWeight: number;
312
312
  sendHighWaterMark: number;
313
313
  receiveHighWaterMark: number;
314
+ receiveTimeoutMs: number;
314
315
  sendTimeoutMs: number;
315
316
  maxMessageSize: number;
316
317
  send(message: Message | readonly Message[]): Promise<void>;
@@ -337,6 +338,7 @@ export interface ZLinkBackendRouterSocket extends ZLinkBackendConnectableSocket
337
338
  peerWeight: number;
338
339
  sendHighWaterMark: number;
339
340
  receiveHighWaterMark: number;
341
+ receiveTimeoutMs: number;
340
342
  sendTimeoutMs: number;
341
343
  maxMessageSize: number;
342
344
  setRoutingId(routingId: RoutingId): void;
@@ -466,6 +468,7 @@ export interface ZLinkMeshBackendAdapter {
466
468
  createMeshNode(context: ZLinkBackendContext, options: {
467
469
  readonly meshName: string;
468
470
  readonly routingId?: RoutingId;
471
+ readonly receiveTimeoutMs?: number;
469
472
  readonly trustProfile?: string;
470
473
  readonly applicationJobQueue: import('../../application-jobs/contracts').ApplicationJobQueuePort;
471
474
  readonly applicationJobReceiveFlowFailureSink?: (error: unknown) => void;
@@ -3,6 +3,7 @@ export declare class ZLinkNodeMeshBackendAdapter implements ZLinkMeshBackendAdap
3
3
  createMeshNode(context: ZLinkBackendContext, options: {
4
4
  readonly meshName: string;
5
5
  readonly routingId?: string;
6
+ readonly receiveTimeoutMs?: number;
6
7
  readonly trustProfile?: string;
7
8
  readonly applicationJobQueue: import('../../application-jobs/contracts').ApplicationJobQueuePort;
8
9
  readonly applicationJobReceiveFlowFailureSink?: (error: unknown) => void;
@@ -12,7 +12,7 @@ class ZLinkNodeMeshBackendAdapter {
12
12
  if (!isBindingContext(bindingContext)) {
13
13
  throw new TypeError('Node MeshNode creation requires the Node binding Context owned by the host.');
14
14
  }
15
- return new node_raw_mesh_backend_1.ZLinkNodeRawMeshBackend(options.meshName, options.routingId, new node_raw_binding_port_1.ZLinkNodeRawBindingPort(bindingContext), options.applicationJobQueue, options.applicationJobReceiveFlowFailureSink, options.peerAdmissionSealed);
15
+ return new node_raw_mesh_backend_1.ZLinkNodeRawMeshBackend(options.meshName, options.routingId, new node_raw_binding_port_1.ZLinkNodeRawBindingPort(bindingContext, options.receiveTimeoutMs), options.applicationJobQueue, options.applicationJobReceiveFlowFailureSink, options.peerAdmissionSealed);
16
16
  }
17
17
  }
18
18
  exports.ZLinkNodeMeshBackendAdapter = ZLinkNodeMeshBackendAdapter;
@@ -3,6 +3,7 @@ import type { ZLinkRawBindingPort, ZLinkRawHostPort } from '../raw-binding-port'
3
3
  export type { ZLinkRawBindingPort, ZLinkRawDealerPort, ZLinkRawHostPort, ZLinkRawMonitorPort, ZLinkRawMonitorRecord, ZLinkRawReceivedRecord, ZLinkRawRouterPort, ZLinkRawSocketPort } from '../raw-binding-port';
4
4
  export declare class ZLinkNodeRawBindingPort implements ZLinkRawBindingPort {
5
5
  private readonly sharedContext?;
6
- constructor(sharedContext?: Context | undefined);
6
+ private readonly routerReceiveTimeoutMs?;
7
+ constructor(sharedContext?: Context | undefined, routerReceiveTimeoutMs?: number | undefined);
7
8
  createHost(): ZLinkRawHostPort;
8
9
  }
@@ -7,26 +7,30 @@ const node_socket_backend_adapter_1 = require("./node-socket-backend-adapter");
7
7
  const node_event_loop_poller_1 = require("./node-event-loop-poller");
8
8
  class ZLinkNodeRawBindingPort {
9
9
  sharedContext;
10
- constructor(sharedContext) {
10
+ routerReceiveTimeoutMs;
11
+ constructor(sharedContext, routerReceiveTimeoutMs) {
11
12
  this.sharedContext = sharedContext;
13
+ this.routerReceiveTimeoutMs = routerReceiveTimeoutMs;
12
14
  }
13
15
  createHost() {
14
- return new NodeRawHostPort(this.sharedContext ?? (0, zlink_1.createContext)(), this.sharedContext === undefined);
16
+ return new NodeRawHostPort(this.sharedContext ?? (0, zlink_1.createContext)(), this.sharedContext === undefined, this.routerReceiveTimeoutMs);
15
17
  }
16
18
  }
17
19
  exports.ZLinkNodeRawBindingPort = ZLinkNodeRawBindingPort;
18
20
  class NodeRawHostPort {
19
21
  context;
20
22
  ownsContext;
23
+ routerReceiveTimeoutMs;
21
24
  resources = [];
22
25
  state = 'open';
23
- constructor(context, ownsContext) {
26
+ constructor(context, ownsContext, routerReceiveTimeoutMs) {
24
27
  this.context = context;
25
28
  this.ownsContext = ownsContext;
29
+ this.routerReceiveTimeoutMs = routerReceiveTimeoutMs;
26
30
  }
27
31
  createRouter() {
28
32
  this.requireOpen();
29
- return this.own(new NodeRawRouterPort((0, zlink_1.createRouterSocket)(this.context)));
33
+ return this.own(new NodeRawRouterPort((0, zlink_1.createRouterSocket)(this.context), this.routerReceiveTimeoutMs));
30
34
  }
31
35
  createDealer() {
32
36
  this.requireOpen();
@@ -178,11 +182,14 @@ class NodeRawRouterPort extends NodeRawSocketPort {
178
182
  this.requireOpen();
179
183
  this.socket.disconnectRid(bindingRoutingId(routingId));
180
184
  }
181
- constructor(socket) {
185
+ constructor(socket, receiveTimeoutMs) {
182
186
  super(socket);
183
187
  socket.options.handover = true;
184
188
  socket.options.mandatory = true;
185
189
  socket.options.probe = true;
190
+ if (receiveTimeoutMs !== undefined) {
191
+ socket.options.recvTimeout = receiveTimeoutMs;
192
+ }
186
193
  }
187
194
  localEndpoint() {
188
195
  this.requireOpen();
@@ -178,7 +178,7 @@ export declare class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
178
178
  registerUserSpotOperationHandler(handler: ServiceUserSpotOperationHandler): void;
179
179
  requestUserSpotCreate(targetNodeRid: string, request: Omit<ServiceUserSpotCreateRecord, 'kind' | 'correlation' | 'operation'>, timeoutMs: number): Promise<ServiceUserSpotOperationResult>;
180
180
  requestUserSpotClose(targetNodeRid: string, request: Omit<ServiceUserSpotCloseRecord, 'kind' | 'correlation' | 'operation'>, timeoutMs: number): Promise<ServiceUserSpotOperationResult>;
181
- requestActorCreate(targetNodeRid: string, request: Omit<ServiceActorCreateRecord, 'kind' | 'correlation' | 'operation'>, timeoutMs: number): Promise<ServiceUserSpotOperationResult>;
181
+ requestActorCreate(targetNodeRid: string, request: Omit<ServiceActorCreateRecord, 'kind' | 'correlation'>, timeoutMs: number): Promise<ServiceUserSpotOperationResult>;
182
182
  recoverInstanceActivation(envelope: ServiceInstanceActivationRecoveryEnvelope, route: ServiceInstanceRouteFence, expectedCurrentRoute?: ServiceInstanceRouteFence | null): Promise<boolean>;
183
183
  recoverPendingInstanceActivation(envelope: ServiceInstanceActivationRecoveryEnvelope, pending: ServicePendingInstanceActivation, expectedCurrentRoute?: ServiceInstanceRouteFence | null): Promise<boolean>;
184
184
  completeRecoveredInstanceActivation(target: ServiceInstanceActivationTarget, route: ServiceInstanceRouteFence, expectedCurrentRoute?: ServiceInstanceRouteFence | null): Promise<ServiceInstanceRouteFence | undefined>;
@@ -92,6 +92,12 @@ function wrapSocket(nativeInstance, pollCompletion) {
92
92
  set receiveHighWaterMark(value) {
93
93
  requireSocketOptions(socket).recvHwm = value;
94
94
  },
95
+ get receiveTimeoutMs() {
96
+ return socket.options?.recvTimeout ?? 0;
97
+ },
98
+ set receiveTimeoutMs(value) {
99
+ requireSocketOptions(socket).recvTimeout = value;
100
+ },
95
101
  get sendTimeoutMs() {
96
102
  return socket.options?.sendTimeout ?? 0;
97
103
  },
@@ -33,6 +33,13 @@ class ZLinkLiveSocketConfig {
33
33
  validateHighWaterMark(value, 'receiveHighWaterMark');
34
34
  this.socket.receiveHighWaterMark = value;
35
35
  }
36
+ get receiveTimeoutMs() {
37
+ return this.socket.receiveTimeoutMs;
38
+ }
39
+ set receiveTimeoutMs(value) {
40
+ (0, SendTimeoutValidation_1.requireValidSendTimeoutMs)('receiveTimeoutMs', value);
41
+ this.socket.receiveTimeoutMs = value;
42
+ }
36
43
  get sendTimeoutMs() {
37
44
  return this.socket.sendTimeoutMs;
38
45
  }
@@ -1446,6 +1446,9 @@ function applySocketConfig(socket, config) {
1446
1446
  if (config.receiveHighWaterMark !== undefined) {
1447
1447
  socket.receiveHighWaterMark = config.receiveHighWaterMark;
1448
1448
  }
1449
+ if (config.receiveTimeoutMs !== undefined) {
1450
+ socket.receiveTimeoutMs = config.receiveTimeoutMs;
1451
+ }
1449
1452
  if (config.sendTimeoutMs !== undefined) {
1450
1453
  socket.sendTimeoutMs = config.sendTimeoutMs;
1451
1454
  }
@@ -253,7 +253,7 @@ export declare class ServiceStatefulRuntime {
253
253
  registerUserSpotOperationHandler(handler: ServiceUserSpotOperationHandler): void;
254
254
  requestUserSpotCreate(targetNodeRid: string, request: Omit<ServiceUserSpotCreateRecord, 'kind' | 'correlation' | 'operation'>, timeoutMs: number): Promise<ServiceUserSpotOperationResult>;
255
255
  requestUserSpotClose(targetNodeRid: string, request: Omit<ServiceUserSpotCloseRecord, 'kind' | 'correlation' | 'operation'>, timeoutMs: number): Promise<ServiceUserSpotOperationResult>;
256
- requestActorCreate(targetNodeRid: string, request: Omit<ServiceActorCreateRecord, 'kind' | 'correlation' | 'operation'>, timeoutMs: number): Promise<ServiceUserSpotOperationResult>;
256
+ requestActorCreate(targetNodeRid: string, request: Omit<ServiceActorCreateRecord, 'kind' | 'correlation'>, timeoutMs: number): Promise<ServiceUserSpotOperationResult>;
257
257
  recoverInstanceActivation(envelope: ServiceInstanceActivationRecoveryEnvelope, route: ServiceInstanceRouteFence, expectedCurrentRoute?: ServiceInstanceRouteFence | null): Promise<boolean>;
258
258
  private finishRecoveredInstanceActivation;
259
259
  recoverPendingInstanceActivation(envelope: ServiceInstanceActivationRecoveryEnvelope, pending: ServicePendingInstanceActivation, expectedCurrentRoute?: ServiceInstanceRouteFence | null): Promise<boolean>;
@@ -289,16 +289,12 @@ class ServiceStatefulRuntime {
289
289
  }
290
290
  requestActorCreate(targetNodeRid, request, timeoutMs) {
291
291
  const correlation = this.nextUserSpotOperation++;
292
- const operation = {
293
- high: this.nodeGeneration,
294
- low: correlation
295
- };
296
292
  return this.requestUserSpotOperation(targetNodeRid, (0, service_stateful_wire_codec_1.encodeActorCreateHeader)({
297
293
  ...request,
298
294
  sourceNodeRid: this.nodeRid,
299
295
  sourceNodeGeneration: this.nodeGeneration,
300
296
  correlation,
301
- operation
297
+ operation: request.operation
302
298
  }), correlation, 'actorCreate', timeoutMs);
303
299
  }
304
300
  async recoverInstanceActivation(envelope, route, expectedCurrentRoute) {
@@ -10,11 +10,13 @@ export interface ZLinkActorPlacementTarget {
10
10
  readonly entrySpotId: string;
11
11
  readonly owner: ZLinkLocationOwnerToken;
12
12
  readonly isLocal: boolean;
13
+ readonly sourceNodeRid: RoutingId;
14
+ readonly sourceNodeGeneration: bigint;
13
15
  }
14
16
  export interface ZLinkActorPlacementCoordinatorOptions {
15
17
  readonly store: ZLinkObjectCreationStore & ZLinkAuthorityStore;
16
18
  readonly target: (meshName: string | undefined, stableType: string, signal?: AbortSignal, excludedNodeRids?: ReadonlySet<string>) => Promise<ZLinkActorPlacementTarget | undefined>;
17
- readonly remoteCreate: (meshName: string, targetNodeRid: string, request: Omit<ServiceActorCreateRecord, 'kind' | 'correlation' | 'operation'>, timeoutMs: number) => Promise<ServiceUserSpotOperationResult>;
19
+ readonly remoteCreate: (meshName: string, targetNodeRid: string, request: Omit<ServiceActorCreateRecord, 'kind' | 'correlation'>, timeoutMs: number) => Promise<ServiceUserSpotOperationResult>;
18
20
  readonly decodeRemoteReply?: (payload: Uint8Array) => unknown;
19
21
  }
20
22
  export declare class ZLinkActorPlacementCoordinator {
@@ -22,11 +24,18 @@ export declare class ZLinkActorPlacementCoordinator {
22
24
  constructor(options: ZLinkActorPlacementCoordinatorOptions);
23
25
  create(actorId: string, stableType: string, createOnly: boolean, meshName: string | undefined, requestPayload: Uint8Array, timeoutMs: number, signal?: AbortSignal): Promise<ZLinkActorCreateResult>;
24
26
  handleRemoteCreate(record: ServiceActorCreateRecord, materialize: (requestPayload: Uint8Array, authority: ZLinkAuthoritySnapshot, signal: AbortSignal) => Promise<{
25
- readonly result: 'created' | 'rejected';
26
- readonly actor?: ActorRef;
27
+ readonly result: 'created';
28
+ readonly actor: ActorRef;
27
29
  readonly reply?: Uint8Array;
28
30
  readonly onPublished?: () => void;
29
- readonly entrySpotId?: string;
30
- readonly entrySpotGeneration?: bigint;
31
+ readonly entrySpotId: string;
32
+ readonly entrySpotGeneration: bigint;
33
+ } | {
34
+ readonly result: 'rejected';
35
+ readonly reply?: Uint8Array;
36
+ readonly onPublished?: () => void;
37
+ } | {
38
+ readonly result: 'failed';
39
+ readonly error: unknown;
31
40
  }>, signal: AbortSignal): Promise<ServiceUserSpotOperationResult>;
32
41
  }