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.
@@ -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
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "undici",
3
- "version": "4.7.3",
3
+ "version": "4.8.0",
4
4
  "description": "An HTTP/1.1 client, written from scratch for Node.js",
5
5
  "homepage": "https://undici.nodejs.org",
6
6
  "bugs": {
@@ -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
+ }