@olane/o-node 0.7.52 → 0.7.54

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.
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Message sent by limited connection clients to identify their dedicated reader stream
3
- * This allows the receiver to identify which stream to use for sending requests back to the caller
2
+ * Message sent by limited connection clients to identify their dedicated persistent streams
3
+ * This allows the receiver to identify which streams to use for bidirectional communication
4
4
  */
5
5
  export interface StreamInitMessage {
6
6
  /**
@@ -9,10 +9,11 @@ export interface StreamInitMessage {
9
9
  type: 'stream-init';
10
10
  /**
11
11
  * Role of this stream
12
- * - 'reader': Dedicated reader stream for receiving requests
12
+ * - 'reader': Dedicated reader stream for receiving requests from receiver
13
+ * - 'writer': Dedicated writer stream for sending responses back to receiver
13
14
  * - 'standard': Standard request-response stream
14
15
  */
15
- role: 'reader' | 'standard';
16
+ role: 'reader' | 'writer' | 'standard';
16
17
  /**
17
18
  * Timestamp when the stream was created
18
19
  */
@@ -26,4 +27,38 @@ export interface StreamInitMessage {
26
27
  * Type guard to check if a message is a StreamInitMessage
27
28
  */
28
29
  export declare function isStreamInitMessage(message: any): message is StreamInitMessage;
30
+ /**
31
+ * Acknowledgment message sent by receiver in response to stream-init
32
+ * This confirms that the receiver has processed and registered the stream
33
+ */
34
+ export interface StreamInitAckMessage {
35
+ /**
36
+ * Message type identifier
37
+ */
38
+ type: 'stream-init-ack';
39
+ /**
40
+ * Status of the initialization
41
+ */
42
+ status: 'success' | 'error';
43
+ /**
44
+ * The stream ID that was registered
45
+ */
46
+ streamId: string;
47
+ /**
48
+ * The role that was registered
49
+ */
50
+ role: 'reader' | 'writer' | 'standard';
51
+ /**
52
+ * Optional error message if status is 'error'
53
+ */
54
+ error?: string;
55
+ /**
56
+ * Timestamp when the ack was sent
57
+ */
58
+ timestamp: number;
59
+ }
60
+ /**
61
+ * Type guard to check if a message is a StreamInitAckMessage
62
+ */
63
+ export declare function isStreamInitAckMessage(message: any): message is StreamInitAckMessage;
29
64
  //# sourceMappingURL=stream-init-message.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream-init-message.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/stream-init-message.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,IAAI,EAAE,aAAa,CAAC;IAEpB;;;;OAIG;IACH,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IAE5B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,IAAI,iBAAiB,CAM9E"}
1
+ {"version":3,"file":"stream-init-message.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/stream-init-message.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,IAAI,EAAE,aAAa,CAAC;IAEpB;;;;;OAKG;IACH,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;IAEvC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,IAAI,iBAAiB,CAM9E;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,IAAI,EAAE,iBAAiB,CAAC;IAExB;;OAEG;IACH,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAE5B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;IAEvC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,GAAG,GACX,OAAO,IAAI,oBAAoB,CAQjC"}
@@ -3,6 +3,16 @@
3
3
  */
4
4
  export function isStreamInitMessage(message) {
5
5
  return (message?.type === 'stream-init' &&
6
- (message.role === 'reader' || message.role === 'standard') &&
6
+ (message.role === 'reader' || message.role === 'writer' || message.role === 'standard') &&
7
+ typeof message.timestamp === 'number');
8
+ }
9
+ /**
10
+ * Type guard to check if a message is a StreamInitAckMessage
11
+ */
12
+ export function isStreamInitAckMessage(message) {
13
+ return (message?.type === 'stream-init-ack' &&
14
+ (message.status === 'success' || message.status === 'error') &&
15
+ typeof message.streamId === 'string' &&
16
+ (message.role === 'reader' || message.role === 'writer' || message.role === 'standard') &&
7
17
  typeof message.timestamp === 'number');
8
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"o-node-connection.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAU,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAEL,WAAW,EAGX,QAAQ,EACR,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,qBAAa,eAAgB,SAAQ,WAAW;IAKlC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB;IAJrD,aAAa,EAAE,UAAU,CAAC;IACjC,SAAS,CAAC,WAAW,EAAE,iBAAiB,CAAC;IAClC,aAAa,EAAE,kBAAkB,CAAC;gBAEV,MAAM,EAAE,qBAAqB;IAW5D,IAAI,YAAY,qCAEf;IAED,IAAI,UAAU,wCAEb;IAED;;OAEG;IACH,IAAI,gBAAgB,IAAI,qBAAqB,CAE5C;IAED,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO;IAM/C,IAAI,OAAO,IAAI,WAAW,EAAE,CAE3B;IAEK,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IA2D/C,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhD,KAAK,CAAC,KAAK,EAAE,KAAK;IAMlB,KAAK;CASZ"}
1
+ {"version":3,"file":"o-node-connection.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAU,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAEL,WAAW,EAGX,QAAQ,EACR,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,qBAAa,eAAgB,SAAQ,WAAW;IAKlC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB;IAJrD,aAAa,EAAE,UAAU,CAAC;IACjC,SAAS,CAAC,WAAW,EAAE,iBAAiB,CAAC;IAClC,aAAa,EAAE,kBAAkB,CAAC;gBAEV,MAAM,EAAE,qBAAqB;IAW5D,IAAI,YAAY,qCAEf;IAED,IAAI,UAAU,wCAEb;IAED;;OAEG;IACH,IAAI,gBAAgB,IAAI,qBAAqB,CAE5C;IAED,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO;IAM/C,IAAI,OAAO,IAAI,WAAW,EAAE,CAE3B;IAEK,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAkF/C,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhD,KAAK,CAAC,KAAK,EAAE,KAAK;IAMlB,KAAK;CASZ"}
@@ -36,6 +36,7 @@ export class oNodeConnection extends oConnection {
36
36
  // Build protocol string
37
37
  const protocol = this.nextHopAddress.protocol +
38
38
  (this.reusePolicy === 'reuse' ? '/reuse' : '');
39
+ this.logger.debug('Transmitting request on limited connection?', this.config.runOnLimitedConnection);
39
40
  const streamConfig = {
40
41
  signal: this.abortSignal,
41
42
  drainTimeoutMs: this.config.drainTimeoutMs,
@@ -43,7 +44,7 @@ export class oNodeConnection extends oConnection {
43
44
  maxOutboundStreams: process.env.MAX_OUTBOUND_STREAMS
44
45
  ? parseInt(process.env.MAX_OUTBOUND_STREAMS)
45
46
  : 1000,
46
- runOnLimitedConnection: this.config.runOnLimitedConnection ?? true,
47
+ runOnLimitedConnection: this.config.runOnLimitedConnection ?? false,
47
48
  };
48
49
  // Get stream from StreamManager
49
50
  const wrappedStream = await this.streamManager.getOrCreateStream(protocol, this.nextHopAddress, streamConfig);
@@ -53,9 +54,27 @@ export class oNodeConnection extends oConnection {
53
54
  // Send the request with backpressure handling
54
55
  const data = new TextEncoder().encode(request.toString());
55
56
  await this.streamManager.sendLengthPrefixed(stream, data, streamConfig);
57
+ // Determine which stream to wait for response on
58
+ // If _streamId is specified, use that stream (for limited connections with persistent writer stream)
59
+ let responseStream = stream;
60
+ if (request.params._streamId) {
61
+ const specifiedStream = this.streamManager.getStreamById(request.params._streamId);
62
+ if (specifiedStream) {
63
+ responseStream = specifiedStream;
64
+ this.logger.debug('Using specified stream for response', {
65
+ requestStreamId: stream.id,
66
+ responseStreamId: specifiedStream.id,
67
+ });
68
+ }
69
+ else {
70
+ this.logger.warn('Specified response stream not found, using request stream', {
71
+ streamId: request.params._streamId,
72
+ });
73
+ }
74
+ }
56
75
  // Handle response using StreamManager
57
76
  // Pass request ID to enable proper response correlation on shared streams
58
- const response = await this.streamManager.handleOutgoingStream(stream, this.emitter, streamConfig, request.id);
77
+ const response = await this.streamManager.handleOutgoingStream(responseStream, this.emitter, streamConfig, request.id);
59
78
  // Handle cleanup of the stream
60
79
  await this.postTransmit(wrappedStream);
61
80
  return response;
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  import { EventEmitter } from 'events';
3
3
  import type { Connection, Stream } from '@libp2p/interface';
4
- import { oObject, oResponse } from '@olane/o-core';
4
+ import { oObject, oRequest, oResponse } from '@olane/o-core';
5
5
  import type { oRouterRequest, oConnection } from '@olane/o-core';
6
6
  import { oNodeStream } from './o-node-stream.js';
7
7
  import { StreamManagerConfig } from './interfaces/stream-manager.config.js';
@@ -21,10 +21,11 @@ export declare class oNodeStreamManager extends oObject {
21
21
  readonly config: StreamManagerConfig;
22
22
  private streams;
23
23
  protected eventEmitter: EventEmitter;
24
- protected isInitialized: boolean;
24
+ isInitialized: boolean;
25
25
  private p2pConnection;
26
26
  private activeStreamHandlers;
27
27
  protected callerReaderStream?: Stream;
28
+ protected callerWriterStream?: Stream;
28
29
  constructor(config: StreamManagerConfig);
29
30
  /**
30
31
  * Initialize the stream manager
@@ -65,6 +66,14 @@ export declare class oNodeStreamManager extends oObject {
65
66
  * @returns Array of wrapped streams
66
67
  */
67
68
  getAllStreams(): oNodeStream[];
69
+ /**
70
+ * Gets a stream by its ID
71
+ * Checks persistent caller streams (reader/writer) and tracked streams
72
+ *
73
+ * @param streamId - The ID of the stream to retrieve
74
+ * @returns The libp2p Stream or undefined if not found
75
+ */
76
+ getStreamById(streamId: string): Stream | undefined;
68
77
  /**
69
78
  * Emits an async event and waits for the first listener to return a result
70
79
  * This enables event-based request handling with async responses
@@ -88,11 +97,12 @@ export declare class oNodeStreamManager extends oObject {
88
97
  /**
89
98
  * Handles a stream initialization message
90
99
  * Stores reference to caller's reader stream for bidirectional communication
100
+ * Sends acknowledgment back to confirm stream registration
91
101
  *
92
102
  * @param message - The decoded stream init message
93
103
  * @param stream - The stream that sent the message
94
104
  */
95
- protected handleStreamInitMessage(message: StreamInitMessage, stream: Stream): void;
105
+ protected handleStreamInitMessage(message: StreamInitMessage, stream: Stream): Promise<void>;
96
106
  /**
97
107
  * Extracts and parses JSON from various formats including:
98
108
  * - Already parsed objects
@@ -105,7 +115,7 @@ export declare class oNodeStreamManager extends oObject {
105
115
  * @returns Parsed JSON object
106
116
  * @throws Error if JSON parsing fails even with JSON5 fallback
107
117
  */
108
- private extractAndParseJSON;
118
+ protected extractAndParseJSON(decoded: string | any): any;
109
119
  /**
110
120
  * Sends data through a stream using length-prefixed encoding (libp2p v3 best practice)
111
121
  * Each message is automatically prefixed with a varint indicating the message length
@@ -133,6 +143,15 @@ export declare class oNodeStreamManager extends oObject {
133
143
  * @param connection - The connection the stream belongs to
134
144
  */
135
145
  handleIncomingStream(stream: Stream, connection: Connection): Promise<void>;
146
+ /**
147
+ * Determines which stream to use for sending the response
148
+ * Checks for _streamId in request params and routes accordingly
149
+ *
150
+ * @param request - The incoming request
151
+ * @param defaultStream - The stream the request came on (fallback)
152
+ * @returns The stream to use for the response
153
+ */
154
+ protected getResponseStream(request: oRequest, defaultStream: Stream): Stream;
136
155
  /**
137
156
  * Handles a request message by emitting an event and sending response
138
157
  *
@@ -140,7 +159,7 @@ export declare class oNodeStreamManager extends oObject {
140
159
  * @param stream - The stream to send the response on
141
160
  * @param connection - The connection the stream belongs to
142
161
  */
143
- private handleRequestMessage;
162
+ protected handleRequestMessage(message: any, stream: Stream, connection: Connection): Promise<void>;
144
163
  /**
145
164
  * Handles an outgoing stream on the client side using length-prefixed protocol
146
165
  * Uses async read loops to process responses with proper message boundaries
@@ -1 +1 @@
1
- {"version":3,"file":"o-node-stream.manager.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-stream.manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"o-node-stream.manager.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-stream.manager.ts"],"names":[],"mappings":"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"}
@@ -100,7 +100,7 @@ export class oNodeStreamManager extends oObject {
100
100
  const stream = await this.p2pConnection.newStream(protocol, {
101
101
  signal: config.signal,
102
102
  maxOutboundStreams: config.maxOutboundStreams ?? 1000,
103
- runOnLimitedConnection: config.runOnLimitedConnection ?? false,
103
+ runOnLimitedConnection: config.runOnLimitedConnection ?? true,
104
104
  });
105
105
  // Wrap in oNodeStream with metadata
106
106
  const wrappedStream = new oNodeStream(stream, {
@@ -157,6 +157,26 @@ export class oNodeStreamManager extends oObject {
157
157
  getAllStreams() {
158
158
  return Array.from(this.streams.values());
159
159
  }
160
+ /**
161
+ * Gets a stream by its ID
162
+ * Checks persistent caller streams (reader/writer) and tracked streams
163
+ *
164
+ * @param streamId - The ID of the stream to retrieve
165
+ * @returns The libp2p Stream or undefined if not found
166
+ */
167
+ getStreamById(streamId) {
168
+ // Check caller writer stream
169
+ if (this.callerWriterStream?.id === streamId) {
170
+ return this.callerWriterStream;
171
+ }
172
+ // Check caller reader stream
173
+ if (this.callerReaderStream?.id === streamId) {
174
+ return this.callerReaderStream;
175
+ }
176
+ // Check tracked streams
177
+ const wrappedStream = this.streams.get(streamId);
178
+ return wrappedStream?.p2pStream;
179
+ }
160
180
  /**
161
181
  * Emits an async event and waits for the first listener to return a result
162
182
  * This enables event-based request handling with async responses
@@ -194,23 +214,72 @@ export class oNodeStreamManager extends oObject {
194
214
  /**
195
215
  * Handles a stream initialization message
196
216
  * Stores reference to caller's reader stream for bidirectional communication
217
+ * Sends acknowledgment back to confirm stream registration
197
218
  *
198
219
  * @param message - The decoded stream init message
199
220
  * @param stream - The stream that sent the message
200
221
  */
201
- handleStreamInitMessage(message, stream) {
202
- if (message.role === 'reader') {
203
- this.callerReaderStream = stream;
204
- this.logger.info('Identified caller reader stream', {
222
+ async handleStreamInitMessage(message, stream) {
223
+ try {
224
+ if (message.role === 'reader') {
225
+ this.callerReaderStream = stream;
226
+ this.logger.info('Identified caller reader stream', {
227
+ streamId: stream.id,
228
+ connectionId: message.connectionId,
229
+ });
230
+ this.emit(StreamManagerEvent.StreamIdentified, {
231
+ streamId: stream.id,
232
+ role: message.role,
233
+ connectionId: message.connectionId,
234
+ });
235
+ }
236
+ else if (message.role === 'writer') {
237
+ this.callerWriterStream = stream;
238
+ this.logger.info('Identified caller writer stream', {
239
+ streamId: stream.id,
240
+ connectionId: message.connectionId,
241
+ });
242
+ this.emit(StreamManagerEvent.StreamIdentified, {
243
+ streamId: stream.id,
244
+ role: message.role,
245
+ connectionId: message.connectionId,
246
+ });
247
+ }
248
+ // Send acknowledgment back to caller
249
+ const ackMessage = {
250
+ type: 'stream-init-ack',
251
+ status: 'success',
205
252
  streamId: stream.id,
206
- connectionId: message.connectionId,
207
- });
208
- this.emit(StreamManagerEvent.StreamIdentified, {
253
+ role: message.role,
254
+ timestamp: Date.now(),
255
+ };
256
+ const ackBytes = new TextEncoder().encode(JSON.stringify(ackMessage));
257
+ await this.sendLengthPrefixed(stream, ackBytes, {});
258
+ this.logger.debug('Sent stream-init-ack', {
209
259
  streamId: stream.id,
210
260
  role: message.role,
211
- connectionId: message.connectionId,
212
261
  });
213
262
  }
263
+ catch (error) {
264
+ this.logger.error('Failed to process stream-init message', error);
265
+ // Try to send error acknowledgment
266
+ try {
267
+ const errorAck = {
268
+ type: 'stream-init-ack',
269
+ status: 'error',
270
+ streamId: stream.id,
271
+ role: message.role,
272
+ error: error.message,
273
+ timestamp: Date.now(),
274
+ };
275
+ const errorAckBytes = new TextEncoder().encode(JSON.stringify(errorAck));
276
+ await this.sendLengthPrefixed(stream, errorAckBytes, {});
277
+ }
278
+ catch (ackError) {
279
+ this.logger.error('Failed to send error acknowledgment', ackError);
280
+ }
281
+ throw error;
282
+ }
214
283
  }
215
284
  /**
216
285
  * Extracts and parses JSON from various formats including:
@@ -301,7 +370,7 @@ export class oNodeStreamManager extends oObject {
301
370
  // Parse JSON (handles markdown blocks, mixed content, and JSON5)
302
371
  const message = this.extractAndParseJSON(decoded);
303
372
  if (this.isStreamInit(message)) {
304
- this.handleStreamInitMessage(message, stream);
373
+ await this.handleStreamInitMessage(message, stream);
305
374
  // Continue reading for subsequent messages on this stream
306
375
  }
307
376
  else if (this.isRequest(message)) {
@@ -330,6 +399,42 @@ export class oNodeStreamManager extends oObject {
330
399
  this.untrackStreamHandler(stream.id);
331
400
  }
332
401
  }
402
+ /**
403
+ * Determines which stream to use for sending the response
404
+ * Checks for _streamId in request params and routes accordingly
405
+ *
406
+ * @param request - The incoming request
407
+ * @param defaultStream - The stream the request came on (fallback)
408
+ * @returns The stream to use for the response
409
+ */
410
+ getResponseStream(request, defaultStream) {
411
+ const streamId = request.params._streamId;
412
+ // If no explicit response stream specified, use the request stream (backward compatibility)
413
+ if (!streamId) {
414
+ return defaultStream;
415
+ }
416
+ // Check if the response stream is the identified caller writer stream
417
+ if (this.callerWriterStream && this.callerWriterStream.id === streamId) {
418
+ this.logger.debug('Routing response to caller writer stream', {
419
+ requestId: request.id,
420
+ streamId,
421
+ });
422
+ return this.callerWriterStream;
423
+ }
424
+ if (this.callerReaderStream && this.callerReaderStream.id === streamId) {
425
+ this.logger.debug('Routing response to caller reader stream', {
426
+ requestId: request.id,
427
+ streamId,
428
+ });
429
+ return this.callerReaderStream;
430
+ }
431
+ // If specified stream not found, warn and fall back to request stream
432
+ this.logger.warn('Specified response stream not found, using request stream', {
433
+ requestId: request.id,
434
+ streamId,
435
+ });
436
+ return defaultStream;
437
+ }
333
438
  /**
334
439
  * Handles a request message by emitting an event and sending response
335
440
  *
@@ -340,6 +445,8 @@ export class oNodeStreamManager extends oObject {
340
445
  async handleRequestMessage(message, stream, connection) {
341
446
  const request = new oRequest(message);
342
447
  const responseBuilder = ResponseBuilder.create();
448
+ // Determine which stream to use for the response
449
+ const responseStream = this.getResponseStream(request, stream);
343
450
  try {
344
451
  // Emit InboundRequest event and wait for handler to process
345
452
  const result = await this.emitAsync(StreamManagerEvent.InboundRequest, {
@@ -348,13 +455,13 @@ export class oNodeStreamManager extends oObject {
348
455
  connection,
349
456
  });
350
457
  const response = await responseBuilder.build(request, result, null);
351
- await CoreUtils.sendResponse(response, stream);
458
+ await CoreUtils.sendResponse(response, responseStream);
352
459
  this.logger.debug(`Successfully processed request: method=${request.method}, id=${request.id}`);
353
460
  }
354
461
  catch (error) {
355
462
  this.logger.error(`Error processing request: method=${request.method}, id=${request.id}`, error);
356
463
  const errorResponse = await responseBuilder.buildError(request, error);
357
- await CoreUtils.sendResponse(errorResponse, stream);
464
+ await CoreUtils.sendResponse(errorResponse, responseStream);
358
465
  this.emit(StreamManagerEvent.StreamError, {
359
466
  streamId: stream.id,
360
467
  error: error instanceof Error ? error : new Error(String(error)),
@@ -5,6 +5,7 @@ export declare enum StreamManagerEvent {
5
5
  ManagerInitialized = "manager-initialized",
6
6
  ManagerClosed = "manager-closed",
7
7
  ReaderStarted = "reader-started",
8
+ WriterStarted = "writer-started",
8
9
  ReaderFailed = "reader-failed",
9
10
  ReaderRecovered = "reader-recovered",
10
11
  RecoveryFailed = "recovery-failed",
@@ -23,6 +24,9 @@ export interface InitializedData {
23
24
  export interface ReaderStartedData {
24
25
  streamId: string;
25
26
  }
27
+ export interface WriterStartedData {
28
+ streamId: string;
29
+ }
26
30
  export interface ReaderFailedData {
27
31
  error?: string;
28
32
  failureCount: number;
@@ -46,7 +50,7 @@ export interface StreamFailedData {
46
50
  }
47
51
  export interface StreamIdentifiedData {
48
52
  streamId: string;
49
- role: 'reader' | 'standard';
53
+ role: 'reader' | 'writer' | 'standard';
50
54
  connectionId?: string;
51
55
  }
52
56
  export interface InboundRequestData {
@@ -70,6 +74,7 @@ export type StreamManagerEventData = {
70
74
  [StreamManagerEvent.ManagerInitialized]: InitializedData;
71
75
  [StreamManagerEvent.ManagerClosed]: void;
72
76
  [StreamManagerEvent.ReaderStarted]: ReaderStartedData;
77
+ [StreamManagerEvent.WriterStarted]: WriterStartedData;
73
78
  [StreamManagerEvent.ReaderFailed]: ReaderFailedData;
74
79
  [StreamManagerEvent.ReaderRecovered]: ReaderRecoveredData;
75
80
  [StreamManagerEvent.RecoveryFailed]: RecoveryFailedData;
@@ -1 +1 @@
1
- {"version":3,"file":"stream-manager.events.d.ts","sourceRoot":"","sources":["../../../src/connection/stream-manager.events.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,kBAAkB;IAC5B,kBAAkB,wBAAwB;IAC1C,aAAa,mBAAmB;IAChC,aAAa,mBAAmB;IAChC,YAAY,kBAAkB;IAC9B,eAAe,qBAAqB;IACpC,cAAc,oBAAoB;IAClC,cAAc,oBAAoB;IAClC,YAAY,kBAAkB;IAC9B,gBAAgB,sBAAsB;IACtC,cAAc,oBAAoB;IAClC,eAAe,qBAAqB;IACpC,WAAW,iBAAiB;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;CAAG;AAEnC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,GAAG,CAAC;IACb,MAAM,EAAE,GAAG,CAAC;IACZ,UAAU,EAAE,GAAG,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,GAAG,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,EAAE,eAAe,CAAC;IACzD,CAAC,kBAAkB,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC;IACzC,CAAC,kBAAkB,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IACtD,CAAC,kBAAkB,CAAC,YAAY,CAAC,EAAE,gBAAgB,CAAC;IACpD,CAAC,kBAAkB,CAAC,eAAe,CAAC,EAAE,mBAAmB,CAAC;IAC1D,CAAC,kBAAkB,CAAC,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACxD,CAAC,kBAAkB,CAAC,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACxD,CAAC,kBAAkB,CAAC,YAAY,CAAC,EAAE,gBAAgB,CAAC;IACpD,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IAC5D,CAAC,kBAAkB,CAAC,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACxD,CAAC,kBAAkB,CAAC,eAAe,CAAC,EAAE,mBAAmB,CAAC;IAC1D,CAAC,kBAAkB,CAAC,WAAW,CAAC,EAAE,eAAe,CAAC;CACnD,CAAC"}
1
+ {"version":3,"file":"stream-manager.events.d.ts","sourceRoot":"","sources":["../../../src/connection/stream-manager.events.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,kBAAkB;IAC5B,kBAAkB,wBAAwB;IAC1C,aAAa,mBAAmB;IAChC,aAAa,mBAAmB;IAChC,aAAa,mBAAmB;IAChC,YAAY,kBAAkB;IAC9B,eAAe,qBAAqB;IACpC,cAAc,oBAAoB;IAClC,cAAc,oBAAoB;IAClC,YAAY,kBAAkB;IAC9B,gBAAgB,sBAAsB;IACtC,cAAc,oBAAoB;IAClC,eAAe,qBAAqB;IACpC,WAAW,iBAAiB;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;CAAG;AAEnC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,GAAG,CAAC;IACb,MAAM,EAAE,GAAG,CAAC;IACZ,UAAU,EAAE,GAAG,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,GAAG,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,EAAE,eAAe,CAAC;IACzD,CAAC,kBAAkB,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC;IACzC,CAAC,kBAAkB,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IACtD,CAAC,kBAAkB,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IACtD,CAAC,kBAAkB,CAAC,YAAY,CAAC,EAAE,gBAAgB,CAAC;IACpD,CAAC,kBAAkB,CAAC,eAAe,CAAC,EAAE,mBAAmB,CAAC;IAC1D,CAAC,kBAAkB,CAAC,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACxD,CAAC,kBAAkB,CAAC,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACxD,CAAC,kBAAkB,CAAC,YAAY,CAAC,EAAE,gBAAgB,CAAC;IACpD,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IAC5D,CAAC,kBAAkB,CAAC,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACxD,CAAC,kBAAkB,CAAC,eAAe,CAAC,EAAE,mBAAmB,CAAC;IAC1D,CAAC,kBAAkB,CAAC,WAAW,CAAC,EAAE,eAAe,CAAC;CACnD,CAAC"}
@@ -6,6 +6,7 @@ export var StreamManagerEvent;
6
6
  StreamManagerEvent["ManagerInitialized"] = "manager-initialized";
7
7
  StreamManagerEvent["ManagerClosed"] = "manager-closed";
8
8
  StreamManagerEvent["ReaderStarted"] = "reader-started";
9
+ StreamManagerEvent["WriterStarted"] = "writer-started";
9
10
  StreamManagerEvent["ReaderFailed"] = "reader-failed";
10
11
  StreamManagerEvent["ReaderRecovered"] = "reader-recovered";
11
12
  StreamManagerEvent["RecoveryFailed"] = "recovery-failed";
@@ -25,7 +25,7 @@ export class oNodeTool extends oTool(oServerNode) {
25
25
  await this.p2pNode.handle(reuseProtocol, this.handleStreamReuse.bind(this), {
26
26
  maxInboundStreams: 10000,
27
27
  maxOutboundStreams: maxOutboundsStreams,
28
- runOnLimitedConnection: this.config.runOnLimitedConnection,
28
+ runOnLimitedConnection: true, // reuse is always on limited connections
29
29
  });
30
30
  this.logger.debug('Handled protocol reuse: ' + reuseProtocol);
31
31
  }
@@ -74,7 +74,7 @@ export class oNodeTool extends oTool(oServerNode) {
74
74
  currentNode: this,
75
75
  connection: connection,
76
76
  });
77
- this.connectionManager.answer({
77
+ await this.connectionManager.answer({
78
78
  nextHopAddress: remoteAddress,
79
79
  address: remoteAddress,
80
80
  callerAddress: this.address,
@@ -21,7 +21,7 @@ describe('Parent-Child Registration', () => {
21
21
  await builder.startNode('o://child');
22
22
  // Verify child is in parent's hierarchy manager
23
23
  const children = leader.getChildren();
24
- console.log('Leader status:', leader.state);
24
+ console.log('Children', children);
25
25
  expect(children).to.have.lengthOf(1);
26
26
  expect(children[0].toString()).to.include('child');
27
27
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olane/o-node",
3
- "version": "0.7.52",
3
+ "version": "0.7.54",
4
4
  "type": "module",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -40,7 +40,7 @@
40
40
  "devDependencies": {
41
41
  "@eslint/eslintrc": "^3.3.1",
42
42
  "@eslint/js": "^9.29.0",
43
- "@olane/o-test": "0.7.52",
43
+ "@olane/o-test": "0.7.54",
44
44
  "@tsconfig/node20": "^20.1.6",
45
45
  "@types/jest": "^30.0.0",
46
46
  "@types/json5": "^2.2.0",
@@ -60,13 +60,13 @@
60
60
  "typescript": "5.4.5"
61
61
  },
62
62
  "dependencies": {
63
- "@olane/o-config": "0.7.52",
64
- "@olane/o-core": "0.7.52",
65
- "@olane/o-protocol": "0.7.52",
66
- "@olane/o-tool": "0.7.52",
63
+ "@olane/o-config": "0.7.54",
64
+ "@olane/o-core": "0.7.54",
65
+ "@olane/o-protocol": "0.7.54",
66
+ "@olane/o-tool": "0.7.54",
67
67
  "debug": "^4.4.1",
68
68
  "dotenv": "^16.5.0",
69
69
  "json5": "^2.2.3"
70
70
  },
71
- "gitHead": "706ee0d5b546e96b6c05270b39035ee7e08dadbd"
71
+ "gitHead": "8e527a1481c6aeaf0840ea30198500a9baef1e98"
72
72
  }