@olane/o-node 0.7.12-alpha.50 → 0.7.12-alpha.51

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,4 +1,4 @@
1
- import { Connection } from '@olane/o-config';
1
+ import { Connection, Stream } from '@olane/o-config';
2
2
  import { oConnection, oRequest, oResponse } from '@olane/o-core';
3
3
  import { oNodeConnectionConfig } from './interfaces/o-node-connection.config.js';
4
4
  export declare class oNodeConnection extends oConnection {
@@ -6,8 +6,10 @@ export declare class oNodeConnection extends oConnection {
6
6
  p2pConnection: Connection;
7
7
  constructor(config: oNodeConnectionConfig);
8
8
  setupConnectionListeners(): void;
9
- validate(): void;
9
+ validate(stream?: Stream): void;
10
+ getOrCreateStream(): Promise<Stream>;
10
11
  transmit(request: oRequest): Promise<oResponse>;
12
+ postTransmit(stream: Stream): Promise<void>;
11
13
  abort(error: Error): Promise<void>;
12
14
  close(): Promise<void>;
13
15
  }
@@ -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,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAEL,WAAW,EAGX,QAAQ,EACR,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AAEjF,qBAAa,eAAgB,SAAQ,WAAW;IAGlC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB;IAFrD,aAAa,EAAE,UAAU,CAAC;gBAEF,MAAM,EAAE,qBAAqB;IAM5D,wBAAwB;IAYxB,QAAQ;IAOF,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAyF/C,KAAK,CAAC,KAAK,EAAE,KAAK;IAMlB,KAAK;CAKZ"}
1
+ {"version":3,"file":"o-node-connection.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAEL,WAAW,EAGX,QAAQ,EACR,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AAEjF,qBAAa,eAAgB,SAAQ,WAAW;IAGlC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB;IAFrD,aAAa,EAAE,UAAU,CAAC;gBAEF,MAAM,EAAE,qBAAqB;IAM5D,wBAAwB;IAYxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;IAmBlB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAcpC,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IA2E/C,YAAY,CAAC,MAAM,EAAE,MAAM;IAU3B,KAAK,CAAC,KAAK,EAAE,KAAK;IAMlB,KAAK;CAKZ"}
@@ -13,30 +13,37 @@ export class oNodeConnection extends oConnection {
13
13
  this.logger.debug('Connection closed for address: ' + this.nextHopAddress.toString());
14
14
  });
15
15
  }
16
- validate() {
16
+ validate(stream) {
17
17
  if (this.config.p2pConnection.status !== 'open') {
18
18
  throw new Error('Connection is not valid');
19
19
  }
20
20
  // do nothing
21
+ if (!stream || (stream.status !== 'open' && stream.status !== 'reset')) {
22
+ throw new oError(oErrorCodes.FAILED_TO_DIAL_TARGET, 'Failed to dial target');
23
+ }
24
+ if (stream.status === 'reset') {
25
+ throw new oError(oErrorCodes.CONNECTION_LIMIT_REACHED, 'Connection limit reached');
26
+ }
27
+ }
28
+ async getOrCreateStream() {
29
+ if (this.p2pConnection.status !== 'open') {
30
+ throw new oError(oErrorCodes.INVALID_STATE, 'Connection not open');
31
+ }
32
+ return this.p2pConnection.newStream(this.nextHopAddress.protocol, {
33
+ signal: this.abortSignal,
34
+ maxOutboundStreams: process.env.MAX_OUTBOUND_STREAMS
35
+ ? parseInt(process.env.MAX_OUTBOUND_STREAMS)
36
+ : 1000,
37
+ runOnLimitedConnection: this.config.runOnLimitedConnection ?? false,
38
+ });
21
39
  }
22
40
  async transmit(request) {
23
41
  try {
24
42
  if (this.config.runOnLimitedConnection) {
25
43
  this.logger.debug('Running on limited connection...');
26
44
  }
27
- const stream = await this.p2pConnection.newStream(this.nextHopAddress.protocol, {
28
- signal: this.abortSignal,
29
- maxOutboundStreams: process.env.MAX_OUTBOUND_STREAMS
30
- ? parseInt(process.env.MAX_OUTBOUND_STREAMS)
31
- : 1000,
32
- runOnLimitedConnection: this.config.runOnLimitedConnection ?? false,
33
- });
34
- if (!stream || (stream.status !== 'open' && stream.status !== 'reset')) {
35
- throw new oError(oErrorCodes.FAILED_TO_DIAL_TARGET, 'Failed to dial target');
36
- }
37
- if (stream.status === 'reset') {
38
- throw new oError(oErrorCodes.CONNECTION_LIMIT_REACHED, 'Connection limit reached');
39
- }
45
+ const stream = await this.getOrCreateStream();
46
+ this.validate(stream);
40
47
  // Send the data with backpressure handling (libp2p v3 best practice)
41
48
  const data = new TextEncoder().encode(request.toString());
42
49
  const sent = stream.send(data);
@@ -60,17 +67,21 @@ export class oNodeConnection extends oConnection {
60
67
  this.emitter.emit('chunk', response);
61
68
  // marked as the last chunk let's close
62
69
  if (response.result._last || !response.result._isStreaming) {
63
- // this.logger.debug('Last chunk received...');
64
70
  lastResponse = response;
65
71
  // Clean up abort listener before closing
66
72
  if (this.abortSignal) {
67
73
  this.abortSignal.removeEventListener('abort', abortHandler);
68
74
  }
69
- await stream.close();
70
75
  resolve(true);
71
76
  }
72
77
  });
73
78
  });
