@olane/o-node 0.7.50 → 0.7.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.
- package/dist/src/connection/index.d.ts +4 -0
- package/dist/src/connection/index.d.ts.map +1 -1
- package/dist/src/connection/index.js +4 -0
- package/dist/src/connection/interfaces/o-node-connection-stream.config.d.ts +8 -0
- package/dist/src/connection/interfaces/o-node-connection-stream.config.d.ts.map +1 -1
- package/dist/src/connection/interfaces/stream-pool-manager.config.d.ts +41 -0
- package/dist/src/connection/interfaces/stream-pool-manager.config.d.ts.map +1 -0
- package/dist/src/connection/interfaces/stream-pool-manager.config.js +1 -0
- package/dist/src/connection/o-node-connection-stream.d.ts +12 -0
- package/dist/src/connection/o-node-connection-stream.d.ts.map +1 -1
- package/dist/src/connection/o-node-connection-stream.js +18 -0
- package/dist/src/connection/stream-pool-manager.d.ts +86 -0
- package/dist/src/connection/stream-pool-manager.d.ts.map +1 -0
- package/dist/src/connection/stream-pool-manager.events.d.ts +57 -0
- package/dist/src/connection/stream-pool-manager.events.d.ts.map +1 -0
- package/dist/src/connection/stream-pool-manager.events.js +14 -0
- package/dist/src/connection/stream-pool-manager.js +356 -0
- package/dist/test/connection-management.spec.js +24 -24
- package/dist/test/helpers/stream-pool-test-helpers.d.ts +76 -0
- package/dist/test/helpers/stream-pool-test-helpers.d.ts.map +1 -0
- package/dist/test/helpers/stream-pool-test-helpers.js +229 -0
- package/dist/test/network-communication.spec.js +68 -66
- package/dist/test/stream-pool-manager.spec.d.ts +1 -0
- package/dist/test/stream-pool-manager.spec.d.ts.map +1 -0
- package/dist/test/stream-pool-manager.spec.js +424 -0
- package/package.json +7 -7
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// import { expect } from 'chai';
|
|
3
|
+
// import { StreamPoolManager } from '../src/connection/stream-pool-manager.js';
|
|
4
|
+
// import { NetworkBuilder, NetworkTopologies } from './helpers/network-builder.js';
|
|
5
|
+
// import { createConnectionSpy } from './helpers/connection-spy.js';
|
|
6
|
+
// import { StreamPoolEvent } from '../src/connection/stream-pool-manager.events.js';
|
|
7
|
+
// import { oNodeConnectionStream } from '../src/connection/o-node-connection-stream.js';
|
|
8
|
+
// import type { TestTool } from './helpers/network-builder.js';
|
|
9
|
+
// import type { Connection } from '@olane/o-config';
|
|
10
|
+
// /**
|
|
11
|
+
// * Integration tests for StreamPoolManager using real libp2p nodes and connections
|
|
12
|
+
// */
|
|
13
|
+
// describe('StreamPoolManager Integration Tests', () => {
|
|
14
|
+
// let builder: NetworkBuilder;
|
|
15
|
+
// let leader: TestTool;
|
|
16
|
+
// let child: TestTool;
|
|
17
|
+
// let p2pConnection: Connection;
|
|
18
|
+
// let poolManager: StreamPoolManager | undefined;
|
|
19
|
+
// /**
|
|
20
|
+
// * Helper to create a real libp2p connection between two nodes
|
|
21
|
+
// */
|
|
22
|
+
// async function getP2pConnection(): Promise<Connection> {
|
|
23
|
+
// // Make a call to establish connection
|
|
24
|
+
// await leader.use(child.address, {
|
|
25
|
+
// method: 'echo',
|
|
26
|
+
// params: { message: 'establish connection' }
|
|
27
|
+
// });
|
|
28
|
+
// // Get the connection
|
|
29
|
+
// const connections = leader.p2pNode.getConnections();
|
|
30
|
+
// const connection = connections.find(
|
|
31
|
+
// conn => conn.remotePeer.toString() === child.peerId.toString()
|
|
32
|
+
// );
|
|
33
|
+
// if (!connection) {
|
|
34
|
+
// throw new Error('Failed to establish connection between nodes');
|
|
35
|
+
// }
|
|
36
|
+
// return connection;
|
|
37
|
+
// }
|
|
38
|
+
// /**
|
|
39
|
+
// * Helper to create a StreamPoolManager with real connection
|
|
40
|
+
// */
|
|
41
|
+
// async function createStreamPoolManager(config?: Partial<any>): Promise<StreamPoolManager> {
|
|
42
|
+
// const manager = new StreamPoolManager({
|
|
43
|
+
// poolSize: config?.poolSize || 10,
|
|
44
|
+
// readerStreamIndex: config?.readerStreamIndex ?? 0,
|
|
45
|
+
// streamHandler: {
|
|
46
|
+
// handleIncomingStream: config?.streamHandler?.handleIncomingStream || (async (stream: any) => {
|
|
47
|
+
// // Default handler: just keep stream alive
|
|
48
|
+
// return new Promise(() => {}); // Never resolves (keeps reader active)
|
|
49
|
+
// })
|
|
50
|
+
// },
|
|
51
|
+
// p2pConnection,
|
|
52
|
+
// requestHandler: config?.requestHandler,
|
|
53
|
+
// createStream: async () => {
|
|
54
|
+
// // Create a real libp2p stream
|
|
55
|
+
// const stream = await p2pConnection.newStream('/o-protocol/1.0.0');
|
|
56
|
+
// return new oNodeConnectionStream({
|
|
57
|
+
// p2pStream: stream,
|
|
58
|
+
// streamType: 'request-response',
|
|
59
|
+
// readTimeoutMs: 30000,
|
|
60
|
+
// drainTimeoutMs: 5000,
|
|
61
|
+
// });
|
|
62
|
+
// },
|
|
63
|
+
// ...config,
|
|
64
|
+
// });
|
|
65
|
+
// return manager;
|
|
66
|
+
// }
|
|
67
|
+
// beforeEach(async () => {
|
|
68
|
+
// // Create real node network
|
|
69
|
+
// builder = await NetworkTopologies.twoNode();
|
|
70
|
+
// leader = builder.getNode('o://leader')!;
|
|
71
|
+
// child = builder.getNode('o://child')!;
|
|
72
|
+
// // Establish real p2p connection
|
|
73
|
+
// p2pConnection = await getP2pConnection();
|
|
74
|
+
// });
|
|
75
|
+
// afterEach(async () => {
|
|
76
|
+
// if (poolManager) {
|
|
77
|
+
// await poolManager.close();
|
|
78
|
+
// poolManager = undefined;
|
|
79
|
+
// }
|
|
80
|
+
// await builder.cleanup();
|
|
81
|
+
// });
|
|
82
|
+
// describe('Initialization', () => {
|
|
83
|
+
// it('should initialize pool with default size of 10 streams', async () => {
|
|
84
|
+
// poolManager = await createStreamPoolManager();
|
|
85
|
+
// await poolManager.initialize();
|
|
86
|
+
// const stats = poolManager.getStats();
|
|
87
|
+
// expect(stats.totalStreams).to.equal(10);
|
|
88
|
+
// });
|
|
89
|
+
// it('should initialize pool with custom size', async () => {
|
|
90
|
+
// poolManager = await createStreamPoolManager({ poolSize: 5 });
|
|
91
|
+
// await poolManager.initialize();
|
|
92
|
+
// const stats = poolManager.getStats();
|
|
93
|
+
// expect(stats.totalStreams).to.equal(5);
|
|
94
|
+
// });
|
|
95
|
+
// it('should throw error when pool size is less than 2', async () => {
|
|
96
|
+
// expect(() => {
|
|
97
|
+
// poolManager = new StreamPoolManager({
|
|
98
|
+
// poolSize: 1,
|
|
99
|
+
// readerStreamIndex: 0,
|
|
100
|
+
// streamHandler: {} as any,
|
|
101
|
+
// p2pConnection,
|
|
102
|
+
// createStream: async () => ({} as any),
|
|
103
|
+
// });
|
|
104
|
+
// }).to.throw('Pool size must be at least 2');
|
|
105
|
+
// });
|
|
106
|
+
// it('should start dedicated reader automatically', async () => {
|
|
107
|
+
// let readerStarted = false;
|
|
108
|
+
// poolManager = await createStreamPoolManager();
|
|
109
|
+
// poolManager.on(StreamPoolEvent.ReaderStarted, () => {
|
|
110
|
+
// readerStarted = true;
|
|
111
|
+
// });
|
|
112
|
+
// await poolManager.initialize();
|
|
113
|
+
// // Wait a bit for reader to start
|
|
114
|
+
// await new Promise(resolve => setTimeout(resolve, 100));
|
|
115
|
+
// expect(readerStarted).to.be.true;
|
|
116
|
+
// });
|
|
117
|
+
// it('should emit pool-initialized event', async () => {
|
|
118
|
+
// let eventData: any;
|
|
119
|
+
// poolManager = await createStreamPoolManager();
|
|
120
|
+
// poolManager.on(StreamPoolEvent.PoolInitialized, (data: any) => {
|
|
121
|
+
// eventData = data;
|
|
122
|
+
// });
|
|
123
|
+
// await poolManager.initialize();
|
|
124
|
+
// expect(eventData).to.exist;
|
|
125
|
+
// expect(eventData.poolSize).to.equal(10);
|
|
126
|
+
// });
|
|
127
|
+
// it('should be idempotent (calling initialize twice is safe)', async () => {
|
|
128
|
+
// poolManager = await createStreamPoolManager();
|
|
129
|
+
// await poolManager.initialize();
|
|
130
|
+
// const statsFirst = poolManager.getStats();
|
|
131
|
+
// await poolManager.initialize();
|
|
132
|
+
// const statsSecond = poolManager.getStats();
|
|
133
|
+
// expect(statsFirst.totalStreams).to.equal(statsSecond.totalStreams);
|
|
134
|
+
// expect(statsSecond.totalStreams).to.equal(10);
|
|
135
|
+
// });
|
|
136
|
+
// it('should assign correct stream types', async () => {
|
|
137
|
+
// poolManager = await createStreamPoolManager({ poolSize: 3 });
|
|
138
|
+
// await poolManager.initialize();
|
|
139
|
+
// const stats = poolManager.getStats();
|
|
140
|
+
// expect(stats.requestResponseStreams).to.equal(2); // All except stream[0]
|
|
141
|
+
// });
|
|
142
|
+
// });
|
|
143
|
+
// describe('Round-Robin Stream Selection', () => {
|
|
144
|
+
// beforeEach(async () => {
|
|
145
|
+
// poolManager = await createStreamPoolManager({ poolSize: 5 });
|
|
146
|
+
// await poolManager.initialize();
|
|
147
|
+
// });
|
|
148
|
+
// it('should return streams in round-robin order', async () => {
|
|
149
|
+
// const stream1 = await poolManager!.getStream();
|
|
150
|
+
// const stream2 = await poolManager!.getStream();
|
|
151
|
+
// const stream3 = await poolManager!.getStream();
|
|
152
|
+
// const stream4 = await poolManager!.getStream();
|
|
153
|
+
// // Should cycle through streams[1-4]
|
|
154
|
+
// expect(stream1.p2pStream.id).to.not.equal(stream2.p2pStream.id);
|
|
155
|
+
// expect(stream2.p2pStream.id).to.not.equal(stream3.p2pStream.id);
|
|
156
|
+
// expect(stream3.p2pStream.id).to.not.equal(stream4.p2pStream.id);
|
|
157
|
+
// });
|
|
158
|
+
// it('should wrap around after last stream', async () => {
|
|
159
|
+
// // Pool size is 5, so we have streams 1-4 for request-response (4 streams total)
|
|
160
|
+
// const firstRound: any[] = [];
|
|
161
|
+
// for (let i = 0; i < 4; i++) {
|
|
162
|
+
// firstRound.push(await poolManager!.getStream());
|
|
163
|
+
// }
|
|
164
|
+
// const nextStream = await poolManager!.getStream();
|
|
165
|
+
// // Should wrap back to first request-response stream
|
|
166
|
+
// expect(nextStream.p2pStream.id).to.equal(firstRound[0].p2pStream.id);
|
|
167
|
+
// });
|
|
168
|
+
// it('should throw error when getStream called before initialize', async () => {
|
|
169
|
+
// const uninitializedManager = await createStreamPoolManager();
|
|
170
|
+
// try {
|
|
171
|
+
// await uninitializedManager.getStream();
|
|
172
|
+
// expect.fail('Should have thrown error');
|
|
173
|
+
// } catch (error: any) {
|
|
174
|
+
// expect(error.message).to.include('not initialized');
|
|
175
|
+
// } finally {
|
|
176
|
+
// await uninitializedManager.close();
|
|
177
|
+
// }
|
|
178
|
+
// });
|
|
179
|
+
// });
|
|
180
|
+
// describe('Stream Validation and Replacement', () => {
|
|
181
|
+
// it('should detect invalid stream and replace it', async () => {
|
|
182
|
+
// poolManager = await createStreamPoolManager({ poolSize: 3 });
|
|
183
|
+
// await poolManager.initialize();
|
|
184
|
+
// // Get first stream and forcibly close it
|
|
185
|
+
// const firstStream = await poolManager.getStream();
|
|
186
|
+
// await firstStream.p2pStream.close();
|
|
187
|
+
// // Wait for stream to be marked invalid
|
|
188
|
+
// await new Promise(resolve => setTimeout(resolve, 100));
|
|
189
|
+
// // Next getStream should detect and replace the invalid stream
|
|
190
|
+
// const nextStream = await poolManager.getStream();
|
|
191
|
+
// expect(nextStream.isValid).to.be.true;
|
|
192
|
+
// });
|
|
193
|
+
// it('should emit stream-replaced event when replacing stream', async () => {
|
|
194
|
+
// let replacedEventFired = false;
|
|
195
|
+
// poolManager = await createStreamPoolManager({ poolSize: 3 });
|
|
196
|
+
// poolManager.on(StreamPoolEvent.StreamReplaced, () => {
|
|
197
|
+
// replacedEventFired = true;
|
|
198
|
+
// });
|
|
199
|
+
// await poolManager.initialize();
|
|
200
|
+
// // Close a request-response stream
|
|
201
|
+
// const stream = await poolManager.getStream();
|
|
202
|
+
// await stream.p2pStream.close();
|
|
203
|
+
// // Wait for detection and replacement
|
|
204
|
+
// await new Promise(resolve => setTimeout(resolve, 100));
|
|
205
|
+
// // Trigger getStream to force validation
|
|
206
|
+
// await poolManager.getStream();
|
|
207
|
+
// expect(replacedEventFired).to.be.true;
|
|
208
|
+
// });
|
|
209
|
+
// });
|
|
210
|
+
// describe('Dedicated Reader Recovery', () => {
|
|
211
|
+
// it('should detect reader failure and trigger recovery', async () => {
|
|
212
|
+
// let failureDetected = false;
|
|
213
|
+
// const mockStreamHandler = {
|
|
214
|
+
// handleIncomingStream: async () => {
|
|
215
|
+
// failureDetected = true;
|
|
216
|
+
// throw new Error('Reader stream failed');
|
|
217
|
+
// },
|
|
218
|
+
// };
|
|
219
|
+
// poolManager = await createStreamPoolManager({
|
|
220
|
+
// poolSize: 3,
|
|
221
|
+
// streamHandler: mockStreamHandler,
|
|
222
|
+
// });
|
|
223
|
+
// poolManager.on(StreamPoolEvent.ReaderFailed, () => {
|
|
224
|
+
// failureDetected = true;
|
|
225
|
+
// });
|
|
226
|
+
// await poolManager.initialize();
|
|
227
|
+
// // Wait for reader failure event
|
|
228
|
+
// await new Promise(resolve => setTimeout(resolve, 500));
|
|
229
|
+
// const stats = poolManager.getStats();
|
|
230
|
+
// expect(stats.failureCount).to.be.greaterThan(0);
|
|
231
|
+
// });
|
|
232
|
+
// it('should emit reader-recovered event on successful recovery', async () => {
|
|
233
|
+
// let callCount = 0;
|
|
234
|
+
// let recoveryEventFired = false;
|
|
235
|
+
// const mockStreamHandler = {
|
|
236
|
+
// handleIncomingStream: async () => {
|
|
237
|
+
// callCount++;
|
|
238
|
+
// if (callCount === 1) {
|
|
239
|
+
// throw new Error('Initial failure');
|
|
240
|
+
// }
|
|
241
|
+
// // Second call succeeds (recovery)
|
|
242
|
+
// return new Promise(() => {}); // Never resolves (keeps reader active)
|
|
243
|
+
// },
|
|
244
|
+
// };
|
|
245
|
+
// poolManager = await createStreamPoolManager({
|
|
246
|
+
// poolSize: 3,
|
|
247
|
+
// streamHandler: mockStreamHandler,
|
|
248
|
+
// });
|
|
249
|
+
// poolManager.on(StreamPoolEvent.ReaderRecovered, () => {
|
|
250
|
+
// recoveryEventFired = true;
|
|
251
|
+
// });
|
|
252
|
+
// await poolManager.initialize();
|
|
253
|
+
// // Wait for recovery
|
|
254
|
+
// await new Promise(resolve => setTimeout(resolve, 1000));
|
|
255
|
+
// expect(recoveryEventFired).to.be.true;
|
|
256
|
+
// });
|
|
257
|
+
// it('should not attempt recovery during close', async () => {
|
|
258
|
+
// let recoveryAttempted = false;
|
|
259
|
+
// const mockStreamHandler = {
|
|
260
|
+
// handleIncomingStream: async () => {
|
|
261
|
+
// await new Promise((resolve) => setTimeout(resolve, 50));
|
|
262
|
+
// throw new Error('Reader failed');
|
|
263
|
+
// },
|
|
264
|
+
// };
|
|
265
|
+
// poolManager = await createStreamPoolManager({
|
|
266
|
+
// poolSize: 3,
|
|
267
|
+
// streamHandler: mockStreamHandler,
|
|
268
|
+
// });
|
|
269
|
+
// poolManager.on(StreamPoolEvent.ReaderRecovered, () => {
|
|
270
|
+
// recoveryAttempted = true;
|
|
271
|
+
// });
|
|
272
|
+
// await poolManager.initialize();
|
|
273
|
+
// // Close immediately
|
|
274
|
+
// await poolManager.close();
|
|
275
|
+
// // Wait a bit
|
|
276
|
+
// await new Promise((resolve) => setTimeout(resolve, 200));
|
|
277
|
+
// // Should not have attempted recovery
|
|
278
|
+
// expect(recoveryAttempted).to.be.false;
|
|
279
|
+
// });
|
|
280
|
+
// });
|
|
281
|
+
// describe('Statistics', () => {
|
|
282
|
+
// it('should return accurate totalStreams count', async () => {
|
|
283
|
+
// poolManager = await createStreamPoolManager({ poolSize: 7 });
|
|
284
|
+
// await poolManager.initialize();
|
|
285
|
+
// const stats = poolManager.getStats();
|
|
286
|
+
// expect(stats.totalStreams).to.equal(7);
|
|
287
|
+
// });
|
|
288
|
+
// it('should return accurate healthyStreams count', async () => {
|
|
289
|
+
// poolManager = await createStreamPoolManager({ poolSize: 5 });
|
|
290
|
+
// await poolManager.initialize();
|
|
291
|
+
// const stats = poolManager.getStats();
|
|
292
|
+
// expect(stats.healthyStreams).to.be.greaterThan(0);
|
|
293
|
+
// });
|
|
294
|
+
// it('should report reader health status', async () => {
|
|
295
|
+
// poolManager = await createStreamPoolManager({ poolSize: 3 });
|
|
296
|
+
// await poolManager.initialize();
|
|
297
|
+
// const stats = poolManager.getStats();
|
|
298
|
+
// expect(stats.readerStreamHealth).to.be.oneOf([
|
|
299
|
+
// 'healthy',
|
|
300
|
+
// 'unhealthy',
|
|
301
|
+
// 'not-initialized',
|
|
302
|
+
// ]);
|
|
303
|
+
// });
|
|
304
|
+
// it('should track request-response stream count', async () => {
|
|
305
|
+
// poolManager = await createStreamPoolManager({ poolSize: 6 });
|
|
306
|
+
// await poolManager.initialize();
|
|
307
|
+
// const stats = poolManager.getStats();
|
|
308
|
+
// expect(stats.requestResponseStreams).to.equal(5); // 6 total - 1 reader
|
|
309
|
+
// });
|
|
310
|
+
// it('should increment failureCount on reader failures', async () => {
|
|
311
|
+
// let callCount = 0;
|
|
312
|
+
// const mockStreamHandler = {
|
|
313
|
+
// handleIncomingStream: async () => {
|
|
314
|
+
// callCount++;
|
|
315
|
+
// if (callCount <= 2) {
|
|
316
|
+
// throw new Error('Failure');
|
|
317
|
+
// }
|
|
318
|
+
// return new Promise(() => {}); // Then succeed
|
|
319
|
+
// },
|
|
320
|
+
// };
|
|
321
|
+
// poolManager = await createStreamPoolManager({
|
|
322
|
+
// poolSize: 3,
|
|
323
|
+
// streamHandler: mockStreamHandler,
|
|
324
|
+
// });
|
|
325
|
+
// await poolManager.initialize();
|
|
326
|
+
// // Wait for failures
|
|
327
|
+
// await new Promise(resolve => setTimeout(resolve, 1000));
|
|
328
|
+
// const stats = poolManager.getStats();
|
|
329
|
+
// expect(stats.failureCount).to.be.at.least(1);
|
|
330
|
+
// });
|
|
331
|
+
// });
|
|
332
|
+
// describe('Event Emission', () => {
|
|
333
|
+
// it('should emit all lifecycle events with correct data', async () => {
|
|
334
|
+
// let poolInitialized = false;
|
|
335
|
+
// let readerStarted = false;
|
|
336
|
+
// let poolClosed = false;
|
|
337
|
+
// poolManager = await createStreamPoolManager({ poolSize: 3 });
|
|
338
|
+
// poolManager.on(StreamPoolEvent.PoolInitialized, () => {
|
|
339
|
+
// poolInitialized = true;
|
|
340
|
+
// });
|
|
341
|
+
// poolManager.on(StreamPoolEvent.ReaderStarted, () => {
|
|
342
|
+
// readerStarted = true;
|
|
343
|
+
// });
|
|
344
|
+
// poolManager.on(StreamPoolEvent.PoolClosed, () => {
|
|
345
|
+
// poolClosed = true;
|
|
346
|
+
// });
|
|
347
|
+
// await poolManager.initialize();
|
|
348
|
+
// await new Promise(resolve => setTimeout(resolve, 100));
|
|
349
|
+
// await poolManager.close();
|
|
350
|
+
// expect(poolInitialized).to.be.true;
|
|
351
|
+
// expect(readerStarted).to.be.true;
|
|
352
|
+
// expect(poolClosed).to.be.true;
|
|
353
|
+
// });
|
|
354
|
+
// it('should support multiple listeners for same event', async () => {
|
|
355
|
+
// let listener1Called = false;
|
|
356
|
+
// let listener2Called = false;
|
|
357
|
+
// poolManager = await createStreamPoolManager({ poolSize: 3 });
|
|
358
|
+
// poolManager.on(StreamPoolEvent.PoolInitialized, () => {
|
|
359
|
+
// listener1Called = true;
|
|
360
|
+
// });
|
|
361
|
+
// poolManager.on(StreamPoolEvent.PoolInitialized, () => {
|
|
362
|
+
// listener2Called = true;
|
|
363
|
+
// });
|
|
364
|
+
// await poolManager.initialize();
|
|
365
|
+
// expect(listener1Called).to.be.true;
|
|
366
|
+
// expect(listener2Called).to.be.true;
|
|
367
|
+
// });
|
|
368
|
+
// it('should allow removing event listeners', async () => {
|
|
369
|
+
// let callCount = 0;
|
|
370
|
+
// const listener = () => {
|
|
371
|
+
// callCount++;
|
|
372
|
+
// };
|
|
373
|
+
// poolManager = await createStreamPoolManager({ poolSize: 3 });
|
|
374
|
+
// poolManager.on(StreamPoolEvent.PoolInitialized, listener);
|
|
375
|
+
// await poolManager.initialize();
|
|
376
|
+
// expect(callCount).to.equal(1);
|
|
377
|
+
// poolManager.off(StreamPoolEvent.PoolInitialized, listener);
|
|
378
|
+
// // Verify off doesn't throw
|
|
379
|
+
// expect(() =>
|
|
380
|
+
// poolManager!.off(StreamPoolEvent.PoolInitialized, listener),
|
|
381
|
+
// ).to.not.throw();
|
|
382
|
+
// });
|
|
383
|
+
// });
|
|
384
|
+
// describe('Cleanup and Lifecycle', () => {
|
|
385
|
+
// it('should close all streams on close()', async () => {
|
|
386
|
+
// poolManager = await createStreamPoolManager({ poolSize: 5 });
|
|
387
|
+
// await poolManager.initialize();
|
|
388
|
+
// const statsBefore = poolManager.getStats();
|
|
389
|
+
// expect(statsBefore.totalStreams).to.equal(5);
|
|
390
|
+
// await poolManager.close();
|
|
391
|
+
// const statsAfter = poolManager.getStats();
|
|
392
|
+
// expect(statsAfter.totalStreams).to.equal(0);
|
|
393
|
+
// });
|
|
394
|
+
// it('should emit pool-closed event', async () => {
|
|
395
|
+
// let closedEventFired = false;
|
|
396
|
+
// poolManager = await createStreamPoolManager({ poolSize: 3 });
|
|
397
|
+
// poolManager.on(StreamPoolEvent.PoolClosed, () => {
|
|
398
|
+
// closedEventFired = true;
|
|
399
|
+
// });
|
|
400
|
+
// await poolManager.initialize();
|
|
401
|
+
// await poolManager.close();
|
|
402
|
+
// expect(closedEventFired).to.be.true;
|
|
403
|
+
// });
|
|
404
|
+
// it('should be safe to call close() multiple times', async () => {
|
|
405
|
+
// poolManager = await createStreamPoolManager({ poolSize: 3 });
|
|
406
|
+
// await poolManager.initialize();
|
|
407
|
+
// await poolManager.close();
|
|
408
|
+
// await poolManager.close(); // Should not throw
|
|
409
|
+
// const stats = poolManager.getStats();
|
|
410
|
+
// expect(stats.totalStreams).to.equal(0);
|
|
411
|
+
// });
|
|
412
|
+
// it('should prevent getStream() after close()', async () => {
|
|
413
|
+
// poolManager = await createStreamPoolManager({ poolSize: 3 });
|
|
414
|
+
// await poolManager.initialize();
|
|
415
|
+
// await poolManager.close();
|
|
416
|
+
// try {
|
|
417
|
+
// await poolManager.getStream();
|
|
418
|
+
// expect.fail('Should have thrown error');
|
|
419
|
+
// } catch (error: any) {
|
|
420
|
+
// expect(error.message).to.include('not initialized');
|
|
421
|
+
// }
|
|
422
|
+
// });
|
|
423
|
+
// });
|
|
424
|
+
// });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olane/o-node",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.51",
|
|
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.
|
|
43
|
+
"@olane/o-test": "0.7.51",
|
|
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.
|
|
64
|
-
"@olane/o-core": "0.7.
|
|
65
|
-
"@olane/o-protocol": "0.7.
|
|
66
|
-
"@olane/o-tool": "0.7.
|
|
63
|
+
"@olane/o-config": "0.7.51",
|
|
64
|
+
"@olane/o-core": "0.7.51",
|
|
65
|
+
"@olane/o-protocol": "0.7.51",
|
|
66
|
+
"@olane/o-tool": "0.7.51",
|
|
67
67
|
"debug": "^4.4.1",
|
|
68
68
|
"dotenv": "^16.5.0",
|
|
69
69
|
"json5": "^2.2.3"
|
|
70
70
|
},
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "f770a110369cb9791d9e9208c7a084feecbb9b2c"
|
|
72
72
|
}
|