@zlink-systems/framework 0.31.0 → 0.32.1

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 (181) 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-context.js +1 -1
  15. package/dist/runtime/actors/actor-creation.js +1 -1
  16. package/dist/runtime/actors/actor-mailbox.d.ts +1 -1
  17. package/dist/runtime/actors/actor-runtime-state.d.ts +3 -2
  18. package/dist/runtime/actors/actor-runtime-state.js +24 -8
  19. package/dist/runtime/actors/index.d.ts +3 -3
  20. package/dist/runtime/actors/index.js +19 -32
  21. package/dist/runtime/actors/spot-actor-dispatch.d.ts +4 -2
  22. package/dist/runtime/actors/spot-actor-dispatch.js +2 -1
  23. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +1 -0
  24. package/dist/runtime/application-jobs/application-ingress-record-owner.js +3 -0
  25. package/dist/runtime/backend/contracts/index.d.ts +2 -0
  26. package/dist/runtime/backend/mesh-completion-table.d.ts +1 -0
  27. package/dist/runtime/backend/mesh-completion-table.js +1 -0
  28. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +5 -1
  29. package/dist/runtime/backend/node/node-raw-binding-port.d.ts +7 -2
  30. package/dist/runtime/backend/node/node-raw-binding-port.js +17 -11
  31. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +2 -2
  32. package/dist/runtime/backend/node/node-raw-mesh-backend.js +15 -8
  33. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +7 -6
  34. package/dist/runtime/channels/channel-dispatch-pipeline.js +1 -0
  35. package/dist/runtime/channels/channel-dispatchers.d.ts +7 -3
  36. package/dist/runtime/channels/channel-dispatchers.js +27 -19
  37. package/dist/runtime/channels/channel-envelope.js +543 -23
  38. package/dist/runtime/channels/channel-receive-loops.d.ts +9 -6
  39. package/dist/runtime/channels/channel-receive-loops.js +59 -18
  40. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +22 -3
  41. package/dist/runtime/channels/channel-socket-registry.d.ts +22 -4
  42. package/dist/runtime/diagnostics/runtime-metrics.d.ts +1 -1
  43. package/dist/runtime/diagnostics/runtime-metrics.js +2 -1
  44. package/dist/runtime/execution/serial-execution-queue.d.ts +26 -13
  45. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +27 -11
  46. package/dist/runtime/foundation/raw-service-mesh-runtime.js +29 -25
  47. package/dist/runtime/foundation/service-liveness-registry.d.ts +1 -1
  48. package/dist/runtime/foundation/service-mailbox.d.ts +3 -1
  49. package/dist/runtime/foundation/service-mailbox.js +4 -1
  50. package/dist/runtime/foundation/service-runtime-contracts.d.ts +3 -1
  51. package/dist/runtime/foundation/service-stateful-registry.d.ts +2 -0
  52. package/dist/runtime/foundation/service-stateful-registry.js +28 -12
  53. package/dist/runtime/foundation/service-stateful-runtime.d.ts +51 -19
  54. package/dist/runtime/foundation/service-stateful-runtime.js +54 -5
  55. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +3 -0
  56. package/dist/runtime/foundation/service-stateful-wire-codec.js +15 -0
  57. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  58. package/dist/runtime/foundation/service-wire-constants.generated.js +12 -0
  59. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +2 -0
  60. package/dist/runtime/foundation/service-wire-m6a-codec.js +17 -7
  61. package/dist/runtime/host/actor-placement-coordinator.d.ts +1 -1
  62. package/dist/runtime/host/actor-transfer-runtime.d.ts +3 -3
  63. package/dist/runtime/host/application-job-queue.d.ts +1 -1
  64. package/dist/runtime/host/index.d.ts +89 -36
  65. package/dist/runtime/host/index.js +101 -7
  66. package/dist/runtime/host/location-runtime-owner.d.ts +2 -2
  67. package/dist/runtime/host/service-relocation-host-runtime.d.ts +181 -44
  68. package/dist/runtime/host/service-relocation-host-runtime.js +47 -13
  69. package/dist/runtime/host/spot-address-transport.js +50 -42
  70. package/dist/runtime/locations/actor-location-claims.js +9 -10
  71. package/dist/runtime/locations/auto-connect-loop.d.ts +0 -1
  72. package/dist/runtime/locations/auto-connect-loop.js +25 -19
  73. package/dist/runtime/locations/auto-connect-planner.js +2 -5
  74. package/dist/runtime/locations/auto-connect-reconciler.d.ts +1 -0
  75. package/dist/runtime/locations/auto-connect-reconciler.js +35 -23
  76. package/dist/runtime/locations/in-memory-location-store.d.ts +0 -2
  77. package/dist/runtime/locations/in-memory-location-store.js +1 -38
  78. package/dist/runtime/locations/location-store-repository.d.ts +0 -1
  79. package/dist/runtime/locations/location-store-repository.js +13 -115
  80. package/dist/runtime/locations/runtime.d.ts +3 -3
  81. package/dist/runtime/locations/runtime.js +12 -16
  82. package/dist/runtime/messaging/creation-payload-codec.js +2 -2
  83. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +4 -0
  84. package/dist/runtime/protocol/service_wire_codec.generated.js +17 -7
  85. package/dist/runtime/spots/index.d.ts +20 -5
  86. package/dist/runtime/spots/index.js +14 -0
  87. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +3 -3
  88. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +1 -0
  89. package/dist/runtime/spots/spot-actor-packet-dispatch.js +13 -7
  90. package/dist/runtime/spots/spot-actor-packet-drain.d.ts +1 -0
  91. package/dist/runtime/spots/spot-actor-packet-drain.js +12 -5
  92. package/dist/runtime/spots/spot-entry-activation.d.ts +2 -1
  93. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +8 -6
  94. package/dist/runtime/spots/spot-node-runtime-manager.js +2 -0
  95. package/dist/runtime/spots/spot-route-packet-dispatch.js +7 -4
  96. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +3 -1
  97. package/dist/runtime/spots/spot-serial-executor.d.ts +2 -1
  98. package/dist/runtime/spots/spot-subscription-dispatch.js +3 -1
  99. package/dist/runtime/spots/spot-timer.d.ts +1 -1
  100. package/dist/runtime/streams/actor-session-binding-registry.d.ts +9 -3
  101. package/dist/runtime/streams/actor-session-binding-registry.js +17 -0
  102. package/dist/runtime/streams/index.d.ts +3 -3
  103. package/dist/runtime/streams/index.js +22 -2
  104. package/dist/runtime/streams/managed-stream.js +2 -1
  105. package/dist/runtime/streams/session-calls.d.ts +1 -1
  106. package/dist/runtime/streams/session-calls.js +3 -9
  107. package/dist/runtime/streams/session-context.d.ts +2 -2
  108. package/dist/runtime/streams/session-context.js +2 -2
  109. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -0
  110. package/dist/runtime/streams/stream-session-runtime.js +37 -12
  111. package/package.json +3 -3
  112. package/src/contracts/Actors/ZLinkActor.ts +6 -0
  113. package/src/contracts/Actors/ZLinkSessionBindingIdentity.ts +7 -0
  114. package/src/contracts/Actors/index.ts +1 -0
  115. package/src/contracts/Common/payload-slab.ts +29 -0
  116. package/src/contracts/Handlers/Contexts.ts +1 -0
  117. package/src/internal.ts +17 -0
  118. package/src/runtime/actors/actor-client.ts +48 -23
  119. package/src/runtime/actors/actor-context.ts +1 -1
  120. package/src/runtime/actors/actor-creation.ts +1 -1
  121. package/src/runtime/actors/actor-mailbox.ts +1 -1
  122. package/src/runtime/actors/actor-runtime-state.ts +28 -10
  123. package/src/runtime/actors/index.ts +30 -35
  124. package/src/runtime/actors/spot-actor-dispatch.ts +4 -3
  125. package/src/runtime/application-jobs/application-ingress-record-owner.ts +4 -0
  126. package/src/runtime/backend/contracts/index.ts +2 -0
  127. package/src/runtime/backend/mesh-completion-table.ts +2 -0
  128. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +5 -1
  129. package/src/runtime/backend/node/node-raw-binding-port.ts +20 -7
  130. package/src/runtime/backend/node/node-raw-mesh-backend.ts +18 -10
  131. package/src/runtime/channels/channel-dispatch-pipeline.ts +6 -5
  132. package/src/runtime/channels/channel-dispatchers.ts +39 -19
  133. package/src/runtime/channels/channel-envelope.ts +547 -20
  134. package/src/runtime/channels/channel-receive-loops.ts +93 -36
  135. package/src/runtime/channels/channel-runtime-lifecycle.ts +2 -2
  136. package/src/runtime/channels/channel-socket-registry.ts +3 -3
  137. package/src/runtime/diagnostics/runtime-metrics.ts +3 -1
  138. package/src/runtime/execution/serial-execution-queue.ts +13 -13
  139. package/src/runtime/foundation/raw-service-mesh-runtime.ts +40 -39
  140. package/src/runtime/foundation/service-liveness-registry.ts +1 -1
  141. package/src/runtime/foundation/service-mailbox.ts +6 -1
  142. package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
  143. package/src/runtime/foundation/service-stateful-registry.ts +39 -14
  144. package/src/runtime/foundation/service-stateful-runtime.ts +87 -21
  145. package/src/runtime/foundation/service-stateful-wire-codec.ts +18 -0
  146. package/src/runtime/foundation/service-wire-constants.generated.ts +10 -0
  147. package/src/runtime/foundation/service-wire-m6a-codec.ts +29 -7
  148. package/src/runtime/host/actor-placement-coordinator.ts +1 -1
  149. package/src/runtime/host/actor-transfer-runtime.ts +3 -3
  150. package/src/runtime/host/application-job-queue.ts +1 -1
  151. package/src/runtime/host/index.ts +183 -44
  152. package/src/runtime/host/location-runtime-owner.ts +2 -2
  153. package/src/runtime/host/service-relocation-host-runtime.ts +101 -65
  154. package/src/runtime/host/spot-address-transport.ts +67 -61
  155. package/src/runtime/locations/actor-location-claims.ts +14 -14
  156. package/src/runtime/locations/auto-connect-loop.ts +24 -16
  157. package/src/runtime/locations/auto-connect-planner.ts +2 -5
  158. package/src/runtime/locations/auto-connect-reconciler.ts +37 -24
  159. package/src/runtime/locations/in-memory-location-store.ts +1 -74
  160. package/src/runtime/locations/location-store-repository.ts +32 -153
  161. package/src/runtime/locations/runtime.ts +16 -28
  162. package/src/runtime/messaging/creation-payload-codec.ts +3 -3
  163. package/src/runtime/protocol/service_wire_codec.generated.ts +18 -8
  164. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
  165. package/src/runtime/spots/index.ts +28 -4
  166. package/src/runtime/spots/spot-actor-admission-coordinator.ts +1 -1
  167. package/src/runtime/spots/spot-actor-packet-dispatch.ts +16 -6
  168. package/src/runtime/spots/spot-actor-packet-drain.ts +21 -6
  169. package/src/runtime/spots/spot-entry-activation.ts +1 -1
  170. package/src/runtime/spots/spot-node-runtime-manager.ts +8 -6
  171. package/src/runtime/spots/spot-route-packet-dispatch.ts +8 -4
  172. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +3 -1
  173. package/src/runtime/spots/spot-serial-executor.ts +1 -1
  174. package/src/runtime/spots/spot-subscription-dispatch.ts +3 -1
  175. package/src/runtime/spots/spot-timer.ts +1 -1
  176. package/src/runtime/streams/actor-session-binding-registry.ts +30 -3
  177. package/src/runtime/streams/index.ts +30 -4
  178. package/src/runtime/streams/managed-stream.ts +2 -1
  179. package/src/runtime/streams/session-calls.ts +9 -14
  180. package/src/runtime/streams/session-context.ts +6 -11
  181. package/src/runtime/streams/stream-session-runtime.ts +49 -20
