fix(throughput): add tests for per-IP connection tracking and throughput history; assert per-IP eviction after connection close to prevent memory leak

This commit is contained in:
2026-02-19 09:12:50 +00:00
parent 0ae882731a
commit c7722c30f3
3 changed files with 31 additions and 17 deletions

View File

@@ -1,5 +1,13 @@
# Changelog
## 2026-02-19 - 25.7.6 - fix(throughput)
add tests for per-IP connection tracking and throughput history; assert per-IP eviction after connection close to prevent memory leak
- Adds runtime assertions for per-IP TCP connection tracking (m.connections.byIP) while a connection is active
- Adds checks for throughput history (m.throughput.history) to ensure history length and timestamps are recorded
- Asserts that per-IP tracking data is evicted after connection close (byIP.size === 0) to verify memory leak fix
- Reorders test checks so per-IP and history metrics are validated during the active connection and totals are validated after close
## 2026-02-19 - 25.7.5 - fix(rustproxy)
prune stale per-route metrics, add per-route rate limiter caching and regex cache, and improve connection tracking cleanup to prevent memory growth

View File

@@ -151,11 +151,28 @@ tap.test('TCP forward - real-time byte tracking', async (tools) => {
console.log(`TCP forward (during) — recent throughput: in=${tpDuring.in}, out=${tpDuring.out}`);
expect(tpDuring.in + tpDuring.out).toBeGreaterThan(0);
// ── v25.2.0: Per-IP tracking (TCP connections) ──
// Must check WHILE connection is active — per-IP data is evicted on last close
const byIP = mDuring.connections.byIP();
console.log('TCP forward — connections byIP:', Array.from(byIP.entries()));
expect(byIP.size).toBeGreaterThan(0);
const topIPs = mDuring.connections.topIPs(10);
console.log('TCP forward — topIPs:', topIPs);
expect(topIPs.length).toBeGreaterThan(0);
expect(topIPs[0].ip).toBeTruthy();
// ── v25.2.0: Throughput history ──
const history = mDuring.throughput.history(10);
console.log('TCP forward — throughput history length:', history.length);
expect(history.length).toBeGreaterThan(0);
expect(history[0].timestamp).toBeGreaterThan(0);
// Close connection
client.destroy();
await tools.delayFor(500);
// Final check
// Final check — totals persist even after connection close
await pollMetrics(proxy);
const m = proxy.getMetrics();
const bytesIn = m.totals.bytesIn();
@@ -168,21 +185,10 @@ tap.test('TCP forward - real-time byte tracking', async (tools) => {
const byRoute = m.throughput.byRoute();
console.log('TCP forward — throughput byRoute:', Array.from(byRoute.entries()));
// ── v25.2.0: Per-IP tracking (TCP connections) ──
const byIP = m.connections.byIP();
console.log('TCP forward — connections byIP:', Array.from(byIP.entries()));
expect(byIP.size).toBeGreaterThan(0);
const topIPs = m.connections.topIPs(10);
console.log('TCP forward — topIPs:', topIPs);
expect(topIPs.length).toBeGreaterThan(0);
expect(topIPs[0].ip).toBeTruthy();
// ── v25.2.0: Throughput history ──
const history = m.throughput.history(10);
console.log('TCP forward — throughput history length:', history.length);
expect(history.length).toBeGreaterThan(0);
expect(history[0].timestamp).toBeGreaterThan(0);
// After close, per-IP data should be evicted (memory leak fix)
const byIPAfter = m.connections.byIP();
console.log('TCP forward — connections byIP after close:', Array.from(byIPAfter.entries()));
expect(byIPAfter.size).toEqual(0);
await proxy.stop();
await tools.delayFor(200);

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@push.rocks/smartproxy',
version: '25.7.5',
version: '25.7.6',
description: 'A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.'
}