undici 6.1.0 → 6.2.0
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/lib/agent.js +35 -34
- package/lib/mock/mock-agent.js +6 -17
- package/package.json +1 -1
package/lib/agent.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { InvalidArgumentError } = require('./core/errors')
|
|
4
|
-
const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = require('./core/symbols')
|
|
4
|
+
const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors, kBusy } = require('./core/symbols')
|
|
5
5
|
const DispatcherBase = require('./dispatcher-base')
|
|
6
6
|
const Pool = require('./pool')
|
|
7
7
|
const Client = require('./client')
|
|
8
8
|
const util = require('./core/util')
|
|
9
9
|
const createRedirectInterceptor = require('./interceptor/redirectInterceptor')
|
|
10
|
-
const { WeakRef, FinalizationRegistry } = require('./compat/dispatcher-weakref')()
|
|
11
10
|
|
|
12
11
|
const kOnConnect = Symbol('onConnect')
|
|
13
12
|
const kOnDisconnect = Symbol('onDisconnect')
|
|
@@ -15,8 +14,8 @@ const kOnConnectionError = Symbol('onConnectionError')
|
|
|
15
14
|
const kMaxRedirections = Symbol('maxRedirections')
|
|
16
15
|
const kOnDrain = Symbol('onDrain')
|
|
17
16
|
const kFactory = Symbol('factory')
|
|
18
|
-
const kFinalizer = Symbol('finalizer')
|
|
19
17
|
const kOptions = Symbol('options')
|
|
18
|
+
const kDeleteScheduled = Symbol('deleteScheduled')
|
|
20
19
|
|
|
21
20
|
function defaultFactory (origin, opts) {
|
|
22
21
|
return opts && opts.connections === 1
|
|
@@ -55,12 +54,6 @@ class Agent extends DispatcherBase {
|
|
|
55
54
|
this[kMaxRedirections] = maxRedirections
|
|
56
55
|
this[kFactory] = factory
|
|
57
56
|
this[kClients] = new Map()
|
|
58
|
-
this[kFinalizer] = new FinalizationRegistry(/* istanbul ignore next: gc is undeterministic */ key => {
|
|
59
|
-
const ref = this[kClients].get(key)
|
|
60
|
-
if (ref !== undefined && ref.deref() === undefined) {
|
|
61
|
-
this[kClients].delete(key)
|
|
62
|
-
}
|
|
63
|
-
})
|
|
64
57
|
|
|
65
58
|
const agent = this
|
|
66
59
|
|
|
@@ -83,12 +76,8 @@ class Agent extends DispatcherBase {
|
|
|
83
76
|
|
|
84
77
|
get [kRunning] () {
|
|
85
78
|
let ret = 0
|
|
86
|
-
for (const
|
|
87
|
-
|
|
88
|
-
/* istanbul ignore next: gc is undeterministic */
|
|
89
|
-
if (client) {
|
|
90
|
-
ret += client[kRunning]
|
|
91
|
-
}
|
|
79
|
+
for (const client of this[kClients].values()) {
|
|
80
|
+
ret += client[kRunning]
|
|
92
81
|
}
|
|
93
82
|
return ret
|
|
94
83
|
}
|
|
@@ -101,18 +90,38 @@ class Agent extends DispatcherBase {
|
|
|
101
90
|
throw new InvalidArgumentError('opts.origin must be a non-empty string or URL.')
|
|
102
91
|
}
|
|
103
92
|
|
|
104
|
-
|
|
93
|
+
let dispatcher = this[kClients].get(key)
|
|
105
94
|
|
|
106
|
-
let dispatcher = ref ? ref.deref() : null
|
|
107
95
|
if (!dispatcher) {
|
|
108
96
|
dispatcher = this[kFactory](opts.origin, this[kOptions])
|
|
109
|
-
.on('drain',
|
|
97
|
+
.on('drain', (...args) => {
|
|
98
|
+
this[kOnDrain](...args)
|
|
99
|
+
|
|
100
|
+
// We remove the client if it is not busy for 5 minutes
|
|
101
|
+
// to avoid a long list of clients to saturate memory.
|
|
102
|
+
// Ideally, we could use a FinalizationRegistry here, but
|
|
103
|
+
// it is currently very buggy in Node.js.
|
|
104
|
+
// See
|
|
105
|
+
// * https://github.com/nodejs/node/issues/49344
|
|
106
|
+
// * https://github.com/nodejs/node/issues/47748
|
|
107
|
+
// TODO(mcollina): make the timeout configurable or
|
|
108
|
+
// use an event to remove disconnected clients.
|
|
109
|
+
this[kDeleteScheduled] = setTimeout(() => {
|
|
110
|
+
if (dispatcher[kBusy] === 0) {
|
|
111
|
+
this[kClients].destroy().then(() => {})
|
|
112
|
+
this[kClients].delete(key)
|
|
113
|
+
}
|
|
114
|
+
}, 300_000)
|
|
115
|
+
this[kDeleteScheduled].unref()
|
|
116
|
+
})
|
|
110
117
|
.on('connect', this[kOnConnect])
|
|
111
118
|
.on('disconnect', this[kOnDisconnect])
|
|
112
119
|
.on('connectionError', this[kOnConnectionError])
|
|
113
120
|
|
|
114
|
-
this[kClients].set(key,
|
|
115
|
-
|
|
121
|
+
this[kClients].set(key, dispatcher)
|
|
122
|
+
} else if (dispatcher[kDeleteScheduled]) {
|
|
123
|
+
clearTimeout(dispatcher[kDeleteScheduled])
|
|
124
|
+
dispatcher[kDeleteScheduled] = null
|
|
116
125
|
}
|
|
117
126
|
|
|
118
127
|
return dispatcher.dispatch(opts, handler)
|
|
@@ -120,28 +129,20 @@ class Agent extends DispatcherBase {
|
|
|
120
129
|
|
|
121
130
|
async [kClose] () {
|
|
122
131
|
const closePromises = []
|
|
123
|
-
for (const
|
|
124
|
-
|
|
125
|
-
/* istanbul ignore else: gc is undeterministic */
|
|
126
|
-
if (client) {
|
|
127
|
-
this[kFinalizer].unregister(client)
|
|
128
|
-
closePromises.push(client.close())
|
|
129
|
-
}
|
|
132
|
+
for (const client of this[kClients].values()) {
|
|
133
|
+
closePromises.push(client.close())
|
|
130
134
|
}
|
|
135
|
+
this[kClients].clear()
|
|
131
136
|
|
|
132
137
|
await Promise.all(closePromises)
|
|
133
138
|
}
|
|
134
139
|
|
|
135
140
|
async [kDestroy] (err) {
|
|
136
141
|
const destroyPromises = []
|
|
137
|
-
for (const
|
|
138
|
-
|
|
139
|
-
/* istanbul ignore else: gc is undeterministic */
|
|
140
|
-
if (client) {
|
|
141
|
-
this[kFinalizer].unregister(client)
|
|
142
|
-
destroyPromises.push(client.destroy(err))
|
|
143
|
-
}
|
|
142
|
+
for (const client of this[kClients].values()) {
|
|
143
|
+
destroyPromises.push(client.destroy(err))
|
|
144
144
|
}
|
|
145
|
+
this[kClients].clear()
|
|
145
146
|
|
|
146
147
|
await Promise.all(destroyPromises)
|
|
147
148
|
}
|
package/lib/mock/mock-agent.js
CHANGED
|
@@ -21,16 +21,6 @@ const Dispatcher = require('../dispatcher')
|
|
|
21
21
|
const Pluralizer = require('./pluralizer')
|
|
22
22
|
const PendingInterceptorsFormatter = require('./pending-interceptors-formatter')
|
|
23
23
|
|
|
24
|
-
class FakeWeakRef {
|
|
25
|
-
constructor (value) {
|
|
26
|
-
this.value = value
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
deref () {
|
|
30
|
-
return this.value
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
24
|
class MockAgent extends Dispatcher {
|
|
35
25
|
constructor (opts) {
|
|
36
26
|
super(opts)
|
|
@@ -103,7 +93,7 @@ class MockAgent extends Dispatcher {
|
|
|
103
93
|
}
|
|
104
94
|
|
|
105
95
|
[kMockAgentSet] (origin, dispatcher) {
|
|
106
|
-
this[kClients].set(origin,
|
|
96
|
+
this[kClients].set(origin, dispatcher)
|
|
107
97
|
}
|
|
108
98
|
|
|
109
99
|
[kFactory] (origin) {
|
|
@@ -115,9 +105,9 @@ class MockAgent extends Dispatcher {
|
|
|
115
105
|
|
|
116
106
|
[kMockAgentGet] (origin) {
|
|
117
107
|
// First check if we can immediately find it
|
|
118
|
-
const
|
|
119
|
-
if (
|
|
120
|
-
return
|
|
108
|
+
const client = this[kClients].get(origin)
|
|
109
|
+
if (client) {
|
|
110
|
+
return client
|
|
121
111
|
}
|
|
122
112
|
|
|
123
113
|
// If the origin is not a string create a dummy parent pool and return to user
|
|
@@ -128,8 +118,7 @@ class MockAgent extends Dispatcher {
|
|
|
128
118
|
}
|
|
129
119
|
|
|
130
120
|
// If we match, create a pool and assign the same dispatches
|
|
131
|
-
for (const [keyMatcher,
|
|
132
|
-
const nonExplicitDispatcher = nonExplicitRef.deref()
|
|
121
|
+
for (const [keyMatcher, nonExplicitDispatcher] of Array.from(this[kClients])) {
|
|
133
122
|
if (nonExplicitDispatcher && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) {
|
|
134
123
|
const dispatcher = this[kFactory](origin)
|
|
135
124
|
this[kMockAgentSet](origin, dispatcher)
|
|
@@ -147,7 +136,7 @@ class MockAgent extends Dispatcher {
|
|
|
147
136
|
const mockAgentClients = this[kClients]
|
|
148
137
|
|
|
149
138
|
return Array.from(mockAgentClients.entries())
|
|
150
|
-
.flatMap(([origin, scope]) => scope
|
|
139
|
+
.flatMap(([origin, scope]) => scope[kDispatches].map(dispatch => ({ ...dispatch, origin })))
|
|
151
140
|
.filter(({ pending }) => pending)
|
|
152
141
|
}
|
|
153
142
|
|