@@ -60,6 +60,9 @@ import { ZLinkBoundSessionService, type ZLinkBoundSessionTransport } from './bou
60
60
  import { ZLinkManagedStream } from './managed-stream';
61
61
  import {
62
62
  messageToBytes,
63
+ decodeStreamFrame,
64
+ decodeStreamHeader,
65
+ encodeStreamFrame,
63
66
  ZLinkStreamCodec,
64
67
  ZLinkStreamMessageKind,
65
68
  type ZLinkStreamFrameHeader,
@@ -417,7 +420,7 @@ export class ZLinkStreamSessionNodeRuntime extends ZLinkStreamSessionNodeRuntime
417
420
  }
418
421
 
419
422
  export class ZLinkStreamBindingRuntime {
420
- private readonly routes: ZLinkActorSessionBindingRegistry<
423
+ readonly routes: ZLinkActorSessionBindingRegistry<
421
424
  DefaultZLinkSessionContext,
422
425
  DefaultZLinkSessionActor
423
426
  >;
@@ -808,19 +811,42 @@ export class ZLinkStreamBindingRuntime {
808
811
  );
809
812
  }
810
813
 
811
- createJsonReplyFrameMessage(
814
+ async submitReply(
815
+ context: DefaultZLinkSessionContext,
812
816
  requestHeader: ZLinkStreamFrameHeader,
813
817
  kind: ZLinkStreamReplyMessageKind,
814
818
  metadata: ReadonlyMap<string, string>,
815
819
  compressed: boolean,
816
820
  payload: unknown
817
- ): Message {
818
- return this.frameMessages.createJsonReplyFrameMessage(
821
+ ): Promise<ZLinkSubmitResult> {
822
+ const frame = this.frameMessages.createJsonReplyFrameMessage(
819
823
  requestHeader,
820
824
  kind,
821
825
  metadata,
822
826
  compressed,
823
827
  payload
824
828
  );
829
+ try {
830
+ return await this.routes.submitReply(context, requestHeader, async (header) => {
831
+ if (header === requestHeader) return await context.stream.submitRaw(frame);
832
+ const encoded = decodeStreamFrame(messageToBytes(frame));
833
+ const normalized = this.createBinaryMessage(
834
+ encodeStreamFrame(
835
+ {
836
+ ...decodeStreamHeader(encoded.header),
837
+ actorSlot: header.actorSlot
838
+ },
839
+ encoded.payload
840
+ )
841
+ );
842
+ try {
843
+ return await context.stream.submitRaw(normalized);
844
+ } finally {
845
+ normalized.close();
846
+ }
847
+ });
848
+ } finally {
849
+ frame.close();
850
+ }
825
851
  }
826
852
  }
@@ -478,7 +478,8 @@ export class ZLinkManagedStream implements ZLinkStream {
478
478
  throw wireReplyFailureException(
479
479
  completion.terminalResult,
480
480
  completion.failureErrno,
481
- `${operationName} failed with result ${completion.terminalResult} (errno ${completion.failureErrno}).`
481
+ completion.failureMessage ??
482
+ `${operationName} failed with result ${completion.terminalResult} (errno ${completion.failureErrno}).`
482
483
  );
483
484
  }
484
485
  } finally {
@@ -39,13 +39,13 @@ export interface ZLinkSessionCallContext {
39
39
  payload: unknown,
40
40
  correlationId?: string
41
41
  ): Message;
42
- createJsonReplyFrameMessage(
42
+ submitReply(
43
43
  requestHeader: ZLinkStreamFrameHeader,
44
44
  kind: ZLinkStreamReplyMessageKind,
45
45
  metadata: ReadonlyMap<string, string>,
46
46
  compressed: boolean,
47
47
  payload: unknown
48
- ): Message;
48
+ ): Promise<ZLinkSubmitResult>;
49
49
  claimReply(requestHeader: ZLinkStreamFrameHeader): void;
50
50
  /**
51
51
  * Spec 26 §2.2: the STREAM surface records session-connected sends and the
@@ -168,23 +168,18 @@ export class DefaultZLinkSessionReplyCall implements ZLinkSessionReplyCall {
168
168
  throw new Error('Reply is only available while handling a request packet.');
169
169
  }
170
170
  this.context.claimReply(requestHeader);
171
- const message = this.context.createJsonReplyFrameMessage(
171
+ const result = await this.context.submitReply(
172
172
  requestHeader,
173
173
  ZLinkStreamMessageKind.Response,
174
174
  new Map<string, string>(),
175
175
  this.compressionEnabled,
176
176
  this.message
177
177
  );
178
- try {
179
- const result = await this.context.stream.submitRaw(message);
180
- requireOneWayCompletion(result, 'STREAM session reply');
181
- this.context.traceFrameWritten?.(
182
- ZLinkStreamMessageKind.Response,
183
- requestHeader.name,
184
- requestHeader.correlationId
185
- );
186
- } finally {
187
- message.close();
188
- }
178
+ requireOneWayCompletion(result, 'STREAM session reply');
179
+ this.context.traceFrameWritten?.(
180
+ ZLinkStreamMessageKind.Response,
181
+ requestHeader.name,
182
+ requestHeader.correlationId
183
+ );
189
184
  }
190
185
  }
@@ -65,13 +65,14 @@ interface ZLinkSessionContextRuntime {
65
65
  payload: unknown,
66
66
  correlationId?: string
67
67
  ): Message;
68
- createJsonReplyFrameMessage(
68
+ submitReply(
69
+ context: DefaultZLinkSessionContext,
69
70
  requestHeader: ZLinkStreamFrameHeader,
70
71
  kind: ZLinkStreamReplyMessageKind,
71
72
  metadata: ReadonlyMap<string, string>,
72
73
  compressed: boolean,
73
74
  payload: unknown
74
- ): Message;
75
+ ): Promise<ZLinkSubmitResult>;
75
76
  decompressPayload(payload: Message): Message;
76
77
  bind(
77
78
  context: DefaultZLinkSessionContext,
@@ -267,20 +268,14 @@ export class DefaultZLinkSessionContext implements ZLinkSessionContext {
267
268
  );
268
269
  }
269
270
 
270
- createJsonReplyFrameMessage(
271
+ submitReply(
271
272
  requestHeader: ZLinkStreamFrameHeader,
272
273
  kind: ZLinkStreamReplyMessageKind,
273
274
  metadata: ReadonlyMap<string, string>,
274
275
  compressed: boolean,
275
276
  payload: unknown
276
- ): Message {
277
- return this.runtime.createJsonReplyFrameMessage(
278
- requestHeader,
279
- kind,
280
- metadata,
281
- compressed,
282
- payload
283
- );
277
+ ): Promise<ZLinkSubmitResult> {
278
+ return this.runtime.submitReply(this, requestHeader, kind, metadata, compressed, payload);
284
279
  }
285
280
 
286
281
  enterDispatch(header: ZLinkStreamFrameHeader): void {
@@ -1,3 +1,6 @@
1
+ import { requireOneWayCompletion } from '../messaging/submission-result';
2
+ import { logs, SeverityNumber } from '@opentelemetry/api-logs';
3
+ import { ZlinkStreamControlPacket } from '@zlink-systems/stream-wire';
1
4
  import type { RoutingId, ZLinkMessageSerializer, ZLinkSession } from '../../contracts';
2
5
  import type { Message } from '../../contracts/Common/Message';
3
6
  import type { ZLinkProviderResolver } from '../../contracts/Common/ZLinkProviderResolver';
@@ -30,6 +33,7 @@ import type {
30
33
  import type { ZLinkMeshCompletionTable } from '../backend/mesh-completion-table';
31
34
  import { ZLinkDispatchErrorReporter, ZLinkRouteDisconnectedError } from '../channels';
32
35
  import { type ZLinkRuntimeMetrics, flowIfEnabled } from '../diagnostics';
36
+ import { TELEMETRY_INSTRUMENTATION_NAME } from '../diagnostics/message-flow-record';
33
37
 
34
38
  import { createInboundFlow, runWithFlow } from '../diagnostics/flow-context';
35
39
  import { ZLinkSocketNativeEventType } from '../diagnostics/internal-event-contracts';
@@ -63,7 +67,6 @@ import { ZLinkSessionSerialExecutor } from './session-serial-executor';
63
67
  import { ownedMessage } from './stream-message-utils';
64
68
  import { normalizeStreamLiveness } from '../../contracts/Configuration/RegistrationNormalizers';
65
69
 
66
- const ZLINK_SEND_DONT_WAIT = 1;
67
70
  const ZLINK_RECV_DONT_WAIT = 1;
68
71
  const ZLINK_STREAM_RECEIVE_FRAME_BATCH_LIMIT = 64;
69
72
  const ZLINK_STREAM_ACTOR_BINDING_REPLACEMENT_CLOSE_DELAY_MS = 100;
@@ -88,6 +91,7 @@ interface ZLinkStreamLivenessOptions {
88
91
  }
89
92
 
90
93
  const MAX_TIMER_DELAY_MS = 2_147_483_647;
94
+ const STREAM_RUNTIME_LOGGER = logs.getLogger(TELEMETRY_INSTRUMENTATION_NAME);
91
95
 
92
96
  const systemLivenessClock: ZLinkStreamLivenessClock = {
93
97
  now: () => performance.now(),
@@ -583,19 +587,33 @@ export class ZLinkStreamSessionRuntime {
583
587
  }
584
588
 
585
589
  private async handleControl(header: ZLinkStreamFrameHeader, payload: Message): Promise<void> {
586
- if (messageToBytes(payload).length !== 0) {
590
+ const payloadBytes = messageToBytes(payload);
591
+ if (header.name === ZLINK_STREAM_HEARTBEAT_PING) {
592
+ if (payloadBytes.length !== 0) {
593
+ this.logIgnoredControl(header.name, payloadBytes.length);
594
+ }
595
+ await this.stream.writeControl(ZLINK_STREAM_HEARTBEAT_PONG);
596
+ return;
597
+ }
598
+ if (header.name === ZLINK_STREAM_HEARTBEAT_PONG) {
599
+ if (payloadBytes.length !== 0) {
600
+ this.logIgnoredControl(header.name, payloadBytes.length);
601
+ }
602
+ return;
603
+ }
604
+ if (
605
+ header.name === ZlinkStreamControlPacket.ActorBound ||
606
+ header.name === ZlinkStreamControlPacket.ActorUnbound
607
+ ) {
587
608
  await this.closeForLiveness(
588
609
  ZLinkStreamCloseReasonCode.ProtocolError,
589
610
  'protocol_error',
590
- 'Control heartbeat payload must be empty.'
611
+ `Unexpected stream actor control frame: ${header.name}`
591
612
  );
592
613
  return;
593
614
  }
594
- if (header.name === ZLINK_STREAM_HEARTBEAT_PONG) {
595
- return;
596
- }
597
- if (header.name === ZLINK_STREAM_HEARTBEAT_PING) {
598
- await this.stream.writeControl(ZLINK_STREAM_HEARTBEAT_PONG);
615
+ if (header.name.startsWith('$zlink.')) {
616
+ this.logIgnoredControl(header.name, payloadBytes.length);
599
617
  return;
600
618
  }
601
619
  await this.closeForLiveness(
@@ -605,6 +623,21 @@ export class ZLinkStreamSessionRuntime {
605
623
  );
606
624
  }
607
625
 
626
+ private logIgnoredControl(name: string, payloadLength: number): void {
627
+ STREAM_RUNTIME_LOGGER.emit({
628
+ eventName: 'zlink.stream.control_ignored',
629
+ timestamp: new Date(),
630
+ severityNumber: SeverityNumber.DEBUG,
631
+ severityText: 'DEBUG',
632
+ body: `Ignored STREAM control name=${name} payloadBytes=${payloadLength} peerSessionRid=${this.stream.sessionId}`,
633
+ attributes: {
634
+ control_name: name,
635
+ payload_bytes: payloadLength,
636
+ peer_session_rid: this.stream.sessionId
637
+ }
638
+ });
639
+ }
640
+
608
641
  private scheduleLivenessCheck(): void {
609
642
  if (this.disposed || this.disconnected || this.livenessTimer !== undefined) {
610
643
  return;
@@ -694,22 +727,18 @@ export class ZLinkStreamSessionRuntime {
694
727
  // record (spec 26 §2.2) and confuse the peer's reply matching.
695
728
  return;
696
729
  }
697
- const message = this.context.createJsonReplyFrameMessage(
698
- header,
699
- ZLinkStreamMessageKind.Error,
700
- new Map(),
701
- false,
702
- boundSessionErrorPayload(error)
703
- );
704
730
  try {
705
- if (!this.context.stream.writeRaw(message, ZLINK_SEND_DONT_WAIT)) {
706
- throw new Error('Client stream error reply send failed.');
707
- }
731
+ const result = await this.context.submitReply(
732
+ header,
733
+ ZLinkStreamMessageKind.Error,
734
+ new Map(),
735
+ false,
736
+ boundSessionErrorPayload(error)
737
+ );
738
+ requireOneWayCompletion(result, 'Client stream error reply');
708
739
  this.traceFrameWritten(ZLinkStreamMessageKind.Error, header.name, header.correlationId);
709
740
  } catch (replyError) {
710
741
  this.options.onError?.(replyError);
711
- } finally {
712
- message.close();
713
742
  }
714
743
  }
715
744