@zlink-systems/framework 0.11.0 → 0.13.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 (119) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Configuration/EndpointNotation.d.ts +5 -4
  3. package/dist/contracts/Configuration/EndpointNotation.js +5 -4
  4. package/dist/contracts/Configuration/InternalDefaults.d.ts +0 -1
  5. package/dist/contracts/Configuration/InternalDefaults.js +1 -2
  6. package/dist/contracts/Configuration/RegistrationNormalizers.js +1 -2
  7. package/dist/contracts/Configuration/RegistrationTypes.d.ts +2 -5
  8. package/dist/contracts/Configuration/RegistrationValidators.js +0 -1
  9. package/dist/contracts/Errors/ZLinkFrameworkException.d.ts +6 -7
  10. package/dist/contracts/Errors/ZLinkFrameworkException.js +6 -7
  11. package/dist/runtime/actors/actor-client.js +1 -1
  12. package/dist/runtime/actors/actor-mailbox.js +1 -5
  13. package/dist/runtime/backend/contracts/index.d.ts +2 -0
  14. package/dist/runtime/backend/mesh-completion-table.d.ts +1 -3
  15. package/dist/runtime/backend/mesh-completion-table.js +11 -15
  16. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +11 -4
  17. package/dist/runtime/backend/mesh-dispatch-pump.js +201 -134
  18. package/dist/runtime/backend/node/node-backend-adapter-factory.d.ts +3 -4
  19. package/dist/runtime/backend/node/node-backend-adapter-factory.js +51 -37
  20. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
  21. package/dist/runtime/backend/node/node-backend-adapter-support.js +2 -2
  22. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +2 -2
  23. package/dist/runtime/backend/node/node-event-loop-poller.d.ts +16 -0
  24. package/dist/runtime/backend/node/node-event-loop-poller.js +49 -0
  25. package/dist/runtime/backend/node/node-raw-binding-port.js +24 -41
  26. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +8 -8
  27. package/dist/runtime/backend/node/node-raw-mesh-backend.js +100 -107
  28. package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +3 -2
  29. package/dist/runtime/backend/node/node-socket-backend-adapter.js +18 -67
  30. package/dist/runtime/backend/raw-binding-port.d.ts +1 -0
  31. package/dist/runtime/backend/runtime-values.d.ts +5 -1
  32. package/dist/runtime/channels/channel-dispatchers.js +2 -2
  33. package/dist/runtime/channels/channel-envelope.js +324 -121
  34. package/dist/runtime/channels/channel-multipart.d.ts +8 -1
  35. package/dist/runtime/channels/channel-outbound-operations.js +0 -2
  36. package/dist/runtime/channels/channel-receive-loops.d.ts +1 -3
  37. package/dist/runtime/channels/channel-receive-loops.js +25 -65
  38. package/dist/runtime/channels/channel-socket-registry.js +3 -1
  39. package/dist/runtime/channels/channel-transports.d.ts +2 -1
  40. package/dist/runtime/channels/channel-transports.js +12 -10
  41. package/dist/runtime/execution/serial-execution-queue.d.ts +5 -18
  42. package/dist/runtime/execution/serial-execution-queue.js +16 -80
  43. package/dist/runtime/foundation/event-loop-resources.d.ts +0 -3
  44. package/dist/runtime/foundation/event-loop-resources.js +2 -11
  45. package/dist/runtime/foundation/operation-registry.d.ts +2 -8
  46. package/dist/runtime/foundation/operation-registry.js +3 -21
  47. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +19 -7
  48. package/dist/runtime/foundation/raw-service-mesh-runtime.js +56 -10
  49. package/dist/runtime/foundation/service-mailbox.d.ts +1 -7
  50. package/dist/runtime/foundation/service-mailbox.js +3 -2
  51. package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -1
  52. package/dist/runtime/foundation/service-stateful-registry.d.ts +1 -1
  53. package/dist/runtime/foundation/service-stateful-registry.js +2 -2
  54. package/dist/runtime/foundation/service-stateful-runtime.js +14 -14
  55. package/dist/runtime/framework-errors-internal.d.ts +4 -4
  56. package/dist/runtime/framework-errors-internal.js +8 -10
  57. package/dist/runtime/host/actor-placement-coordinator.js +1 -1
  58. package/dist/runtime/host/index.js +1 -1
  59. package/dist/runtime/host/service-relocation-host-runtime.js +0 -4
  60. package/dist/runtime/host/spot-address-transport.js +1 -1
  61. package/dist/runtime/host/user-spot-creation-coordinator.js +1 -1
  62. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +0 -12
  63. package/dist/runtime/spots/spot-node-runtime-manager.js +6 -166
  64. package/dist/runtime/spots/spot-serial-turn-executor.js +1 -4
  65. package/dist/runtime/spots/spot-timer.d.ts +3 -0
  66. package/dist/runtime/spots/spot-timer.js +87 -18
  67. package/dist/runtime/streams/session-serial-executor.js +1 -3
  68. package/dist/runtime/streams/stream-session-runtime.d.ts +2 -2
  69. package/dist/runtime/streams/stream-session-runtime.js +13 -19
  70. package/dist/runtime/workers/index.d.ts +0 -1
  71. package/dist/runtime/workers/index.js +1 -9
  72. package/package.json +3 -3
  73. package/src/contracts/Configuration/EndpointNotation.ts +5 -4
  74. package/src/contracts/Configuration/InternalDefaults.ts +0 -1
  75. package/src/contracts/Configuration/RegistrationNormalizers.ts +2 -4
  76. package/src/contracts/Configuration/RegistrationTypes.ts +2 -5
  77. package/src/contracts/Configuration/RegistrationValidators.ts +0 -1
  78. package/src/contracts/Errors/ZLinkFrameworkException.ts +6 -7
  79. package/src/runtime/actors/actor-client.ts +1 -1
  80. package/src/runtime/actors/actor-mailbox.ts +1 -12
  81. package/src/runtime/backend/contracts/index.ts +2 -0
  82. package/src/runtime/backend/mesh-completion-table.ts +12 -23
  83. package/src/runtime/backend/mesh-dispatch-pump.ts +206 -138
  84. package/src/runtime/backend/node/node-backend-adapter-factory.ts +66 -35
  85. package/src/runtime/backend/node/node-backend-adapter-support.ts +4 -4
  86. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +2 -2
  87. package/src/runtime/backend/node/node-event-loop-poller.ts +55 -0
  88. package/src/runtime/backend/node/node-raw-binding-port.ts +30 -45
  89. package/src/runtime/backend/node/node-raw-mesh-backend.ts +97 -110
  90. package/src/runtime/backend/node/node-socket-backend-adapter.ts +23 -69
  91. package/src/runtime/backend/raw-binding-port.ts +1 -0
  92. package/src/runtime/backend/runtime-values.ts +7 -1
  93. package/src/runtime/channels/channel-dispatchers.ts +2 -2
  94. package/src/runtime/channels/channel-envelope.ts +379 -109
  95. package/src/runtime/channels/channel-multipart.ts +9 -1
  96. package/src/runtime/channels/channel-outbound-operations.ts +0 -1
  97. package/src/runtime/channels/channel-receive-loops.ts +24 -75
  98. package/src/runtime/channels/channel-socket-registry.ts +4 -1
  99. package/src/runtime/channels/channel-transports.ts +20 -10
  100. package/src/runtime/execution/serial-execution-queue.ts +16 -108
  101. package/src/runtime/foundation/event-loop-resources.ts +2 -11
  102. package/src/runtime/foundation/operation-registry.ts +2 -22
  103. package/src/runtime/foundation/raw-service-mesh-runtime.ts +74 -19
  104. package/src/runtime/foundation/service-mailbox.ts +3 -13
  105. package/src/runtime/foundation/service-runtime-contracts.ts +2 -1
  106. package/src/runtime/foundation/service-stateful-registry.ts +2 -2
  107. package/src/runtime/foundation/service-stateful-runtime.ts +14 -14
  108. package/src/runtime/framework-errors-internal.ts +8 -10
  109. package/src/runtime/host/actor-placement-coordinator.ts +1 -1
  110. package/src/runtime/host/index.ts +2 -1
  111. package/src/runtime/host/service-relocation-host-runtime.ts +0 -4
  112. package/src/runtime/host/spot-address-transport.ts +1 -1
  113. package/src/runtime/host/user-spot-creation-coordinator.ts +1 -1
  114. package/src/runtime/spots/spot-node-runtime-manager.ts +13 -233
  115. package/src/runtime/spots/spot-serial-turn-executor.ts +1 -8
  116. package/src/runtime/spots/spot-timer.ts +109 -18
  117. package/src/runtime/streams/session-serial-executor.ts +1 -7
  118. package/src/runtime/streams/stream-session-runtime.ts +13 -17
  119. package/src/runtime/workers/index.ts +2 -17
