import { expect, tap } from '@git.zone/tstest/tapbundle'; import { SmartProxy } from '../ts/index.js'; tap.test('cleanup queue bug - verify queue processing handles more than batch size', async (tools) => { console.log('\n=== Cleanup Queue Bug Test ==='); console.log('Purpose: Verify that the cleanup queue correctly processes all connections'); console.log('even when there are more than the batch size (100)'); // Create proxy const proxy = new SmartProxy({ routes: [{ name: 'test-route', match: { ports: 8588 }, action: { type: 'forward', target: { host: 'localhost', port: 9996 } } }], enableDetailedLogging: false, }); await proxy.start(); console.log('āœ“ Proxy started on port 8588'); // Access connection manager const cm = (proxy as any).connectionManager; // Create mock connection records console.log('\n--- Creating 150 mock connections ---'); const mockConnections: any[] = []; for (let i = 0; i < 150; i++) { // Create mock socket objects with necessary methods const mockIncoming = { destroyed: true, writable: false, remoteAddress: '127.0.0.1', removeAllListeners: () => {}, destroy: () => {}, end: () => {} }; const mockOutgoing = { destroyed: true, writable: false, destroy: () => {}, end: () => {} }; const mockRecord = { id: `mock-${i}`, incoming: mockIncoming, outgoing: mockOutgoing, connectionClosed: false, incomingStartTime: Date.now(), lastActivity: Date.now(), remoteIP: '127.0.0.1', remotePort: 10000 + i, localPort: 8588, bytesReceived: 100, bytesSent: 100, incomingTerminationReason: null, cleanupTimer: null }; // Add to connection records cm.connectionRecords.set(mockRecord.id, mockRecord); mockConnections.push(mockRecord); } console.log(`Created ${cm.getConnectionCount()} mock connections`); expect(cm.getConnectionCount()).toEqual(150); // Queue all connections for cleanup console.log('\n--- Queueing all connections for cleanup ---'); for (const conn of mockConnections) { cm.initiateCleanupOnce(conn, 'test_cleanup'); } console.log(`Cleanup queue size: ${cm.cleanupQueue.size}`); expect(cm.cleanupQueue.size).toEqual(150); // Wait for cleanup to complete console.log('\n--- Waiting for cleanup batches to process ---'); // The cleanup happens in batches, wait for all to complete let waitTime = 0; while (cm.getConnectionCount() > 0 || cm.cleanupQueue.size > 0) { await new Promise(resolve => setTimeout(resolve, 100)); waitTime += 100; if (waitTime > 5000) { console.log('Timeout waiting for cleanup to complete'); break; } } console.log(`Cleanup completed in ${waitTime}ms`); // Check final state const finalCount = cm.getConnectionCount(); console.log(`\nFinal connection count: ${finalCount}`); console.log(`Cleanup queue size: ${cm.cleanupQueue.size}`); // All connections should be cleaned up expect(finalCount).toEqual(0); expect(cm.cleanupQueue.size).toEqual(0); // Verify termination stats const stats = cm.getTerminationStats(); console.log('Termination stats:', stats); expect(stats.incoming.test_cleanup).toEqual(150); // Cleanup console.log('\n--- Stopping proxy ---'); await proxy.stop(); console.log('\nāœ“ Test complete: Cleanup queue now correctly processes all connections'); }); tap.start();