@olane/o-node 0.7.40 → 0.7.41

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 (45) hide show
  1. package/dist/src/connection/index.d.ts +1 -1
  2. package/dist/src/connection/index.d.ts.map +1 -1
  3. package/dist/src/connection/index.js +1 -1
  4. package/dist/src/connection/interfaces/o-node-connection-stream.config.d.ts +8 -0
  5. package/dist/src/connection/interfaces/o-node-connection-stream.config.d.ts.map +1 -0
  6. package/dist/src/connection/interfaces/o-node-connection-stream.config.js +1 -0
  7. package/dist/src/connection/o-node-connection-stream.d.ts +34 -0
  8. package/dist/src/connection/o-node-connection-stream.d.ts.map +1 -0
  9. package/dist/src/connection/o-node-connection-stream.js +68 -0
  10. package/dist/src/connection/o-node-connection.d.ts +10 -4
  11. package/dist/src/connection/o-node-connection.d.ts.map +1 -1
  12. package/dist/src/connection/o-node-connection.js +51 -34
  13. package/dist/src/connection/o-node-connection.manager.d.ts +4 -0
  14. package/dist/src/connection/o-node-connection.manager.d.ts.map +1 -1
  15. package/dist/src/connection/o-node-connection.manager.js +24 -0
  16. package/dist/src/connection/stream-handler.d.ts +1 -59
  17. package/dist/src/connection/stream-handler.d.ts.map +1 -1
  18. package/dist/src/connection/stream-handler.js +104 -179
  19. package/dist/src/o-node.tool.d.ts +3 -1
  20. package/dist/src/o-node.tool.d.ts.map +1 -1
  21. package/dist/src/o-node.tool.js +44 -11
  22. package/dist/src/router/o-node.address.d.ts +1 -0
  23. package/dist/src/router/o-node.address.d.ts.map +1 -1
  24. package/dist/src/router/o-node.address.js +4 -0
  25. package/dist/src/utils/connection.utils.d.ts +9 -0
  26. package/dist/src/utils/connection.utils.d.ts.map +1 -0
  27. package/dist/src/utils/connection.utils.js +26 -0
  28. package/dist/src/utils/index.d.ts +1 -0
  29. package/dist/src/utils/index.d.ts.map +1 -1
  30. package/dist/src/utils/index.js +1 -0
  31. package/dist/test/astream-reuse.spec.d.ts +2 -0
  32. package/dist/test/astream-reuse.spec.d.ts.map +1 -0
  33. package/dist/test/astream-reuse.spec.js +107 -0
  34. package/dist/test/connection-management.spec.js +1 -0
  35. package/dist/test/helpers/network-builder.d.ts.map +1 -1
  36. package/package.json +7 -7
  37. package/dist/src/connection/o-managed-stream.d.ts +0 -57
  38. package/dist/src/connection/o-managed-stream.d.ts.map +0 -1
  39. package/dist/src/connection/o-managed-stream.js +0 -76
  40. package/dist/test/o-managed-stream.spec.d.ts +0 -2
  41. package/dist/test/o-managed-stream.spec.d.ts.map +0 -1
  42. package/dist/test/o-managed-stream.spec.js +0 -122
  43. package/dist/test/stream-handler-caching.spec.d.ts +0 -2
  44. package/dist/test/stream-handler-caching.spec.d.ts.map +0 -1
  45. package/dist/test/stream-handler-caching.spec.js +0 -261
