11'use strict'
22
3- const { InvalidArgumentError } = require ( '../core/errors' )
3+ const { InvalidArgumentError, MaxOriginsReachedError } = require ( '../core/errors' )
44const { kClients, kRunning, kClose, kDestroy, kDispatch, kUrl } = require ( '../core/symbols' )
55const DispatcherBase = require ( './dispatcher-base' )
66const Pool = require ( './pool' )
@@ -13,6 +13,7 @@ const kOnConnectionError = Symbol('onConnectionError')
1313const kOnDrain = Symbol ( 'onDrain' )
1414const kFactory = Symbol ( 'factory' )
1515const kOptions = Symbol ( 'options' )
16+ const kOrigins = Symbol ( 'origins' )
1617
1718function defaultFactory ( origin , opts ) {
1819 return opts && opts . connections === 1
@@ -21,7 +22,7 @@ function defaultFactory (origin, opts) {
2122}
2223
2324class Agent extends DispatcherBase {
24- constructor ( { factory = defaultFactory , connect, ...options } = { } ) {
25+ constructor ( { factory = defaultFactory , maxOrigins = Infinity , connect, ...options } = { } ) {
2526 if ( typeof factory !== 'function' ) {
2627 throw new InvalidArgumentError ( 'factory must be a function.' )
2728 }
@@ -30,15 +31,20 @@ class Agent extends DispatcherBase {
3031 throw new InvalidArgumentError ( 'connect must be a function or an object' )
3132 }
3233
34+ if ( typeof maxOrigins !== 'number' || Number . isNaN ( maxOrigins ) || maxOrigins <= 0 ) {
35+ throw new InvalidArgumentError ( 'maxOrigins must be a number greater than 0' )
36+ }
37+
3338 super ( )
3439
3540 if ( connect && typeof connect !== 'function' ) {
3641 connect = { ...connect }
3742 }
3843
39- this [ kOptions ] = { ...util . deepClone ( options ) , connect }
44+ this [ kOptions ] = { ...util . deepClone ( options ) , maxOrigins , connect }
4045 this [ kFactory ] = factory
4146 this [ kClients ] = new Map ( )
47+ this [ kOrigins ] = new Set ( )
4248
4349 this [ kOnDrain ] = ( origin , targets ) => {
4450 this . emit ( 'drain' , origin , [ this , ...targets ] )
@@ -73,6 +79,10 @@ class Agent extends DispatcherBase {
7379 throw new InvalidArgumentError ( 'opts.origin must be a non-empty string or URL.' )
7480 }
7581
82+ if ( this [ kOrigins ] . size >= this [ kOptions ] . maxOrigins && ! this [ kOrigins ] . has ( key ) ) {
83+ throw new MaxOriginsReachedError ( )
84+ }
85+
7686 const result = this [ kClients ] . get ( key )
7787 let dispatcher = result && result . dispatcher
7888 if ( ! dispatcher ) {
@@ -84,6 +94,7 @@ class Agent extends DispatcherBase {
8494 this [ kClients ] . delete ( key )
8595 result . dispatcher . close ( )
8696 }
97+ this [ kOrigins ] . delete ( key )
8798 }
8899 }
89100 dispatcher = this [ kFactory ] ( opts . origin , this [ kOptions ] )
@@ -105,6 +116,7 @@ class Agent extends DispatcherBase {
105116 } )
106117
107118 this [ kClients ] . set ( key , { count : 0 , dispatcher } )
119+ this [ kOrigins ] . add ( key )
108120 }
109121
110122 return dispatcher . dispatch ( opts , handler )
0 commit comments