79
+ stream.addEventListener('close', async () => {
80
+ this.logger.debug('Stream closed by remote peer, closing connection...');
81
+ stream.close().catch((error) => {
82
+ this.logger.error('Error closing stream: ', error);
83
+ });
84
+ });
74
85
  // If send() returns false, wait for the stream to drain before continuing
75
86
  if (!sent) {
76
87
  this.logger.debug('Stream buffer full, waiting for drain...');
@@ -78,9 +89,8 @@ export class oNodeConnection extends oConnection {
78
89
  signal: AbortSignal.timeout(this.config.drainTimeoutMs ?? 30000),
79
90
  }); // Default: 30 second timeout
80
91
  }
81
- if (stream.status === 'open') {
82
- await stream.abort(new Error('Connection closed'));
83
- }
92
+ // handle cleanup of the stream
93
+ await this.postTransmit(stream);
84
94
  const response = oResponse.fromJSON(lastResponse);
85
95
  return response;
86
96
  }
@@ -91,6 +101,16 @@ export class oNodeConnection extends oConnection {
91
101
  throw error;
92
102
  }
93
103
  }
104
+ async postTransmit(stream) {
105
+ if (stream.status === 'open') {
106
+ stream.close().catch((error) => {
107
+ this.logger.error('Error closing stream after transmission: ', error);
108
+ });
109
+ }
110
+ else {
111
+ this.logger.debug('Stream is not open, skipping cleanup');
112
+ }
113
+ }
94
114
  async abort(error) {
95
115
  this.logger.debug('Aborting connection');
96
116
  await this.p2pConnection.abort(error);
@@ -8,6 +8,7 @@ export declare class oNodeConnectionManager extends oConnectionManager {
8
8
  private defaultReadTimeoutMs?;
9
9
  private defaultDrainTimeoutMs?;
10
10
  constructor(config: oNodeConnectionManagerConfig);
11
+ getOrCreateConnection(nextHopAddress: oAddress, address: oAddress): Promise<Connection>;
11
12
  /**
12
13
  * Connect to a given address, reusing libp2p connections when possible
13
14
  * @param config - Connection configuration
@@ -1 +1 @@
1
- {"version":3,"file":"o-node-connection.manager.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAU,UAAU,EAAU,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,kDAAkD,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,qBAAa,sBAAuB,SAAQ,kBAAkB;IAKhD,QAAQ,CAAC,MAAM,EAAE,4BAA4B;IAJzD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,oBAAoB,CAAC,CAAS;IACtC,OAAO,CAAC,qBAAqB,CAAC,CAAS;gBAElB,MAAM,EAAE,4BAA4B;IAOzD;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC;IAgDlE;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO;IA4BpC;;;;OAIG;IACH,yBAAyB,CAAC,OAAO,EAAE,QAAQ,GAAG,UAAU,GAAG,IAAI;CA0BhE"}
1
+ {"version":3,"file":"o-node-connection.manager.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAU,UAAU,EAAU,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,kDAAkD,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,qBAAa,sBAAuB,SAAQ,kBAAkB;IAKhD,QAAQ,CAAC,MAAM,EAAE,4BAA4B;IAJzD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,oBAAoB,CAAC,CAAS;IACtC,OAAO,CAAC,qBAAqB,CAAC,CAAS;gBAElB,MAAM,EAAE,4BAA4B;IAOnD,qBAAqB,CACzB,cAAc,EAAE,QAAQ,EACxB,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,UAAU,CAAC;IA2BtB;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC;IA6BlE;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO;IA4BpC;;;;OAIG;IACH,yBAAyB,CAAC,OAAO,EAAE,QAAQ,GAAG,UAAU,GAAG,IAAI;CA0BhE"}
@@ -8,13 +8,7 @@ export class oNodeConnectionManager extends oConnectionManager {
8
8
  this.defaultReadTimeoutMs = config.defaultReadTimeoutMs;
9
9
  this.defaultDrainTimeoutMs = config.defaultDrainTimeoutMs;
10
10
  }
11
- /**
12
- * Connect to a given address, reusing libp2p connections when possible
13
- * @param config - Connection configuration
14
- * @returns The connection object
15
- */
16
- async connect(config) {
17
- const { address, nextHopAddress, callerAddress, readTimeoutMs, drainTimeoutMs, } = config;
11
+ async getOrCreateConnection(nextHopAddress, address) {
18
12
  // Check if libp2p already has an active connection to this peer
19
13
  const existingConnection = this.getCachedLibp2pConnection(nextHopAddress);
20
14
  let p2pConnection;
@@ -27,6 +21,16 @@ export class oNodeConnectionManager extends oConnectionManager {
27
21
  this.logger.debug('Dialing new connection for address: ' + address.toString());
28
22
  p2pConnection = await this.p2pNode.dial(nextHopAddress.libp2pTransports.map((ma) => ma.toMultiaddr()));
29
23
  }
24
+ return p2pConnection;
25
+ }
26
+ /**
27
+ * Connect to a given address, reusing libp2p connections when possible
28
+ * @param config - Connection configuration
29
+ * @returns The connection object
30
+ */
31
+ async connect(config) {
32
+ const { address, nextHopAddress, callerAddress, readTimeoutMs, drainTimeoutMs, } = config;
33
+ const p2pConnection = await this.getOrCreateConnection(nextHopAddress, address);
30
34
  const connection = new oNodeConnection({
31
35
  nextHopAddress: nextHopAddress,
32
36
  address: address,
@@ -1 +1 @@
1
- {"version":3,"file":"o-node.tool.d.ts","sourceRoot":"","sources":["../../src/o-node.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAGR,QAAQ,EAIT,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;;AAIrD;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,cAAkB;IACzC,cAAc,CAAC,OAAO,EAAE,QAAQ;IAUhC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAwCnE,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAQ9B,oBAAoB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;CA2B5D"}
1
+ {"version":3,"file":"o-node.tool.d.ts","sourceRoot":"","sources":["../../src/o-node.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAGR,QAAQ,EAIT,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;;AAIrD;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,cAAkB;IACzC,cAAc,CAAC,OAAO,EAAE,QAAQ;IAUhC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA+CnE,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAQ9B,oBAAoB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;CA2B5D"}
@@ -54,6 +54,12 @@ export class oNodeTool extends oTool(oServerNode) {
54
54
  };
55
55
  // Attach listener synchronously before any async operations
56
56
  stream.addEventListener('message', messageHandler);
57
+ stream.addEventListener('close', () => {
58
+ this.logger.debug('Stream closed by remote peer');
59
+ stream.close().catch((error) => {
60
+ this.logger.error('Error closing stream: ', error);
61
+ });
62
+ });
57
63
  }
58
64
  async _tool_identify() {
59
65
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olane/o-node",
3
- "version": "0.7.12-alpha.50",
3
+ "version": "0.7.12-alpha.51",
4
4
  "type": "module",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -54,12 +54,12 @@
54
54
  "typescript": "5.4.5"
55
55
  },
56
56
  "dependencies": {
57
- "@olane/o-config": "0.7.12-alpha.50",
58
- "@olane/o-core": "0.7.12-alpha.50",
59
- "@olane/o-protocol": "0.7.12-alpha.50",
60
- "@olane/o-tool": "0.7.12-alpha.50",
57
+ "@olane/o-config": "0.7.12-alpha.51",
58
+ "@olane/o-core": "0.7.12-alpha.51",
59
+ "@olane/o-protocol": "0.7.12-alpha.51",
60
+ "@olane/o-tool": "0.7.12-alpha.51",
61
61
  "debug": "^4.4.1",
62
62
  "dotenv": "^16.5.0"
63
63
  },
64
- "gitHead": "b39adebc281eb6f08e49985b8d85c84ce331e76a"
64
+ "gitHead": "b877e1e95a2bf32845ec30072eb72422fd25aba7"
65
65
  }