Comparing version 6.1.0 to 6.2.0
'use strict' | ||
const { InvalidArgumentError } = require('./core/errors') | ||
const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = require('./core/symbols') | ||
const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors, kBusy } = require('./core/symbols') | ||
const DispatcherBase = require('./dispatcher-base') | ||
@@ -10,3 +10,2 @@ const Pool = require('./pool') | ||
const createRedirectInterceptor = require('./interceptor/redirectInterceptor') | ||
const { WeakRef, FinalizationRegistry } = require('./compat/dispatcher-weakref')() | ||
@@ -19,4 +18,4 @@ const kOnConnect = Symbol('onConnect') | ||
const kFactory = Symbol('factory') | ||
const kFinalizer = Symbol('finalizer') | ||
const kOptions = Symbol('options') | ||
const kDeleteScheduled = Symbol('deleteScheduled') | ||
@@ -60,8 +59,2 @@ function defaultFactory (origin, opts) { | ||
this[kClients] = new Map() | ||
this[kFinalizer] = new FinalizationRegistry(/* istanbul ignore next: gc is undeterministic */ key => { | ||
const ref = this[kClients].get(key) | ||
if (ref !== undefined && ref.deref() === undefined) { | ||
this[kClients].delete(key) | ||
} | ||
}) | ||
@@ -89,8 +82,4 @@ const agent = this | ||
let ret = 0 | ||
for (const ref of this[kClients].values()) { | ||
const client = ref.deref() | ||
/* istanbul ignore next: gc is undeterministic */ | ||
if (client) { | ||
ret += client[kRunning] | ||
} | ||
for (const client of this[kClients].values()) { | ||
ret += client[kRunning] | ||
} | ||
@@ -108,8 +97,26 @@ return ret | ||
const ref = this[kClients].get(key) | ||
let dispatcher = this[kClients].get(key) | ||
let dispatcher = ref ? ref.deref() : null | ||
if (!dispatcher) { | ||
dispatcher = this[kFactory](opts.origin, this[kOptions]) | ||
.on('drain', this[kOnDrain]) | ||
.on('drain', (...args) => { | ||
this[kOnDrain](...args) | ||
// We remove the client if it is not busy for 5 minutes | ||
// to avoid a long list of clients to saturate memory. | ||
// Ideally, we could use a FinalizationRegistry here, but | ||
// it is currently very buggy in Node.js. | ||
// See | ||
// * https://github.com/nodejs/node/issues/49344 | ||
// * https://github.com/nodejs/node/issues/47748 | ||
// TODO(mcollina): make the timeout configurable or | ||
// use an event to remove disconnected clients. | ||
this[kDeleteScheduled] = setTimeout(() => { | ||
if (dispatcher[kBusy] === 0) { | ||
this[kClients].destroy().then(() => {}) | ||
this[kClients].delete(key) | ||
} | ||
}, 300_000) | ||
this[kDeleteScheduled].unref() | ||
}) | ||
.on('connect', this[kOnConnect]) | ||
@@ -119,4 +126,6 @@ .on('disconnect', this[kOnDisconnect]) | ||
this[kClients].set(key, new WeakRef(dispatcher)) | ||
this[kFinalizer].register(dispatcher, key) | ||
this[kClients].set(key, dispatcher) | ||
} else if (dispatcher[kDeleteScheduled]) { | ||
clearTimeout(dispatcher[kDeleteScheduled]) | ||
dispatcher[kDeleteScheduled] = null | ||
} | ||
@@ -129,10 +138,6 @@ | ||
const closePromises = [] | ||
for (const ref of this[kClients].values()) { | ||
const client = ref.deref() | ||
/* istanbul ignore else: gc is undeterministic */ | ||
if (client) { | ||
this[kFinalizer].unregister(client) | ||
closePromises.push(client.close()) | ||
} | ||
for (const client of this[kClients].values()) { | ||
closePromises.push(client.close()) | ||
} | ||
this[kClients].clear() | ||
@@ -144,10 +149,6 @@ await Promise.all(closePromises) | ||
const destroyPromises = [] | ||
for (const ref of this[kClients].values()) { | ||
const client = ref.deref() | ||
/* istanbul ignore else: gc is undeterministic */ | ||
if (client) { | ||
this[kFinalizer].unregister(client) | ||
destroyPromises.push(client.destroy(err)) | ||
} | ||
for (const client of this[kClients].values()) { | ||
destroyPromises.push(client.destroy(err)) | ||
} | ||
this[kClients].clear() | ||
@@ -154,0 +155,0 @@ await Promise.all(destroyPromises) |
@@ -24,12 +24,2 @@ 'use strict' | ||
class FakeWeakRef { | ||
constructor (value) { | ||
this.value = value | ||
} | ||
deref () { | ||
return this.value | ||
} | ||
} | ||
class MockAgent extends Dispatcher { | ||
@@ -107,3 +97,3 @@ constructor (opts) { | ||
[kMockAgentSet] (origin, dispatcher) { | ||
this[kClients].set(origin, new FakeWeakRef(dispatcher)) | ||
this[kClients].set(origin, dispatcher) | ||
} | ||
@@ -120,5 +110,5 @@ | ||
// First check if we can immediately find it | ||
const ref = this[kClients].get(origin) | ||
if (ref) { | ||
return ref.deref() | ||
const client = this[kClients].get(origin) | ||
if (client) { | ||
return client | ||
} | ||
@@ -134,4 +124,3 @@ | ||
// If we match, create a pool and assign the same dispatches | ||
for (const [keyMatcher, nonExplicitRef] of Array.from(this[kClients])) { | ||
const nonExplicitDispatcher = nonExplicitRef.deref() | ||
for (const [keyMatcher, nonExplicitDispatcher] of Array.from(this[kClients])) { | ||
if (nonExplicitDispatcher && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) { | ||
@@ -154,3 +143,3 @@ const dispatcher = this[kFactory](origin) | ||
return Array.from(mockAgentClients.entries()) | ||
.flatMap(([origin, scope]) => scope.deref()[kDispatches].map(dispatch => ({ ...dispatch, origin }))) | ||
.flatMap(([origin, scope]) => scope[kDispatches].map(dispatch => ({ ...dispatch, origin }))) | ||
.filter(({ pending }) => pending) | ||
@@ -157,0 +146,0 @@ } |
{ | ||
"name": "undici", | ||
"version": "6.1.0", | ||
"version": "6.2.0", | ||
"description": "An HTTP/1.1 client, written from scratch for Node.js", | ||
@@ -5,0 +5,0 @@ "homepage": "https://undici.nodejs.org", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1190098
21035