Skip to content

Commit 25da47e

Browse files
committed
fix: agent memory leak
1 parent dcf82a7 commit 25da47e

1 file changed

Lines changed: 25 additions & 15 deletions

File tree

lib/dispatcher/agent.js

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,35 @@ class Agent extends DispatcherBase {
4545
}
4646

4747
this[kOnConnect] = (origin, targets) => {
48+
const result = this[kClients].get(origin)
49+
if (result) {
50+
result.count += 1
51+
}
4852
this.emit('connect', origin, [this, ...targets])
4953
}
5054

5155
this[kOnDisconnect] = (origin, targets, err) => {
56+
const result = this[kClients].get(origin)
57+
if (result) {
58+
result.count -= 1
59+
if (result.count <= 0) {
60+
this[kClients].delete(origin)
61+
result.dispatcher.destroy()
62+
}
63+
}
5264
this.emit('disconnect', origin, [this, ...targets], err)
5365
}
5466

5567
this[kOnConnectionError] = (origin, targets, err) => {
68+
// TODO: should this decrement result.count here?
5669
this.emit('connectionError', origin, [this, ...targets], err)
5770
}
5871
}
5972

6073
get [kRunning] () {
6174
let ret = 0
62-
for (const client of this[kClients].values()) {
63-
ret += client[kRunning]
75+
for (const { dispatcher } of this[kClients].values()) {
76+
ret += dispatcher[kRunning]
6477
}
6578
return ret
6679
}
@@ -73,28 +86,25 @@ class Agent extends DispatcherBase {
7386
throw new InvalidArgumentError('opts.origin must be a non-empty string or URL.')
7487
}
7588

76-
let dispatcher = this[kClients].get(key)
77-
89+
const result = this[kClients].get(key)
90+
let dispatcher = result && result.dispatcher
7891
if (!dispatcher) {
7992
dispatcher = this[kFactory](opts.origin, this[kOptions])
8093
.on('drain', this[kOnDrain])
8194
.on('connect', this[kOnConnect])
8295
.on('disconnect', this[kOnDisconnect])
8396
.on('connectionError', this[kOnConnectionError])
8497

85-
// This introduces a tiny memory leak, as dispatchers are never removed from the map.
86-
// TODO(mcollina): remove te timer when the client/pool do not have any more
87-
// active connections.
88-
this[kClients].set(key, dispatcher)
98+
this[kClients].set(key, { count: 0, dispatcher })
8999
}
90100

91101
return dispatcher.dispatch(opts, handler)
92102
}
93103

94104
async [kClose] () {
95105
const closePromises = []
96-
for (const client of this[kClients].values()) {
97-
closePromises.push(client.close())
106+
for (const { dispatcher } of this[kClients].values()) {
107+
closePromises.push(dispatcher.close())
98108
}
99109
this[kClients].clear()
100110

@@ -103,8 +113,8 @@ class Agent extends DispatcherBase {
103113

104114
async [kDestroy] (err) {
105115
const destroyPromises = []
106-
for (const client of this[kClients].values()) {
107-
destroyPromises.push(client.destroy(err))
116+
for (const { dispatcher } of this[kClients].values()) {
117+
destroyPromises.push(dispatcher.destroy(err))
108118
}
109119
this[kClients].clear()
110120

@@ -113,9 +123,9 @@ class Agent extends DispatcherBase {
113123

114124
get stats () {
115125
const allClientStats = {}
116-
for (const client of this[kClients].values()) {
117-
if (client.stats) {
118-
allClientStats[client[kUrl].origin] = client.stats
126+
for (const { dispatcher } of this[kClients].values()) {
127+
if (dispatcher.stats) {
128+
allClientStats[dispatcher[kUrl].origin] = dispatcher.stats
119129
}
120130
}
121131
return allClientStats

0 commit comments

Comments
 (0)