@@ -1 +1 @@
1
- {"version":3,"file":"network-builder.d.ts","sourceRoot":"","sources":["../../../test/helpers/network-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAC7E,OAAO,EAAY,QAAQ,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;GAEG;AACH,qBAAa,QAAS,SAAQ,SAAS;IAC9B,SAAS,SAAK;gBAET,MAAM,EAAE,eAAe,GAAG;QAAE,OAAO,EAAE,YAAY,CAAA;KAAE;IAIzD,SAAS,IAAI,OAAO,CAAC,YAAY,CAAC;IAelC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAwC/B,UAAU,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAS3C,cAAc,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAS9C,YAAY,CAAC,OAAO,EAAE,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC;CAY5D;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,YAAY,CAA0B;IAE9C;;;OAGG;IACG,OAAO,CACX,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,GAAE,OAAO,CAAC,UAAU,CAAM,GAC/B,OAAO,CAAC,QAAQ,CAAC;IAqCpB;;OAEG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB/C;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc9C;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAU9B;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI9C;;OAEG;IACH,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC;IAIpC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAyC7B;;OAEG;YACW,iBAAiB;IAkB/B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAK/B;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B;;;OAGG;WACU,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;IAO/C;;;OAGG;WACU,SAAS,IAAI,OAAO,CAAC,cAAc,CAAC;IAQjD;;;;OAIG;WACU,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC;IAUhD;;OAEG;WACU,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC;IAOrD;;;;;OAKG;WACU,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;CAmBhD"}
1
+ {"version":3,"file":"network-builder.d.ts","sourceRoot":"","sources":["../../../test/helpers/network-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAC7E,OAAO,EAAY,QAAQ,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;GAEG;AACH,qBAAa,QAAS,SAAQ,SAAS;IAC9B,SAAS,SAAK;gBAET,MAAM,EAAE,eAAe,GAAG;QAAE,OAAO,EAAE,YAAY,CAAA;KAAE;IAIzD,SAAS,IAAI,OAAO,CAAC,YAAY,CAAC;IAelC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAuC/B,UAAU,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAS3C,cAAc,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAS9C,YAAY,CAAC,OAAO,EAAE,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC;CAY5D;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,YAAY,CAA0B;IAE9C;;;OAGG;IACG,OAAO,CACX,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,GAAE,OAAO,CAAC,UAAU,CAAM,GAC/B,OAAO,CAAC,QAAQ,CAAC;IAqCpB;;OAEG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB/C;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc9C;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAU9B;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI9C;;OAEG;IACH,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC;IAIpC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAyC7B;;OAEG;YACW,iBAAiB;IAkB/B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAK/B;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B;;;OAGG;WACU,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;IAO/C;;;OAGG;WACU,SAAS,IAAI,OAAO,CAAC,cAAc,CAAC;IAQjD;;;;OAIG;WACU,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC;IAUhD;;OAEG;WACU,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC;IAOrD;;;;;OAKG;WACU,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;CAmBhD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olane/o-node",
3
- "version": "0.7.40",
3
+ "version": "0.7.41",
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.40",
43
+ "@olane/o-test": "0.7.41",
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.40",
64
- "@olane/o-core": "0.7.40",
65
- "@olane/o-protocol": "0.7.40",
66
- "@olane/o-tool": "0.7.40",
63
+ "@olane/o-config": "0.7.41",
64
+ "@olane/o-core": "0.7.41",
65
+ "@olane/o-protocol": "0.7.41",
66
+ "@olane/o-tool": "0.7.41",
67
67
  "debug": "^4.4.1",
68
68
  "dotenv": "^16.5.0",
69
69
  "json5": "^2.2.3"
70
70
  },
71
- "gitHead": "d2d7cb62d69249fe63d4cb293dbbdfc44d250f17"
71
+ "gitHead": "f705ab1099e0df6220c8f1d9a44e5b6cd09eb224"
72
72
  }
@@ -1,57 +0,0 @@
1
- import type { Stream } from '@libp2p/interface';
2
- import type { oAddress } from '@olane/o-core';
3
- /**
4
- * oManagedStream wraps a libp2p Stream with caller/receiver address metadata
5
- * to enable proper stream reuse based on address pairs rather than protocol only.
6
- *
7
- * Key features:
8
- * - Bidirectional cache keys: A↔B === B↔A
9
- * - Automatic reusability checking
10
- * - Idle time tracking for cleanup
11
- */
12
- export declare class oManagedStream {
13
- readonly stream: Stream;
14
- readonly callerAddress: oAddress;
15
- readonly receiverAddress: oAddress;
16
- readonly direction: 'inbound' | 'outbound';
17
- readonly createdAt: number;
18
- private _lastUsedAt;
19
- constructor(stream: Stream, callerAddress: oAddress, receiverAddress: oAddress, direction: 'inbound' | 'outbound');
20
- /**
21
- * Generates a bidirectional cache key from caller and receiver addresses.
22
- * The key is symmetric: A↔B === B↔A
23
- *
24
- * @returns Cache key string in format "address1↔address2" (sorted)
25
- */
26
- get cacheKey(): string;
27
- /**
28
- * Checks if the stream is in a reusable state:
29
- * - Stream status is 'open'
30
- * - Write status is 'writable'
31
- * - Remote read status is 'readable'
32
- *
33
- * @returns true if stream can be reused
34
- */
35
- get isReusable(): boolean;
36
- /**
37
- * Gets the last used timestamp
38
- */
39
- get lastUsedAt(): number;
40
- /**
41
- * Gets the age of the stream in milliseconds
42
- */
43
- get age(): number;
44
- /**
45
- * Gets the idle time in milliseconds since last use
46
- */
47
- get idleTime(): number;
48
- /**
49
- * Updates the last used timestamp to now
50
- */
51
- updateLastUsed(): void;
52
- /**
53
- * Gets a string representation of the managed stream for debugging
54
- */
55
- toString(): string;
56
- }
57
- //# sourceMappingURL=o-managed-stream.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"o-managed-stream.d.ts","sourceRoot":"","sources":["../../../src/connection/o-managed-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;;;;;GAQG;AACH,qBAAa,cAAc;aAKP,MAAM,EAAE,MAAM;aACd,aAAa,EAAE,QAAQ;aACvB,eAAe,EAAE,QAAQ;aACzB,SAAS,EAAE,SAAS,GAAG,UAAU;IAPnD,SAAgB,SAAS,EAAE,MAAM,CAAC;IAClC,OAAO,CAAC,WAAW,CAAS;gBAGV,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,QAAQ,EACvB,eAAe,EAAE,QAAQ,EACzB,SAAS,EAAE,SAAS,GAAG,UAAU;IAMnD;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,MAAM,CAQrB;IAED;;;;;;;OAOG;IACH,IAAI,UAAU,IAAI,OAAO,CAMxB;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;OAEG;IACH,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED;;OAEG;IACH,cAAc,IAAI,IAAI;IAItB;;OAEG;IACH,QAAQ,IAAI,MAAM;CAGnB"}
@@ -1,76 +0,0 @@
1
- /**
2
- * oManagedStream wraps a libp2p Stream with caller/receiver address metadata
3
- * to enable proper stream reuse based on address pairs rather than protocol only.
4
- *
5
- * Key features:
6
- * - Bidirectional cache keys: A↔B === B↔A
7
- * - Automatic reusability checking
8
- * - Idle time tracking for cleanup
9
- */
10
- export class oManagedStream {
11
- constructor(stream, callerAddress, receiverAddress, direction) {
12
- this.stream = stream;
13
- this.callerAddress = callerAddress;
14
- this.receiverAddress = receiverAddress;
15
- this.direction = direction;
16
- this.createdAt = Date.now();
17
- this._lastUsedAt = this.createdAt;
18
- }
19
- /**
20
- * Generates a bidirectional cache key from caller and receiver addresses.
21
- * The key is symmetric: A↔B === B↔A
22
- *
23
- * @returns Cache key string in format "address1↔address2" (sorted)
24
- */
25
- get cacheKey() {
26
- // Sort addresses to ensure bidirectionality
27
- const addresses = [
28
- this.callerAddress.value,
29
- this.receiverAddress.value,
30
- ].sort();
31
- return `${addresses[0]}↔${addresses[1]}`;
32
- }
33
- /**
34
- * Checks if the stream is in a reusable state:
35
- * - Stream status is 'open'
36
- * - Write status is 'writable'
37
- * - Remote read status is 'readable'
38
- *
39
- * @returns true if stream can be reused
40
- */
41
- get isReusable() {
42
- return (this.stream.status === 'open' &&
43
- this.stream.writeStatus === 'writable' &&
44
- this.stream.remoteReadStatus === 'readable');
45
- }
46
- /**
47
- * Gets the last used timestamp
48
- */
49
- get lastUsedAt() {
50
- return this._lastUsedAt;
51
- }
52
- /**
53
- * Gets the age of the stream in milliseconds
54
- */
55
- get age() {
56
- return Date.now() - this.createdAt;
57
- }
58
- /**
59
- * Gets the idle time in milliseconds since last use
60
- */
61
- get idleTime() {
62
- return Date.now() - this._lastUsedAt;
63
- }
64
- /**
65
- * Updates the last used timestamp to now
66
- */
67
- updateLastUsed() {
68
- this._lastUsedAt = Date.now();
69
- }
70
- /**
71
- * Gets a string representation of the managed stream for debugging
72
- */
73
- toString() {
74
- return `oManagedStream(${this.cacheKey}, ${this.direction}, ${this.stream.status})`;
75
- }
76
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=o-managed-stream.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"o-managed-stream.spec.d.ts","sourceRoot":"","sources":["../../test/o-managed-stream.spec.ts"],"names":[],"mappings":""}
@@ -1,122 +0,0 @@
1
- import { expect } from 'chai';
2
- import { oManagedStream } from '../src/connection/o-managed-stream.js';
3
- import { oAddress } from '@olane/o-core';
4
- describe('oManagedStream', () => {
5
- let mockStream;
6
- let callerAddress;
7
- let receiverAddress;
8
- beforeEach(() => {
9
- // Create mock stream
10
- mockStream = {
11
- id: 'test-stream-id',
12
- status: 'open',
13
- writeStatus: 'writable',
14
- remoteReadStatus: 'readable',
15
- direction: 'outbound',
16
- protocol: '/o/test',
17
- addEventListener: () => { },
18
- };
19
- callerAddress = new oAddress('o://caller');
20
- receiverAddress = new oAddress('o://receiver');
21
- });
22
- describe('Construction', () => {
23
- it('should create managed stream with correct properties', () => {
24
- const managedStream = new oManagedStream(mockStream, callerAddress, receiverAddress, 'outbound');
25
- expect(managedStream.stream).to.equal(mockStream);
26
- expect(managedStream.callerAddress).to.equal(callerAddress);
27
- expect(managedStream.receiverAddress).to.equal(receiverAddress);
28
- expect(managedStream.direction).to.equal('outbound');
29
- expect(managedStream.createdAt).to.be.a('number');
30
- expect(managedStream.lastUsedAt).to.equal(managedStream.createdAt);
31
- });
32
- });
33
- describe('Cache Key Generation', () => {
34
- it('should generate bidirectional cache key (A→B === B→A)', () => {
35
- const streamAtoB = new oManagedStream(mockStream, callerAddress, receiverAddress, 'outbound');
36
- const streamBtoA = new oManagedStream(mockStream, receiverAddress, callerAddress, 'inbound');
37
- // Cache keys should be identical regardless of direction
38
- expect(streamAtoB.cacheKey).to.equal(streamBtoA.cacheKey);
39
- });
40
- it('should generate different keys for different address pairs', () => {
41
- const address1 = new oAddress('o://node-1');
42
- const address2 = new oAddress('o://node-2');
43
- const address3 = new oAddress('o://node-3');
44
- const stream1 = new oManagedStream(mockStream, address1, address2, 'outbound');
45
- const stream2 = new oManagedStream(mockStream, address1, address3, 'outbound');
46
- expect(stream1.cacheKey).to.not.equal(stream2.cacheKey);
47
- });
48
- it('should create stable, sorted cache keys', () => {
49
- const managedStream = new oManagedStream(mockStream, callerAddress, receiverAddress, 'outbound');
50
- const expectedKey = [callerAddress.value, receiverAddress.value]
51
- .sort()
52
- .join('↔');
53
- expect(managedStream.cacheKey).to.equal(expectedKey);
54
- });
55
- });
56
- describe('Reusability Check', () => {
57
- it('should be reusable when stream is open, writable, and readable', () => {
58
- mockStream.status = 'open';
59
- mockStream.writeStatus = 'writable';
60
- mockStream.remoteReadStatus = 'readable';
61
- const managedStream = new oManagedStream(mockStream, callerAddress, receiverAddress, 'outbound');
62
- expect(managedStream.isReusable).to.be.true;
63
- });
64
- it('should not be reusable when stream is closed', () => {
65
- mockStream.status = 'closed';
66
- mockStream.writeStatus = 'writable';
67
- mockStream.remoteReadStatus = 'readable';
68
- const managedStream = new oManagedStream(mockStream, callerAddress, receiverAddress, 'outbound');
69
- expect(managedStream.isReusable).to.be.false;
70
- });
71
- it('should not be reusable when stream is not writable', () => {
72
- mockStream.status = 'open';
73
- mockStream.writeStatus = 'closed';
74
- mockStream.remoteReadStatus = 'readable';
75
- const managedStream = new oManagedStream(mockStream, callerAddress, receiverAddress, 'outbound');
76
- expect(managedStream.isReusable).to.be.false;
77
- });
78
- it('should not be reusable when remote is not readable', () => {
79
- mockStream.status = 'open';
80
- mockStream.writeStatus = 'writable';
81
- mockStream.remoteReadStatus = 'closed';
82
- const managedStream = new oManagedStream(mockStream, callerAddress, receiverAddress, 'outbound');
83
- expect(managedStream.isReusable).to.be.false;
84
- });
85
- });
86
- describe('Timestamp Management', () => {
87
- it('should update lastUsedAt when updateLastUsed is called', async () => {
88
- const managedStream = new oManagedStream(mockStream, callerAddress, receiverAddress, 'outbound');
89
- const initialLastUsed = managedStream.lastUsedAt;
90
- // Wait a bit to ensure timestamp difference
91
- await new Promise((resolve) => setTimeout(resolve, 10));
92
- managedStream.updateLastUsed();
93
- expect(managedStream.lastUsedAt).to.be.greaterThan(initialLastUsed);
94
- });
95
- it('should calculate age correctly', async () => {
96
- const managedStream = new oManagedStream(mockStream, callerAddress, receiverAddress, 'outbound');
97
- // Wait a bit
98
- await new Promise((resolve) => setTimeout(resolve, 10));
99
- expect(managedStream.age).to.be.greaterThan(0);
100
- expect(managedStream.age).to.be.lessThan(1000); // Should be less than 1 second
101
- });
102
- it('should calculate idle time correctly', async () => {
103
- const managedStream = new oManagedStream(mockStream, callerAddress, receiverAddress, 'outbound');
104
- // Wait a bit without using
105
- await new Promise((resolve) => setTimeout(resolve, 10));
106
- expect(managedStream.idleTime).to.be.greaterThan(0);
107
- // Update and check idle time resets
108
- managedStream.updateLastUsed();
109
- expect(managedStream.idleTime).to.be.lessThan(5);
110
- });
111
- });
112
- describe('String Representation', () => {
113
- it('should provide meaningful toString output', () => {
114
- const managedStream = new oManagedStream(mockStream, callerAddress, receiverAddress, 'outbound');
115
- const str = managedStream.toString();
116
- expect(str).to.include('oManagedStream');
117
- expect(str).to.include(managedStream.cacheKey);
118
- expect(str).to.include('outbound');
119
- expect(str).to.include('open');
120
- });
121
- });
122
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=stream-handler-caching.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stream-handler-caching.spec.d.ts","sourceRoot":"","sources":["../../test/stream-handler-caching.spec.ts"],"names":[],"mappings":""}
@@ -1,261 +0,0 @@
1
- import { expect } from 'chai';
2
- import { StreamHandler } from '../src/connection/stream-handler.js';
3
- import { oAddress } from '@olane/o-core';
4
- describe('StreamHandler Address-Based Caching', () => {
5
- let streamHandler;
6
- let mockConnection;
7
- let mockStream;
8
- let callerAddress;
9
- let receiverAddress;
10
- beforeEach(() => {
11
- streamHandler = new StreamHandler();
12
- // Create mock connection
13
- mockConnection = {
14
- status: 'open',
15
- remotePeer: {
16
- toString: () => 'test-peer-id',
17
- },
18
- remoteAddr: {
19
- toString: () => '/memory/test',
20
- },
21
- streams: [],
22
- newStream: async () => mockStream,
23
- };
24
- // Create mock stream
25
- mockStream = {
26
- id: 'test-stream-id',
27
- status: 'open',
28
- writeStatus: 'writable',
29
- remoteReadStatus: 'readable',
30
- direction: 'outbound',
31
- protocol: '/o/test',
32
- addEventListener: () => { },
33
- };
34
- callerAddress = new oAddress('o://caller');
35
- receiverAddress = new oAddress('o://receiver');
36
- });
37
- describe('getOrCreateStream with Address-Based Caching', () => {
38
- it('should create new stream when cache is empty', async () => {
39
- const config = {
40
- reusePolicy: 'reuse',
41
- };
42
- const streamAddresses = {
43
- callerAddress,
44
- receiverAddress,
45
- direction: 'outbound',
46
- };
47
- const stream = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config, streamAddresses);
48
- expect(stream).to.equal(mockStream);
49
- });
50
- it('should reuse cached stream with same caller-receiver pair', async () => {
51
- const config = {
52
- reusePolicy: 'reuse',
53
- };
54
- const streamAddresses = {
55
- callerAddress,
56
- receiverAddress,
57
- direction: 'outbound',
58
- };
59
- // First call creates and caches
60
- const stream1 = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config, streamAddresses);
61
- // Second call should reuse
62
- const stream2 = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config, streamAddresses);
63
- expect(stream1).to.equal(stream2);
64
- });
65
- it('should reuse stream bidirectionally (A→B same as B→A)', async () => {
66
- const config = {
67
- reusePolicy: 'reuse',
68
- };
69
- // First: caller → receiver
70
- const streamAtoB = {
71
- callerAddress,
72
- receiverAddress,
73
- direction: 'outbound',
74
- };
75
- const stream1 = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config, streamAtoB);
76
- // Second: receiver → caller (reversed)
77
- const streamBtoA = {
78
- callerAddress: receiverAddress,
79
- receiverAddress: callerAddress,
80
- direction: 'inbound',
81
- };
82
- const stream2 = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config, streamBtoA);
83
- // Should be the same stream due to bidirectional caching
84
- expect(stream1).to.equal(stream2);
85
- });
86
- it('should create new stream for different address pairs', async () => {
87
- const config = {
88
- reusePolicy: 'reuse',
89
- };
90
- const otherReceiver = new oAddress('o://other-receiver');
91
- // Create new mock stream for second call
92
- const mockStream2 = {
93
- ...mockStream,
94
- id: 'test-stream-id-2',
95
- };
96
- let streamCount = 0;
97
- mockConnection.newStream = async () => {
98
- streamCount++;
99
- return (streamCount === 1 ? mockStream : mockStream2);
100
- };
101
- // First pair
102
- const stream1 = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config, {
103
- callerAddress,
104
- receiverAddress,
105
- direction: 'outbound',
106
- });
107
- // Different pair
108
- const stream2 = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config, {
109
- callerAddress,
110
- receiverAddress: otherReceiver,
111
- direction: 'outbound',
112
- });
113
- // Should be different streams
114
- expect(stream1.id).to.not.equal(stream2.id);
115
- });
116
- it('should not cache when reusePolicy is none', async () => {
117
- const config = {
118
- reusePolicy: 'none',
119
- };
120
- const streamAddresses = {
121
- callerAddress,
122
- receiverAddress,
123
- direction: 'outbound',
124
- };
125
- let callCount = 0;
126
- mockConnection.newStream = async () => {
127
- callCount++;
128
- return {
129
- ...mockStream,
130
- id: `stream-${callCount}`,
131
- };
132
- };
133
- const stream1 = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config, streamAddresses);
134
- const stream2 = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config, streamAddresses);
135
- // Should be different streams (not cached)
136
- expect(stream1.id).to.not.equal(stream2.id);
137
- });
138
- it('should remove non-reusable streams from cache', async () => {
139
- const config = {
140
- reusePolicy: 'reuse',
141
- };
142
- const streamAddresses = {
143
- callerAddress,
144
- receiverAddress,
145
- direction: 'outbound',
146
- };
147
- // First call creates and caches
148
- const stream1 = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config, streamAddresses);
149
- // Make stream non-reusable
150
- mockStream.status = 'closed';
151
- // Create new mock stream for second call
152
- const mockStream2 = {
153
- ...mockStream,
154
- id: 'test-stream-id-2',
155
- status: 'open',
156
- };
157
- mockConnection.newStream = async () => mockStream2;
158
- // Second call should create new stream (old one not reusable)
159
- const stream2 = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config, streamAddresses);
160
- expect(stream1.id).to.not.equal(stream2.id);
161
- });
162
- it('should fall back to protocol-based check when addresses not provided', async () => {
163
- const config = {
164
- reusePolicy: 'reuse',
165
- };
166
- // Add mock stream to connection streams
167
- mockConnection.streams = [mockStream];
168
- // Call without streamAddresses
169
- const stream = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config);
170
- // Should find and return the existing stream by protocol
171
- expect(stream).to.equal(mockStream);
172
- });
173
- });
174
- describe('extractRemotePeerAddress', () => {
175
- it('should extract address from connection peer ID', () => {
176
- const address = streamHandler.extractRemotePeerAddress(mockConnection);
177
- expect(address.value).to.include('o://peer/');
178
- expect(address.value).to.include('test-peer-id');
179
- });
180
- });
181
- describe('cacheInboundStream', () => {
182
- it('should cache inbound stream when reuse is enabled', async () => {
183
- streamHandler.cacheInboundStream(mockStream, callerAddress, receiverAddress, 'reuse');
184
- // Try to get the cached stream
185
- const config = {
186
- reusePolicy: 'reuse',
187
- };
188
- const streamAddresses = {
189
- callerAddress,
190
- receiverAddress,
191
- direction: 'outbound',
192
- };
193
- const stream = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config, streamAddresses);
194
- // Should reuse the cached inbound stream
195
- expect(stream).to.equal(mockStream);
196
- });
197
- it('should not cache when reusePolicy is none', async () => {
198
- streamHandler.cacheInboundStream(mockStream, callerAddress, receiverAddress, 'none');
199
- // Try to get stream - should create new one
200
- const config = {
201
- reusePolicy: 'reuse',
202
- };
203
- const newMockStream = { ...mockStream, id: 'new-stream-id' };
204
- mockConnection.newStream = async () => newMockStream;
205
- const streamAddresses = {
206
- callerAddress,
207
- receiverAddress,
208
- direction: 'outbound',
209
- };
210
- const stream = await streamHandler.getOrCreateStream(mockConnection, '/o/test', config, streamAddresses);
211
- // Should not reuse (was not cached)
212
- expect(stream.id).to.equal('new-stream-id');
213
- });
214
- it('should not cache duplicate streams', () => {
215
- // Cache first time
216
- streamHandler.cacheInboundStream(mockStream, callerAddress, receiverAddress, 'reuse');
217
- // Try to cache again - should be no-op
218
- streamHandler.cacheInboundStream(mockStream, callerAddress, receiverAddress, 'reuse');
219
- // No error should occur, and stream should still be cached
220
- // (This test mainly ensures no exception is thrown)
221
- });
222
- });
223
- describe('Stream Cleanup', () => {
224
- it('should remove stream from cache on close event', (done) => {
225
- const config = {
226
- reusePolicy: 'reuse',
227
- };
228
- let closeListener;
229
- // Override addEventListener to capture the close listener
230
- mockStream.addEventListener = (event, listener) => {
231
- if (event === 'close') {
232
- closeListener = listener;
233
- }
234
- };
235
- const streamAddresses = {
236
- callerAddress,
237
- receiverAddress,
238
- direction: 'outbound',
239
- };
240
- streamHandler
241
- .getOrCreateStream(mockConnection, '/o/test', config, streamAddresses)
242
- .then(() => {
243
- expect(closeListener).to.not.be.undefined;
244
- // Simulate close event
245
- if (closeListener) {
246
- closeListener();
247
- }
248
- // Create new stream for next call
249
- const newMockStream = { ...mockStream, id: 'new-stream-after-close' };
250
- mockConnection.newStream = async () => newMockStream;
251
- // Try to get stream again - should create new one since old one was removed
252
- return streamHandler.getOrCreateStream(mockConnection, '/o/test', config, streamAddresses);
253
- })
254
- .then((stream) => {
255
- expect(stream.id).to.equal('new-stream-after-close');
256
- done();
257
- })
258
- .catch(done);
259
- });
260
- });
261
- });