fix: memory leak on connections

Massimo Melina committed Aug 1, 2022 at 00:37 UTC 8b48dff808b8d9042f278431760ded7de3850c50
2 files changed +10 -4
server/src/throttler.ts
+8 -4
@@ -5,7 +5,7 @@ import Koa from 'koa'
5 import { ThrottledStream, ThrottleGroup } from './ThrottledStream'
6 import { defineConfig } from './config'
7 import { getOrSet, isLocalHost } from './misc'
8 -import { updateConnection } from './connections'
8 +import { Connection, updateConnection } from './connections'
9 import _ from 'lodash'
10
11 const mainThrottleGroup = new ThrottleGroup(Infinity)
@@ -38,19 +38,22 @@ export const throttler: Koa.Middleware = async (ctx, next) => {
38 group.updateLimit(v))
39 return { group, count:0, destroy: unsub }
40 })
41 - const conn = ctx.state.connection
41 + const conn = ctx.state.connection as Connection | undefined
42 if (!conn) throw 'assert throttler connection'
43
44 const ts = conn[SymThrStr] = new ThrottledStream(ipGroup.group, conn[SymThrStr])
45 + let closed = false
46
47 const DELAY = 1000
48 const update = _.debounce(() => {
48 - const ts = conn[SymThrStr]
49 + const ts = conn[SymThrStr] as ThrottledStream
50 const speed = ts.getSpeed()
51 const outSpeed = _.round(speed, 1) || _.round(speed, 3) // further precision if necessary
52 updateConnection(conn, { outSpeed, sent: ts.getBytesSent() })
53 + /* in case this stream stands still for a while (before the end), we'll have neither 'sent' or 'close' events,
54 + * so who will take care to updateConnection? This artificial next-call will ensure just that */
55 clearTimeout(conn[SymTimeout])
53 - if (outSpeed || !(ts.finished || ts.ended))
56 + if (outSpeed || !closed)
57 conn[SymTimeout] = setTimeout(update, DELAY)
58 }, DELAY, { maxWait:DELAY })
59 ts.on('sent', update)
@@ -58,6 +61,7 @@ export const throttler: Koa.Middleware = async (ctx, next) => {
61 ++ipGroup.count
62 ts.on('close', ()=> {
63 update.flush()
64 + closed = true
65 if (--ipGroup.count) return // any left?
66 ipGroup.destroy?.()
67 delete ip2group[ctx.ip]
todo.md
+2
@@ -1,6 +1,8 @@
1 # To do
2 +- fix: currently user field in the access.log is '-'
3 - admin: check + update
4 - admin/monitor: account column
5 +- admin/monitor: show total throughput
6 - frontend: hide closer button on login dialog accessing a protected resource, as it's no use
7 - easier nat life
8 - show public ip use, https://github.com/sindresorhus/public-ip