@@ -1,7 +1,6 @@
1
1
  import type {
2
2
  Context,
3
3
  CoreHwmBudgetSnapshot,
4
- Received,
5
4
  TopicMessage
6
5
  } from '@zlink-systems/zlink';
7
6
  import type { ZLinkCoreHwmOptions } from '../../../contracts/Configuration';
@@ -11,6 +10,7 @@ import type {
11
10
  ZLinkBackendDealerSocket,
12
11
  ZLinkBackendPublisherSocket,
13
12
  ZLinkBackendReadablePoller,
13
+ ZLinkBackendReceived,
14
14
  ZLinkBackendRouterSocket,
15
15
  ZLinkBackendSocket,
16
16
  ZLinkBackendSocketMonitor,
@@ -24,18 +24,15 @@ import type {
24
24
  import {
25
25
  closeWithBusyRetry,
26
26
  isContextTerminatedError,
27
- isPollerInterruptedError,
28
27
  zlink,
29
28
  type ZLinkBindingModule
30
29
  } from './node-backend-adapter-support';
31
30
  import { wrapMonitorSocket } from './node-monitor-backend-adapter';
32
- import { wrapSocket } from './node-socket-backend-adapter';
31
+ import { nodeEventLoopPollerOf, wrapSocket } from './node-socket-backend-adapter';
33
32
  import { ZLinkNodeMeshBackendAdapter } from './node-mesh-backend-adapter';
34
33
 
35
- export { isDisconnectRouteNotFoundError } from './node-socket-backend-adapter';
36
-
37
34
  export class ZLinkNodeBackendAdapterFactory implements ZLinkBackendAdapterFactory {
38
- createReceived(): Received {
35
+ createReceived(): ZLinkBackendReceived {
39
36
  return new zlink.Received();
40
37
  }
41
38
 
@@ -70,11 +67,17 @@ class ZLinkNodeChannelBackendAdapter implements ZLinkChannelBackendAdapter {
70
67
  }
71
68
 
72
69
  createDealerSocket(context: ZLinkBackendContext): ZLinkBackendDealerSocket {
73
- return wrapSocket(zlink.createDealerSocket(asNodeContext(context))) as unknown as ZLinkBackendDealerSocket;
70
+ return wrapSocket(
71
+ zlink.createDealerSocket(asNodeContext(context)),
72
+ true
73
+ ) as unknown as ZLinkBackendDealerSocket;
74
74
  }
75
75
 
76
76
  createRouterSocket(context: ZLinkBackendContext): ZLinkBackendRouterSocket {
77
- return wrapSocket(zlink.createRouterSocket(asNodeContext(context))) as unknown as ZLinkBackendRouterSocket;
77
+ return wrapSocket(
78
+ zlink.createRouterSocket(asNodeContext(context)),
79
+ true
80
+ ) as unknown as ZLinkBackendRouterSocket;
78
81
  }
79
82
 
80
83
  createPublisherSocket(context: ZLinkBackendContext): ZLinkBackendPublisherSocket {
@@ -82,7 +85,10 @@ class ZLinkNodeChannelBackendAdapter implements ZLinkChannelBackendAdapter {
82
85
  }
83
86
 
84
87
  createSubscriberSocket(context: ZLinkBackendContext): ZLinkBackendSubscriberSocket {
85
- return wrapSocket(zlink.createSubSocket(asNodeContext(context))) as unknown as ZLinkBackendSubscriberSocket;
88
+ return wrapSocket(
89
+ zlink.createSubSocket(asNodeContext(context)),
90
+ false
91
+ ) as unknown as ZLinkBackendSubscriberSocket;
86
92
  }
87
93
 
88
94
  createReadablePoller(socket: ZLinkBackendSubscriberSocket): ZLinkBackendReadablePoller {
@@ -94,7 +100,7 @@ class ZLinkNodeStreamBackendAdapter implements ZLinkStreamBackendAdapter {
94
100
  createStreamSocket(context: ZLinkBackendContext): ZLinkBackendStreamSocket {
95
101
  const socket = zlink.createStreamSocket(asNodeContext(context));
96
102
  socket.options.recvMode = zlink.StreamRecvMode.Packet;
97
- return wrapSocket(socket) as unknown as ZLinkBackendStreamSocket;
103
+ return wrapSocket(socket, true) as unknown as ZLinkBackendStreamSocket;
98
104
  }
99
105
 
100
106
  createStreamPacket(): ZLinkBackendStreamPacket {
@@ -167,38 +173,63 @@ function asNodeContext(context: ZLinkBackendContext): Context {
167
173
  function createNodeReadablePoller(
168
174
  socket: { readonly nativeInstance: unknown }
169
175
  ): ZLinkBackendReadablePoller {
170
- const poller = zlink.createPoller();
171
- const events = zlink.createPollEvents(1);
172
- try {
173
- poller.add(socket.nativeInstance as never, [zlink.PollEventFlag.PollIn], 0);
174
- } catch (error) {
175
- events.close();
176
- poller.close();
177
- throw error;
178
- }
176
+ const eventLoopPoller = nodeEventLoopPollerOf(socket);
179
177
  let disposed = false;
178
+ let readable = false;
179
+ let pending: {
180
+ readonly promise: Promise<boolean>;
181
+ readonly resolve: (readable: boolean) => void;
182
+ readonly signal?: AbortSignal;
183
+ readonly onAbort?: () => void;
184
+ } | undefined;
185
+
186
+ const settlePending = (value: boolean): void => {
187
+ const current = pending;
188
+ if (current === undefined) return;
189
+ pending = undefined;
190
+ if (current.signal !== undefined && current.onAbort !== undefined) {
191
+ current.signal.removeEventListener('abort', current.onAbort);
192
+ }
193
+ current.resolve(value);
194
+ };
195
+
196
+ eventLoopPoller.setReadableHandler(() => {
197
+ if (disposed) return;
198
+ readable = true;
199
+ settlePending(true);
200
+ });
201
+
180
202
  return {
181
- wait(timeoutMs: number): boolean {
182
- try {
183
- return poller.wait(events, timeoutMs) > 0
184
- && events.hasEvent(0, zlink.PollEventFlag.PollIn);
185
- } catch (error) {
186
- if (isPollerInterruptedError(error)) return false;
187
- throw error;
203
+ wait(_timeoutMs: number): boolean {
204
+ return !disposed && readable;
205
+ },
206
+ waitForReadable(signal?: AbortSignal): Promise<boolean> {
207
+ if (disposed || signal?.aborted === true) return Promise.resolve(false);
208
+ if (readable) return Promise.resolve(true);
209
+ if (pending !== undefined) return pending.promise;
210
+
211
+ let resolvePending!: (value: boolean) => void;
212
+ const promise = new Promise<boolean>((resolve) => {
213
+ resolvePending = resolve;
214
+ });
215
+ const onAbort = signal === undefined
216
+ ? undefined
217
+ : (): void => settlePending(false);
218
+ pending = { promise, resolve: resolvePending, signal, onAbort };
219
+ if (signal !== undefined && onAbort !== undefined) {
220
+ signal.addEventListener('abort', onAbort, { once: true });
188
221
  }
222
+ return promise;
223
+ },
224
+ markDrained(): void {
225
+ readable = false;
189
226
  },
190
227
  dispose(): void {
191
228
  if (disposed) return;
192
229
  disposed = true;
193
- try {
194
- poller.remove(socket.nativeInstance as never);
195
- } finally {
196
- try {
197
- events.close();
198
- } finally {
199
- poller.close();
200
- }
201
- }
230
+ readable = false;
231
+ settlePending(false);
232
+ eventLoopPoller.setReadableHandler(() => {});
202
233
  }
203
234
  };
204
235
  }
@@ -30,7 +30,7 @@ interface ZLinkBindingReplySubmitOperation {
30
30
 
31
31
  interface ZLinkBindingAsyncSendSubmitOperation {
32
32
  message(message: unknown): ZLinkBindingAsyncSendSubmitOperation;
33
- submit(): Promise<void>;
33
+ submit(): import('@zlink-systems/zlink').SendSubmission;
34
34
  submit_sync(): void;
35
35
  }
36
36
 
@@ -41,7 +41,7 @@ export interface ZLinkBindingRequestOperation {
41
41
  interface ZLinkBindingRequestSubmitOperation {
42
42
  message(message: unknown): ZLinkBindingRequestSubmitOperation;
43
43
  timeout(timeoutMs: number): ZLinkBindingRequestSubmitOperation;
44
- submit(): Promise<readonly unknown[]>;
44
+ submit(): import('@zlink-systems/zlink').RequestSubmission;
45
45
  }
46
46
 
47
47
  export function isBindingNotFound(error: unknown): boolean {
@@ -113,7 +113,7 @@ export async function submitBindingAsyncSend(
113
113
  current = current === undefined ? operation.message(nativePart) : current.message(nativePart);
114
114
  }
115
115
  current ??= operation.message(Buffer.alloc(0));
116
- await current.submit();
116
+ await current.submit().admitted;
117
117
  } catch (error) {
118
118
  throw translateBindingResultError(error);
119
119
  }
@@ -156,7 +156,7 @@ export async function submitBindingRequest(
156
156
  if (timeoutMs !== undefined) {
157
157
  current = current.timeout(timeoutMs);
158
158
  }
159
- return await current.submit();
159
+ return await current.submit().reply;
160
160
  } catch (error) {
161
161
  throw translateBindingResultError(error);
162
162
  }
@@ -54,7 +54,7 @@ export class ZLinkDealerChannelClientTransport implements ZLinkChannelClientTran
54
54
  true,
55
55
  metadata
56
56
  )
57
- ).submit());
57
+ ).submit().admitted);
58
58
  return { status: ZLinkSubmitStatus.Submitted };
59
59
  }
60
60
 
@@ -83,7 +83,7 @@ export class ZLinkDealerChannelClientTransport implements ZLinkChannelClientTran
83
83
  )
84
84
  ));
85
85
  if (timeoutMs !== undefined) operation.timeout(timeoutMs);
86
- const reply = await submitRequestOperation(operation, 'channel request');
86
+ const reply = await submitRequestOperation({ submit: () => operation.submit().reply }, 'channel request');
87
87
  try {
88
88
  return decodeChannelReply<TReply>(reply);
89
89
  } finally {
@@ -0,0 +1,55 @@
1
+ import type {
2
+ BaseSocket,
3
+ PollEventFlagValue,
4
+ Socket
5
+ } from '@zlink-systems/zlink';
6
+ import { zlink } from './node-backend-adapter-support';
7
+
8
+ /**
9
+ * Owns one binding public Poller and drives it from the socket's libuv
10
+ * readiness callback. PollCompletion is drained only by Poller.wait; the
11
+ * socket callback itself is only the event-loop wakeup.
12
+ */
13
+ export class ZLinkNodeEventLoopPoller {
14
+ private readonly poller = zlink.createPoller();
15
+ private readonly events = zlink.createPollEvents(1);
16
+ private readableHandler: () => void;
17
+ private disposed = false;
18
+
19
+ constructor(
20
+ socket: Socket,
21
+ pollCompletion: boolean,
22
+ readableHandler: () => void
23
+ ) {
24
+ this.readableHandler = readableHandler;
25
+ try {
26
+ const pollEvents: PollEventFlagValue[] = [zlink.PollEventFlag.PollIn];
27
+ if (pollCompletion) pollEvents.push(zlink.PollEventFlag.PollCompletion);
28
+ this.poller.add(socket as BaseSocket, pollEvents, 0);
29
+ socket.setReadableHandler(this.onReady);
30
+ } catch (error) {
31
+ this.events.close();
32
+ this.poller.close();
33
+ throw error;
34
+ }
35
+ }
36
+
37
+ setReadableHandler(handler: () => void): void {
38
+ this.readableHandler = handler;
39
+ }
40
+
41
+ dispose(): void {
42
+ if (this.disposed) return;
43
+ this.disposed = true;
44
+ this.events.close();
45
+ this.poller.close();
46
+ }
47
+
48
+ private readonly onReady = (): void => {
49
+ if (this.disposed) return;
50
+ const ready = this.poller.wait(this.events, 0);
51
+ if (ready === 0 || this.events.hasEvent(0, zlink.PollEventFlag.PollIn)) {
52
+ this.readableHandler();
53
+ }
54
+ };
55
+ }
@@ -5,11 +5,9 @@ import {
5
5
  RoutingId as BindingRoutingId,
6
6
  createContext,
7
7
  createDealerSocket,
8
- createPollEvents,
9
- createPoller,
10
8
  createRouterSocket,
11
- PollEventFlag,
12
9
  ReceiveFlowState,
10
+ SubmitResult,
13
11
  type Context,
14
12
  type DealerSocket,
15
13
  type MonitorEvent,
@@ -24,8 +22,9 @@ import {
24
22
  type SendSubmitOperation,
25
23
  type Socket
26
24
  } from '@zlink-systems/zlink';
27
- import { isPollerInterruptedError, translateBindingResultError } from './node-backend-adapter-support';
25
+ import { translateBindingResultError } from './node-backend-adapter-support';
28
26
  import { isEndpointCloseIgnorableError } from './node-socket-backend-adapter';
27
+ import { ZLinkNodeEventLoopPoller } from './node-event-loop-poller';
29
28
  import type {
30
29
  ZLinkRawBindingPort,
31
30
  ZLinkRawDealerPort,
@@ -122,12 +121,20 @@ class NodeRawHostPort implements ZLinkRawHostPort {
122
121
  abstract class NodeRawSocketPort<TSocket extends Socket> implements ZLinkRawSocketPort {
123
122
  private readonly endpoints = new Set<string>();
124
123
  private readonly monitors = new Set<NodeRawMonitorPort>();
125
- private readonly readablePoller = createPoller();
126
- private readonly readableEvents = createPollEvents(1);
124
+ private readonly eventLoopPoller: ZLinkNodeEventLoopPoller;
127
125
  private closed = false;
128
126
 
129
127
  protected constructor(protected readonly socket: TSocket) {
130
- this.readablePoller.add(socket as never, [PollEventFlag.PollIn], 0);
128
+ this.eventLoopPoller = new ZLinkNodeEventLoopPoller(
129
+ socket,
130
+ true,
131
+ () => {}
132
+ );
133
+ }
134
+
135
+ setReadableHandler(handler: () => void): void {
136
+ this.requireOpen();
137
+ this.eventLoopPoller.setReadableHandler(handler);
131
138
  }
132
139
 
133
140
  bind(endpoint: string): void {
@@ -172,6 +179,11 @@ abstract class NodeRawSocketPort<TSocket extends Socket> implements ZLinkRawSock
172
179
  close(): void {
173
180
  if (this.closed) return;
174
181
  const failures: unknown[] = [];
182
+ try {
183
+ this.eventLoopPoller.dispose();
184
+ } catch (error) {
185
+ failures.push(error);
186
+ }
175
187
  for (const monitor of [...this.monitors].reverse()) {
176
188
  try {
177
189
  monitor.close();
@@ -192,21 +204,6 @@ abstract class NodeRawSocketPort<TSocket extends Socket> implements ZLinkRawSock
192
204
  }
193
205
  }
194
206
  this.endpoints.clear();
195
- try {
196
- this.readablePoller.remove(this.socket as never);
197
- } catch (error) {
198
- failures.push(error);
199
- }
200
- try {
201
- this.readableEvents.close();
202
- } catch (error) {
203
- failures.push(error);
204
- }
205
- try {
206
- this.readablePoller.close();
207
- } catch (error) {
208
- failures.push(error);
209
- }
210
207
  try {
211
208
  this.socket.close();
212
209
  } catch (error) {
@@ -222,24 +219,6 @@ abstract class NodeRawSocketPort<TSocket extends Socket> implements ZLinkRawSock
222
219
  protected requireOpen(): void {
223
220
  if (this.closed) throw new Error('Raw socket is closed.');
224
221
  }
225
-
226
- protected receiveRecord(
227
- dontWait: boolean
228
- ): ZLinkRawReceivedRecord | undefined {
229
- const timeoutMs = dontWait ? 0 : -1;
230
- try {
231
- if (
232
- this.readablePoller.wait(this.readableEvents, timeoutMs) <= 0
233
- || !this.readableEvents.hasEvent(0, PollEventFlag.PollIn)
234
- ) {
235
- return undefined;
236
- }
237
- } catch (error) {
238
- if (isPollerInterruptedError(error)) return undefined;
239
- throw error;
240
- }
241
- return receiveRecord(this.socket as never, true);
242
- }
243
222
  }
244
223
 
245
224
  class NodeRawRouterPort extends NodeRawSocketPort<RouterSocket> implements ZLinkRawRouterPort {
@@ -276,10 +255,13 @@ class NodeRawRouterPort extends NodeRawSocketPort<RouterSocket> implements ZLink
276
255
 
277
256
  async send(targetRid: string, parts: readonly Uint8Array[]): Promise<void> {
278
257
  this.requireOpen();
279
- await appendSendParts(
258
+ const submission = appendSendParts(
280
259
  this.socket.send(bindingRoutingId(targetRid)),
281
260
  parts
282
261
  ).submit();
262
+ if (submission.result === SubmitResult.Backpressured) {
263
+ await submission.admitted;
264
+ }
283
265
  }
284
266
 
285
267
  async request(
@@ -291,7 +273,7 @@ class NodeRawRouterPort extends NodeRawSocketPort<RouterSocket> implements ZLink
291
273
  try {
292
274
  const replies = await appendRequestParts(this.socket.request(bindingRoutingId(targetRid)), parts)
293
275
  .timeout(timeoutMs)
294
- .submit();
276
+ .submit().reply;
295
277
  return copyAndClose(replies);
296
278
  } catch (error) {
297
279
  throw translateBindingResultError(error);
@@ -332,18 +314,21 @@ class NodeRawDealerPort extends NodeRawSocketPort<DealerSocket> implements ZLink
332
314
 
333
315
  async send(parts: readonly Uint8Array[]): Promise<void> {
334
316
  this.requireOpen();
335
- await appendSendParts(this.socket.send(), parts).submit();
317
+ const submission = appendSendParts(this.socket.send(), parts).submit();
318
+ if (submission.result === SubmitResult.Backpressured) {
319
+ await submission.admitted;
320
+ }
336
321
  }
337
322
 
338
323
  async request(parts: readonly Uint8Array[], timeoutMs: number): Promise<readonly Buffer[]> {
339
324
  this.requireOpen();
340
- const replies = await appendRequestParts(this.socket.request(), parts).timeout(timeoutMs).submit();
325
+ const replies = await appendRequestParts(this.socket.request(), parts).timeout(timeoutMs).submit().reply;
341
326
  return copyAndClose(replies);
342
327
  }
343
328
 
344
329
  receive(dontWait = false): ZLinkRawReceivedRecord | undefined {
345
330
  this.requireOpen();
346
- return this.receiveRecord(dontWait);
331
+ return receiveRecord(this.socket, dontWait);
347
332
  }
348
333
  }
349
334