undici 4.7.3 → 4.8.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/docs/api/BalancedPool.md +98 -0
- package/index.d.ts +3 -1
- package/index.js +2 -0
- package/lib/balanced-pool.js +119 -0
- package/lib/core/errors.js +12 -1
- package/package.json +1 -1
- package/types/balanced-pool.d.ts +19 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Class: BalancedPool
|
|
2
|
+
|
|
3
|
+
Extends: `undici.Dispatcher`
|
|
4
|
+
|
|
5
|
+
A pool of [Pool](docs/api/Pool.md) instances connected to multiple upstreams.
|
|
6
|
+
|
|
7
|
+
Requests are not guaranteed to be dispatched in order of invocation.
|
|
8
|
+
|
|
9
|
+
## `new BalancedPool(upstreams [, options])`
|
|
10
|
+
|
|
11
|
+
Arguments:
|
|
12
|
+
|
|
13
|
+
* **upstreams** `URL | string | string[]` - It should only include the **protocol, hostname, and port**.
|
|
14
|
+
* **options** `PoolOptions` (optional)
|
|
15
|
+
|
|
16
|
+
### Parameter: `PoolOptions`
|
|
17
|
+
|
|
18
|
+
The `PoolOptions` are passed to each of the `Pool` instances being created.
|
|
19
|
+
|
|
20
|
+
See: [`PoolOptions`](docs/api/Pool.md#parameter-pooloptions)
|
|
21
|
+
|
|
22
|
+
## Instance Properties
|
|
23
|
+
|
|
24
|
+
### `BalancedPool.upstreams`
|
|
25
|
+
|
|
26
|
+
Returns an array of upstreams that were previously added.
|
|
27
|
+
|
|
28
|
+
### `BalancedPool.busy`
|
|
29
|
+
|
|
30
|
+
Implements [Client.busy](docs/api/Client.md#clientbusy)
|
|
31
|
+
|
|
32
|
+
### `BalancedPool.closed`
|
|
33
|
+
|
|
34
|
+
Implements [Client.closed](docs/api/Client.md#clientclosed)
|
|
35
|
+
|
|
36
|
+
### `BalancedPool.destroyed`
|
|
37
|
+
|
|
38
|
+
Implements [Client.destroyed](docs/api/Client.md#clientdestroyed)
|
|
39
|
+
|
|
40
|
+
## Instance Methods
|
|
41
|
+
|
|
42
|
+
### `BalancedPool.addUpstream(upstream)`
|
|
43
|
+
|
|
44
|
+
Add an upstream.
|
|
45
|
+
|
|
46
|
+
Arguments:
|
|
47
|
+
|
|
48
|
+
* **upstream** `string` - It should only include the **protocol, hostname, and port**.
|
|
49
|
+
|
|
50
|
+
### `BalancedPool.removeUpstream(upstream)`
|
|
51
|
+
|
|
52
|
+
Removes an upstream that was previously addded.
|
|
53
|
+
|
|
54
|
+
### `BalancedPool.close([callback])`
|
|
55
|
+
|
|
56
|
+
Implements [`Dispatcher.close([callback])`](docs/api/Dispatcher.md#clientclose-callback-).
|
|
57
|
+
|
|
58
|
+
### `BalancedPool.destroy([error, callback])`
|
|
59
|
+
|
|
60
|
+
Implements [`Dispatcher.destroy([error, callback])`](docs/api/Dispatcher.md#dispatcher-callback-).
|
|
61
|
+
|
|
62
|
+
### `BalancedPool.connect(options[, callback])`
|
|
63
|
+
|
|
64
|
+
See [`Dispatcher.connect(options[, callback])`](docs/api/Dispatcher.md#clientconnectoptions--callback).
|
|
65
|
+
|
|
66
|
+
### `BalancedPool.dispatch(options, handlers)`
|
|
67
|
+
|
|
68
|
+
Implements [`Dispatcher.dispatch(options, handlers)`](docs/api/Dispatcher.md#clientdispatchoptions-handlers).
|
|
69
|
+
|
|
70
|
+
### `BalancedPool.pipeline(options, handler)`
|
|
71
|
+
|
|
72
|
+
See [`Dispatcher.pipeline(options, handler)`](docs/api/Dispatcher.md#clientpipelineoptions-handler).
|
|
73
|
+
|
|
74
|
+
### `BalancedPool.request(options[, callback])`
|
|
75
|
+
|
|
76
|
+
See [`Dispatcher.request(options [, callback])`](docs/api/Dispatcher.md#clientrequestoptions--callback).
|
|
77
|
+
|
|
78
|
+
### `BalancedPool.stream(options, factory[, callback])`
|
|
79
|
+
|
|
80
|
+
See [`Dispatcher.stream(options, factory[, callback])`](docs/api/Dispatcher.md#clientstreamoptions-factory--callback).
|
|
81
|
+
|
|
82
|
+
### `BalancedPool.upgrade(options[, callback])`
|
|
83
|
+
|
|
84
|
+
See [`Dispatcher.upgrade(options[, callback])`](docs/api/Dispatcher.md#clientupgradeoptions-callback).
|
|
85
|
+
|
|
86
|
+
## Instance Events
|
|
87
|
+
|
|
88
|
+
### Event: `'connect'`
|
|
89
|
+
|
|
90
|
+
See [Dispatcher Event: `'connect'`](docs/api/Dispatcher.md#event-connect).
|
|
91
|
+
|
|
92
|
+
### Event: `'disconnect'`
|
|
93
|
+
|
|
94
|
+
See [Dispatcher Event: `'disconnect'`](docs/api/Dispatcher.md#event-connect).
|
|
95
|
+
|
|
96
|
+
### Event: `'drain'`
|
|
97
|
+
|
|
98
|
+
See [Dispatcher Event: `'drain'`](docs/api/Dispatcher.md#event-connect).
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Dispatcher = require('./types/dispatcher')
|
|
2
2
|
import { setGlobalDispatcher, getGlobalDispatcher } from './types/global-dispatcher'
|
|
3
3
|
import Pool = require('./types/pool')
|
|
4
|
+
import BalancedPool = require('./types/balanced-pool')
|
|
4
5
|
import Client = require('./types/client')
|
|
5
6
|
import buildConnector = require('./types/connector')
|
|
6
7
|
import errors = require('./types/errors')
|
|
@@ -15,7 +16,7 @@ export * from './types/fetch'
|
|
|
15
16
|
export * from './types/file'
|
|
16
17
|
export * from './types/formdata'
|
|
17
18
|
|
|
18
|
-
export { Dispatcher, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, MockClient, MockPool, MockAgent, mockErrors }
|
|
19
|
+
export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, MockClient, MockPool, MockAgent, mockErrors }
|
|
19
20
|
export default Undici
|
|
20
21
|
|
|
21
22
|
declare function Undici(url: string, opts: Pool.Options): Pool
|
|
@@ -23,6 +24,7 @@ declare function Undici(url: string, opts: Pool.Options): Pool
|
|
|
23
24
|
declare namespace Undici {
|
|
24
25
|
var Dispatcher: typeof import('./types/dispatcher')
|
|
25
26
|
var Pool: typeof import('./types/pool');
|
|
27
|
+
var BalancedPool: typeof import('./types/balanced-pool');
|
|
26
28
|
var Client: typeof import('./types/client');
|
|
27
29
|
var buildConnector: typeof import('./types/connector');
|
|
28
30
|
var errors: typeof import('./types/errors');
|
package/index.js
CHANGED
|
@@ -4,6 +4,7 @@ const Client = require('./lib/client')
|
|
|
4
4
|
const Dispatcher = require('./lib/dispatcher')
|
|
5
5
|
const errors = require('./lib/core/errors')
|
|
6
6
|
const Pool = require('./lib/pool')
|
|
7
|
+
const BalancedPool = require('./lib/balanced-pool')
|
|
7
8
|
const Agent = require('./lib/agent')
|
|
8
9
|
const util = require('./lib/core/util')
|
|
9
10
|
const { InvalidArgumentError } = errors
|
|
@@ -23,6 +24,7 @@ Object.assign(Dispatcher.prototype, api)
|
|
|
23
24
|
module.exports.Dispatcher = Dispatcher
|
|
24
25
|
module.exports.Client = Client
|
|
25
26
|
module.exports.Pool = Pool
|
|
27
|
+
module.exports.BalancedPool = BalancedPool
|
|
26
28
|
module.exports.Agent = Agent
|
|
27
29
|
|
|
28
30
|
module.exports.buildConnector = buildConnector
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { BalancedPoolMissingUpstreamError } = require('./core/errors')
|
|
4
|
+
const Dispatcher = require('./dispatcher')
|
|
5
|
+
const Pool = require('./pool')
|
|
6
|
+
|
|
7
|
+
const kPools = Symbol('kPools')
|
|
8
|
+
const kPoolOpts = Symbol('kPoolOpts')
|
|
9
|
+
const kUpstream = Symbol('kUpstream')
|
|
10
|
+
const kNeedDrain = Symbol('kNeedDrain')
|
|
11
|
+
|
|
12
|
+
class BalancedPool extends Dispatcher {
|
|
13
|
+
constructor (upstreams = [], opts = {}) {
|
|
14
|
+
super()
|
|
15
|
+
|
|
16
|
+
this[kPools] = []
|
|
17
|
+
this[kPoolOpts] = opts
|
|
18
|
+
this[kNeedDrain] = false
|
|
19
|
+
|
|
20
|
+
if (!Array.isArray(upstreams)) {
|
|
21
|
+
upstreams = [upstreams]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
for (const upstream of upstreams) {
|
|
25
|
+
this.addUpstream(upstream)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
addUpstream (upstream) {
|
|
30
|
+
if (this[kPools].find((pool) => pool[kUpstream] === upstream)) {
|
|
31
|
+
return this
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const pool = new Pool(upstream, Object.assign({}, this[kPoolOpts]))
|
|
35
|
+
|
|
36
|
+
pool[kUpstream] = upstream
|
|
37
|
+
|
|
38
|
+
pool.on('connect', (...args) => {
|
|
39
|
+
this.emit('connect', ...args)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
pool.on('disconnect', (...args) => {
|
|
43
|
+
this.emit('disconnect', ...args)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
pool.on('drain', (...args) => {
|
|
47
|
+
if (this[kNeedDrain]) {
|
|
48
|
+
this[kNeedDrain] = false
|
|
49
|
+
this.emit('drain', ...args)
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
this[kPools].push(pool)
|
|
54
|
+
return this
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
dispatch (opts, handler) {
|
|
58
|
+
// We validate that pools is greater than 0,
|
|
59
|
+
// otherwise we would have to wait until an upstream
|
|
60
|
+
// is added, which might never happen.
|
|
61
|
+
if (this[kPools].length === 0) {
|
|
62
|
+
throw new BalancedPoolMissingUpstreamError()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let pool = this[kPools].shift()
|
|
66
|
+
this[kPools].push(pool)
|
|
67
|
+
if (pool.busy) {
|
|
68
|
+
pool = this[kPools].find(pool => !pool.busy) || pool
|
|
69
|
+
}
|
|
70
|
+
this[kNeedDrain] = !pool.dispatch(opts, handler)
|
|
71
|
+
return !this[kNeedDrain]
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
removeUpstream (upstream) {
|
|
75
|
+
const pool = this[kPools].find((pool) => pool[kUpstream] === upstream)
|
|
76
|
+
const idx = this[kPools].indexOf(pool)
|
|
77
|
+
this[kPools].splice(idx, 1)
|
|
78
|
+
pool.close()
|
|
79
|
+
return this
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
get upstreams () {
|
|
83
|
+
return this[kPools].map((p) => p[kUpstream])
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
get destroyed () {
|
|
87
|
+
return this[kPools].reduce((acc, pool) => acc && pool.destroyed, true)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
get busy () {
|
|
91
|
+
return this[kPools].reduce((acc, pool) => acc && pool.busy, true) || false
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
get closed () {
|
|
95
|
+
return this[kPools].reduce((acc, pool) => acc && pool.closed, true)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
close (cb) {
|
|
99
|
+
const p = Promise.all(this[kPools].map((p) => p.close()))
|
|
100
|
+
|
|
101
|
+
if (!cb) {
|
|
102
|
+
return p
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
p.then(() => process.nextTick(cb), (err) => process.nextTick(cb, err))
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
destroy (err, cb) {
|
|
109
|
+
const p = Promise.all(this[kPools].map((p) => p.destroy(err)))
|
|
110
|
+
|
|
111
|
+
if (!cb) {
|
|
112
|
+
return p
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
p.then(() => process.nextTick(cb))
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
module.exports = BalancedPool
|
package/lib/core/errors.js
CHANGED
|
@@ -167,6 +167,16 @@ class NotSupportedError extends UndiciError {
|
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
+
class BalancedPoolMissingUpstreamError extends UndiciError {
|
|
171
|
+
constructor (message) {
|
|
172
|
+
super(message)
|
|
173
|
+
Error.captureStackTrace(this, NotSupportedError)
|
|
174
|
+
this.name = 'MissingUpstreamError'
|
|
175
|
+
this.message = message || 'No upstream has been added to the BalancedPool'
|
|
176
|
+
this.code = 'UND_ERR_BPL_MISSING_UPSTREAM'
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
170
180
|
class HTTPParserError extends Error {
|
|
171
181
|
constructor (message, code, data) {
|
|
172
182
|
super(message)
|
|
@@ -195,5 +205,6 @@ module.exports = {
|
|
|
195
205
|
InformationalError,
|
|
196
206
|
SocketError,
|
|
197
207
|
NotSupportedError,
|
|
198
|
-
ResponseContentLengthMismatchError
|
|
208
|
+
ResponseContentLengthMismatchError,
|
|
209
|
+
BalancedPoolMissingUpstreamError
|
|
199
210
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Client = require('./client')
|
|
2
|
+
import Pool = require('./pool')
|
|
3
|
+
import Dispatcher = require('./dispatcher')
|
|
4
|
+
import { URL } from 'url'
|
|
5
|
+
|
|
6
|
+
export = BalancedPool
|
|
7
|
+
|
|
8
|
+
declare class BalancedPool extends Dispatcher {
|
|
9
|
+
constructor(url: string | URL | string[], options?: Pool.Options);
|
|
10
|
+
|
|
11
|
+
addUpstream(upstream: string): BalancedPool;
|
|
12
|
+
removeUpstream(upstream: string): BalancedPool;
|
|
13
|
+
upstreams: Array<string>;
|
|
14
|
+
|
|
15
|
+
/** `true` after `pool.close()` has been called. */
|
|
16
|
+
closed: boolean;
|
|
17
|
+
/** `true` after `pool.destroyed()` has been called or `pool.close()` has been called and the pool shutdown has completed. */
|
|
18
|
+
destroyed: boolean;
|
|
19
|
+
}
|