@per_moeller/asterisk-ari 1.0.3 → 1.0.4
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/dist/client.d.ts +360 -22
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +374 -29
- package/dist/client.js.map +1 -1
- package/dist/connection.d.ts +132 -12
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +121 -10
- package/dist/connection.js.map +1 -1
- package/dist/events/emitter.d.ts +213 -21
- package/dist/events/emitter.d.ts.map +1 -1
- package/dist/events/emitter.js +163 -17
- package/dist/events/emitter.js.map +1 -1
- package/dist/events/types.d.ts +386 -3
- package/dist/events/types.d.ts.map +1 -1
- package/dist/events/types.js +5 -0
- package/dist/events/types.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/models/channel.d.ts +349 -32
- package/dist/models/channel.d.ts.map +1 -1
- package/dist/models/channel.js +348 -34
- package/dist/models/channel.js.map +1 -1
- package/dist/pool.d.ts +152 -11
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +152 -11
- package/dist/pool.js.map +1 -1
- package/dist/queue.d.ts +130 -16
- package/dist/queue.d.ts.map +1 -1
- package/dist/queue.js +123 -16
- package/dist/queue.js.map +1 -1
- package/dist/types/api.d.ts +655 -1
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/api.js +5 -0
- package/dist/types/api.js.map +1 -1
- package/dist/version.d.ts +163 -26
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +143 -22
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
package/dist/pool.d.ts
CHANGED
|
@@ -1,10 +1,50 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Connection pool for high-throughput scenarios
|
|
3
|
+
*
|
|
4
|
+
* This module provides a connection pool that maintains multiple ARI connections
|
|
5
|
+
* for distributing load in high-volume call processing scenarios.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
3
8
|
*/
|
|
4
9
|
import { AriClient } from './client.js';
|
|
5
10
|
import type { PoolOptions } from './types/options.js';
|
|
6
11
|
/**
|
|
7
|
-
* Connection pool for distributing load across multiple ARI connections
|
|
12
|
+
* Connection pool for distributing load across multiple ARI connections.
|
|
13
|
+
*
|
|
14
|
+
* In high-throughput scenarios, a single ARI connection may become a bottleneck.
|
|
15
|
+
* The connection pool maintains multiple connections and distributes requests
|
|
16
|
+
* across them using round-robin selection.
|
|
17
|
+
*
|
|
18
|
+
* @remarks
|
|
19
|
+
* All connections in the pool connect to the same Asterisk server and share
|
|
20
|
+
* the same application name. Events will be received on all connections,
|
|
21
|
+
* so you typically only need to set up event listeners on one client.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* import { createPool } from '@per_moeller/asterisk-ari';
|
|
26
|
+
*
|
|
27
|
+
* // Create a pool with 5 connections
|
|
28
|
+
* const pool = await createPool({
|
|
29
|
+
* url: 'http://localhost:8088',
|
|
30
|
+
* username: 'asterisk',
|
|
31
|
+
* password: 'secret',
|
|
32
|
+
* app: 'my-app',
|
|
33
|
+
* poolSize: 5
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* // Get a connection for making requests
|
|
37
|
+
* const client = pool.getConnection();
|
|
38
|
+
* const channels = await client.channels.list();
|
|
39
|
+
*
|
|
40
|
+
* // Use withConnection for automatic selection
|
|
41
|
+
* const result = await pool.withConnection(async (client) => {
|
|
42
|
+
* return client.channels.originate({ ... });
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* // Clean up
|
|
46
|
+
* await pool.stop();
|
|
47
|
+
* ```
|
|
8
48
|
*/
|
|
9
49
|
export declare class ConnectionPool {
|
|
10
50
|
private connections;
|
|
@@ -12,46 +52,147 @@ export declare class ConnectionPool {
|
|
|
12
52
|
private readonly options;
|
|
13
53
|
private readonly poolSize;
|
|
14
54
|
private initialized;
|
|
55
|
+
/**
|
|
56
|
+
* Create a new connection pool.
|
|
57
|
+
*
|
|
58
|
+
* @param options - Pool options including connection settings and pool size
|
|
59
|
+
*
|
|
60
|
+
* @remarks
|
|
61
|
+
* The pool is not immediately connected. Call {@link initialize} or use
|
|
62
|
+
* the {@link createPool} helper function to create an initialized pool.
|
|
63
|
+
*/
|
|
15
64
|
constructor(options: PoolOptions);
|
|
16
65
|
/**
|
|
17
|
-
* Initialize the connection pool
|
|
66
|
+
* Initialize the connection pool by creating all connections.
|
|
67
|
+
*
|
|
68
|
+
* Creates `poolSize` number of connections in parallel and waits for
|
|
69
|
+
* all of them to be established.
|
|
70
|
+
*
|
|
71
|
+
* @returns Promise that resolves when all connections are established
|
|
72
|
+
* @throws {AriHttpError} If any connection fails
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const pool = new ConnectionPool(options);
|
|
77
|
+
* await pool.initialize();
|
|
78
|
+
* ```
|
|
18
79
|
*/
|
|
19
80
|
initialize(): Promise<void>;
|
|
20
81
|
/**
|
|
21
|
-
* Get a connection from the pool
|
|
82
|
+
* Get a connection from the pool using round-robin selection.
|
|
83
|
+
*
|
|
84
|
+
* Each call returns the next connection in the pool, cycling back
|
|
85
|
+
* to the first after reaching the last.
|
|
86
|
+
*
|
|
87
|
+
* @returns An ARI client from the pool
|
|
88
|
+
* @throws {Error} If the pool is not initialized
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* const client = pool.getConnection();
|
|
93
|
+
* await client.channels.list();
|
|
94
|
+
* ```
|
|
22
95
|
*/
|
|
23
96
|
getConnection(): AriClient;
|
|
24
97
|
/**
|
|
25
|
-
* Get a connection that is currently connected
|
|
98
|
+
* Get a connection that is currently connected.
|
|
99
|
+
*
|
|
100
|
+
* Searches through the pool using round-robin to find a connected client.
|
|
101
|
+
* Returns undefined if no connections are available.
|
|
102
|
+
*
|
|
103
|
+
* @returns A connected ARI client, or undefined if none are connected
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const client = pool.getConnectedConnection();
|
|
108
|
+
* if (client) {
|
|
109
|
+
* await client.channels.list();
|
|
110
|
+
* } else {
|
|
111
|
+
* console.log('No connections available');
|
|
112
|
+
* }
|
|
113
|
+
* ```
|
|
26
114
|
*/
|
|
27
115
|
getConnectedConnection(): AriClient | undefined;
|
|
28
116
|
/**
|
|
29
|
-
* Get all connections in the pool
|
|
117
|
+
* Get all connections in the pool.
|
|
118
|
+
*
|
|
119
|
+
* @returns Read-only array of all ARI clients in the pool
|
|
30
120
|
*/
|
|
31
121
|
getConnections(): readonly AriClient[];
|
|
32
122
|
/**
|
|
33
|
-
* Get the number of connections in the pool
|
|
123
|
+
* Get the total number of connections in the pool.
|
|
34
124
|
*/
|
|
35
125
|
get size(): number;
|
|
36
126
|
/**
|
|
37
|
-
* Get the number of connected clients
|
|
127
|
+
* Get the number of currently connected clients.
|
|
38
128
|
*/
|
|
39
129
|
get connectedCount(): number;
|
|
40
130
|
/**
|
|
41
|
-
* Stop all connections in the pool
|
|
131
|
+
* Stop all connections in the pool.
|
|
132
|
+
*
|
|
133
|
+
* Disconnects all clients and resets the pool state. The pool can be
|
|
134
|
+
* re-initialized after calling stop.
|
|
135
|
+
*
|
|
136
|
+
* @returns Promise that resolves when all connections are stopped
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* // Graceful shutdown
|
|
141
|
+
* await pool.stop();
|
|
142
|
+
* ```
|
|
42
143
|
*/
|
|
43
144
|
stop(): Promise<void>;
|
|
44
145
|
/**
|
|
45
|
-
* Check if the pool is initialized
|
|
146
|
+
* Check if the pool is initialized.
|
|
147
|
+
*
|
|
148
|
+
* @returns `true` if initialize() has been called successfully
|
|
46
149
|
*/
|
|
47
150
|
isInitialized(): boolean;
|
|
48
151
|
/**
|
|
49
|
-
* Execute a function with a pooled connection
|
|
152
|
+
* Execute a function with a pooled connection.
|
|
153
|
+
*
|
|
154
|
+
* Automatically selects a connection from the pool and passes it to
|
|
155
|
+
* the provided function. Useful for one-off operations.
|
|
156
|
+
*
|
|
157
|
+
* @typeParam T - Return type of the function
|
|
158
|
+
* @param fn - Function to execute with the connection
|
|
159
|
+
* @returns Promise resolving to the function's return value
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* const channels = await pool.withConnection(async (client) => {
|
|
164
|
+
* return client.channels.list();
|
|
165
|
+
* });
|
|
166
|
+
*
|
|
167
|
+
* const bridge = await pool.withConnection(async (client) => {
|
|
168
|
+
* return client.bridges.create({ type: 'mixing' });
|
|
169
|
+
* });
|
|
170
|
+
* ```
|
|
50
171
|
*/
|
|
51
172
|
withConnection<T>(fn: (client: AriClient) => Promise<T>): Promise<T>;
|
|
52
173
|
}
|
|
53
174
|
/**
|
|
54
|
-
* Create and initialize a connection pool
|
|
175
|
+
* Create and initialize a connection pool.
|
|
176
|
+
*
|
|
177
|
+
* This is a convenience function that creates a pool and initializes it
|
|
178
|
+
* in one step.
|
|
179
|
+
*
|
|
180
|
+
* @param options - Pool options including connection settings and pool size
|
|
181
|
+
* @returns Promise resolving to an initialized connection pool
|
|
182
|
+
* @throws {AriHttpError} If any connection fails
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```typescript
|
|
186
|
+
* const pool = await createPool({
|
|
187
|
+
* url: 'http://localhost:8088',
|
|
188
|
+
* username: 'asterisk',
|
|
189
|
+
* password: 'secret',
|
|
190
|
+
* app: 'my-app',
|
|
191
|
+
* poolSize: 10
|
|
192
|
+
* });
|
|
193
|
+
*
|
|
194
|
+
* console.log(`Pool has ${pool.size} connections`);
|
|
195
|
+
* ```
|
|
55
196
|
*/
|
|
56
197
|
export declare function createPool(options: PoolOptions): Promise<ConnectionPool>;
|
|
57
198
|
//# sourceMappingURL=pool.d.ts.map
|
package/dist/pool.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAW,SAAS,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,WAAW,CAAS;IAE5B;;;;;;;;OAQG;gBACS,OAAO,EAAE,WAAW;IAKhC;;;;;;;;;;;;;;OAcG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAejC;;;;;;;;;;;;;;OAcG;IACH,aAAa,IAAI,SAAS;IAU1B;;;;;;;;;;;;;;;;;OAiBG;IACH,sBAAsB,IAAI,SAAS,GAAG,SAAS;IAmB/C;;;;OAIG;IACH,cAAc,IAAI,SAAS,SAAS,EAAE;IAItC;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED;;;;;;;;;;;;;OAaG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B;;;;OAIG;IACH,aAAa,IAAI,OAAO;IAIxB;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAI3E;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAI9E"}
|
package/dist/pool.js
CHANGED
|
@@ -1,9 +1,49 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Connection pool for high-throughput scenarios
|
|
3
|
+
*
|
|
4
|
+
* This module provides a connection pool that maintains multiple ARI connections
|
|
5
|
+
* for distributing load in high-volume call processing scenarios.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
3
8
|
*/
|
|
4
9
|
import { connect } from './client.js';
|
|
5
10
|
/**
|
|
6
|
-
* Connection pool for distributing load across multiple ARI connections
|
|
11
|
+
* Connection pool for distributing load across multiple ARI connections.
|
|
12
|
+
*
|
|
13
|
+
* In high-throughput scenarios, a single ARI connection may become a bottleneck.
|
|
14
|
+
* The connection pool maintains multiple connections and distributes requests
|
|
15
|
+
* across them using round-robin selection.
|
|
16
|
+
*
|
|
17
|
+
* @remarks
|
|
18
|
+
* All connections in the pool connect to the same Asterisk server and share
|
|
19
|
+
* the same application name. Events will be received on all connections,
|
|
20
|
+
* so you typically only need to set up event listeners on one client.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { createPool } from '@per_moeller/asterisk-ari';
|
|
25
|
+
*
|
|
26
|
+
* // Create a pool with 5 connections
|
|
27
|
+
* const pool = await createPool({
|
|
28
|
+
* url: 'http://localhost:8088',
|
|
29
|
+
* username: 'asterisk',
|
|
30
|
+
* password: 'secret',
|
|
31
|
+
* app: 'my-app',
|
|
32
|
+
* poolSize: 5
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* // Get a connection for making requests
|
|
36
|
+
* const client = pool.getConnection();
|
|
37
|
+
* const channels = await client.channels.list();
|
|
38
|
+
*
|
|
39
|
+
* // Use withConnection for automatic selection
|
|
40
|
+
* const result = await pool.withConnection(async (client) => {
|
|
41
|
+
* return client.channels.originate({ ... });
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* // Clean up
|
|
45
|
+
* await pool.stop();
|
|
46
|
+
* ```
|
|
7
47
|
*/
|
|
8
48
|
export class ConnectionPool {
|
|
9
49
|
connections = [];
|
|
@@ -11,12 +51,33 @@ export class ConnectionPool {
|
|
|
11
51
|
options;
|
|
12
52
|
poolSize;
|
|
13
53
|
initialized = false;
|
|
54
|
+
/**
|
|
55
|
+
* Create a new connection pool.
|
|
56
|
+
*
|
|
57
|
+
* @param options - Pool options including connection settings and pool size
|
|
58
|
+
*
|
|
59
|
+
* @remarks
|
|
60
|
+
* The pool is not immediately connected. Call {@link initialize} or use
|
|
61
|
+
* the {@link createPool} helper function to create an initialized pool.
|
|
62
|
+
*/
|
|
14
63
|
constructor(options) {
|
|
15
64
|
this.options = options;
|
|
16
65
|
this.poolSize = options.poolSize ?? 5;
|
|
17
66
|
}
|
|
18
67
|
/**
|
|
19
|
-
* Initialize the connection pool
|
|
68
|
+
* Initialize the connection pool by creating all connections.
|
|
69
|
+
*
|
|
70
|
+
* Creates `poolSize` number of connections in parallel and waits for
|
|
71
|
+
* all of them to be established.
|
|
72
|
+
*
|
|
73
|
+
* @returns Promise that resolves when all connections are established
|
|
74
|
+
* @throws {AriHttpError} If any connection fails
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const pool = new ConnectionPool(options);
|
|
79
|
+
* await pool.initialize();
|
|
80
|
+
* ```
|
|
20
81
|
*/
|
|
21
82
|
async initialize() {
|
|
22
83
|
if (this.initialized) {
|
|
@@ -30,7 +91,19 @@ export class ConnectionPool {
|
|
|
30
91
|
this.initialized = true;
|
|
31
92
|
}
|
|
32
93
|
/**
|
|
33
|
-
* Get a connection from the pool
|
|
94
|
+
* Get a connection from the pool using round-robin selection.
|
|
95
|
+
*
|
|
96
|
+
* Each call returns the next connection in the pool, cycling back
|
|
97
|
+
* to the first after reaching the last.
|
|
98
|
+
*
|
|
99
|
+
* @returns An ARI client from the pool
|
|
100
|
+
* @throws {Error} If the pool is not initialized
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const client = pool.getConnection();
|
|
105
|
+
* await client.channels.list();
|
|
106
|
+
* ```
|
|
34
107
|
*/
|
|
35
108
|
getConnection() {
|
|
36
109
|
if (!this.initialized || this.connections.length === 0) {
|
|
@@ -41,7 +114,22 @@ export class ConnectionPool {
|
|
|
41
114
|
return client;
|
|
42
115
|
}
|
|
43
116
|
/**
|
|
44
|
-
* Get a connection that is currently connected
|
|
117
|
+
* Get a connection that is currently connected.
|
|
118
|
+
*
|
|
119
|
+
* Searches through the pool using round-robin to find a connected client.
|
|
120
|
+
* Returns undefined if no connections are available.
|
|
121
|
+
*
|
|
122
|
+
* @returns A connected ARI client, or undefined if none are connected
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* const client = pool.getConnectedConnection();
|
|
127
|
+
* if (client) {
|
|
128
|
+
* await client.channels.list();
|
|
129
|
+
* } else {
|
|
130
|
+
* console.log('No connections available');
|
|
131
|
+
* }
|
|
132
|
+
* ```
|
|
45
133
|
*/
|
|
46
134
|
getConnectedConnection() {
|
|
47
135
|
if (!this.initialized) {
|
|
@@ -59,25 +147,38 @@ export class ConnectionPool {
|
|
|
59
147
|
return undefined;
|
|
60
148
|
}
|
|
61
149
|
/**
|
|
62
|
-
* Get all connections in the pool
|
|
150
|
+
* Get all connections in the pool.
|
|
151
|
+
*
|
|
152
|
+
* @returns Read-only array of all ARI clients in the pool
|
|
63
153
|
*/
|
|
64
154
|
getConnections() {
|
|
65
155
|
return this.connections;
|
|
66
156
|
}
|
|
67
157
|
/**
|
|
68
|
-
* Get the number of connections in the pool
|
|
158
|
+
* Get the total number of connections in the pool.
|
|
69
159
|
*/
|
|
70
160
|
get size() {
|
|
71
161
|
return this.connections.length;
|
|
72
162
|
}
|
|
73
163
|
/**
|
|
74
|
-
* Get the number of connected clients
|
|
164
|
+
* Get the number of currently connected clients.
|
|
75
165
|
*/
|
|
76
166
|
get connectedCount() {
|
|
77
167
|
return this.connections.filter(c => c.isConnected()).length;
|
|
78
168
|
}
|
|
79
169
|
/**
|
|
80
|
-
* Stop all connections in the pool
|
|
170
|
+
* Stop all connections in the pool.
|
|
171
|
+
*
|
|
172
|
+
* Disconnects all clients and resets the pool state. The pool can be
|
|
173
|
+
* re-initialized after calling stop.
|
|
174
|
+
*
|
|
175
|
+
* @returns Promise that resolves when all connections are stopped
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* ```typescript
|
|
179
|
+
* // Graceful shutdown
|
|
180
|
+
* await pool.stop();
|
|
181
|
+
* ```
|
|
81
182
|
*/
|
|
82
183
|
async stop() {
|
|
83
184
|
const stopPromises = this.connections.map(c => c.stop());
|
|
@@ -87,13 +188,33 @@ export class ConnectionPool {
|
|
|
87
188
|
this.initialized = false;
|
|
88
189
|
}
|
|
89
190
|
/**
|
|
90
|
-
* Check if the pool is initialized
|
|
191
|
+
* Check if the pool is initialized.
|
|
192
|
+
*
|
|
193
|
+
* @returns `true` if initialize() has been called successfully
|
|
91
194
|
*/
|
|
92
195
|
isInitialized() {
|
|
93
196
|
return this.initialized;
|
|
94
197
|
}
|
|
95
198
|
/**
|
|
96
|
-
* Execute a function with a pooled connection
|
|
199
|
+
* Execute a function with a pooled connection.
|
|
200
|
+
*
|
|
201
|
+
* Automatically selects a connection from the pool and passes it to
|
|
202
|
+
* the provided function. Useful for one-off operations.
|
|
203
|
+
*
|
|
204
|
+
* @typeParam T - Return type of the function
|
|
205
|
+
* @param fn - Function to execute with the connection
|
|
206
|
+
* @returns Promise resolving to the function's return value
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```typescript
|
|
210
|
+
* const channels = await pool.withConnection(async (client) => {
|
|
211
|
+
* return client.channels.list();
|
|
212
|
+
* });
|
|
213
|
+
*
|
|
214
|
+
* const bridge = await pool.withConnection(async (client) => {
|
|
215
|
+
* return client.bridges.create({ type: 'mixing' });
|
|
216
|
+
* });
|
|
217
|
+
* ```
|
|
97
218
|
*/
|
|
98
219
|
async withConnection(fn) {
|
|
99
220
|
const client = this.getConnection();
|
|
@@ -101,7 +222,27 @@ export class ConnectionPool {
|
|
|
101
222
|
}
|
|
102
223
|
}
|
|
103
224
|
/**
|
|
104
|
-
* Create and initialize a connection pool
|
|
225
|
+
* Create and initialize a connection pool.
|
|
226
|
+
*
|
|
227
|
+
* This is a convenience function that creates a pool and initializes it
|
|
228
|
+
* in one step.
|
|
229
|
+
*
|
|
230
|
+
* @param options - Pool options including connection settings and pool size
|
|
231
|
+
* @returns Promise resolving to an initialized connection pool
|
|
232
|
+
* @throws {AriHttpError} If any connection fails
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* const pool = await createPool({
|
|
237
|
+
* url: 'http://localhost:8088',
|
|
238
|
+
* username: 'asterisk',
|
|
239
|
+
* password: 'secret',
|
|
240
|
+
* app: 'my-app',
|
|
241
|
+
* poolSize: 10
|
|
242
|
+
* });
|
|
243
|
+
*
|
|
244
|
+
* console.log(`Pool has ${pool.size} connections`);
|
|
245
|
+
* ```
|
|
105
246
|
*/
|
|
106
247
|
export async function createPool(options) {
|
|
107
248
|
const pool = new ConnectionPool(options);
|
package/dist/pool.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool.js","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pool.js","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"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"}
|
package/dist/queue.d.ts
CHANGED
|
@@ -1,16 +1,80 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Request queue with retry and circuit breaker
|
|
3
|
+
*
|
|
4
|
+
* This module provides a request queue that handles automatic retries
|
|
5
|
+
* and implements the circuit breaker pattern for fault tolerance.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
3
8
|
*/
|
|
4
9
|
import type { QueueOptions } from './types/options.js';
|
|
10
|
+
/**
|
|
11
|
+
* Circuit breaker state.
|
|
12
|
+
*
|
|
13
|
+
* - `closed` - Normal operation, requests are processed
|
|
14
|
+
* - `open` - Too many failures, requests are rejected immediately
|
|
15
|
+
* - `half-open` - Testing if the system has recovered
|
|
16
|
+
*/
|
|
5
17
|
type CircuitState = 'closed' | 'open' | 'half-open';
|
|
6
18
|
/**
|
|
7
|
-
* Error thrown when circuit breaker is open
|
|
19
|
+
* Error thrown when the circuit breaker is open.
|
|
20
|
+
*
|
|
21
|
+
* This error is thrown immediately when attempting to enqueue a request
|
|
22
|
+
* while the circuit breaker is in the open state, without attempting
|
|
23
|
+
* the actual request.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* try {
|
|
28
|
+
* await queue.enqueue(() => client.channels.list());
|
|
29
|
+
* } catch (error) {
|
|
30
|
+
* if (error instanceof CircuitBreakerOpenError) {
|
|
31
|
+
* console.log('Service temporarily unavailable');
|
|
32
|
+
* }
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
8
35
|
*/
|
|
9
36
|
export declare class CircuitBreakerOpenError extends Error {
|
|
10
37
|
constructor();
|
|
11
38
|
}
|
|
12
39
|
/**
|
|
13
|
-
* Request queue with automatic retry and circuit breaker pattern
|
|
40
|
+
* Request queue with automatic retry and circuit breaker pattern.
|
|
41
|
+
*
|
|
42
|
+
* Provides controlled request execution with:
|
|
43
|
+
* - Concurrent request limiting
|
|
44
|
+
* - Automatic retry with exponential backoff
|
|
45
|
+
* - Circuit breaker to prevent cascading failures
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
* The circuit breaker pattern helps prevent overwhelming a failing service.
|
|
49
|
+
* After a threshold of failures, the circuit "opens" and rejects requests
|
|
50
|
+
* immediately. After a timeout, it enters "half-open" state to test if the
|
|
51
|
+
* service has recovered.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* import { RequestQueue } from '@per_moeller/asterisk-ari';
|
|
56
|
+
*
|
|
57
|
+
* const queue = new RequestQueue({
|
|
58
|
+
* maxConcurrent: 10,
|
|
59
|
+
* maxRetries: 3,
|
|
60
|
+
* retryDelay: 1000,
|
|
61
|
+
* circuitBreakerThreshold: 5,
|
|
62
|
+
* circuitBreakerTimeout: 30000
|
|
63
|
+
* });
|
|
64
|
+
*
|
|
65
|
+
* // Enqueue requests
|
|
66
|
+
* const result = await queue.enqueue(async () => {
|
|
67
|
+
* return fetch('https://api.example.com/data');
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* // Check circuit breaker state
|
|
71
|
+
* if (queue.state === 'open') {
|
|
72
|
+
* console.log('Circuit breaker is open, requests will fail fast');
|
|
73
|
+
* }
|
|
74
|
+
*
|
|
75
|
+
* // Reset if needed
|
|
76
|
+
* queue.reset();
|
|
77
|
+
* ```
|
|
14
78
|
*/
|
|
15
79
|
export declare class RequestQueue {
|
|
16
80
|
private queue;
|
|
@@ -23,61 +87,111 @@ export declare class RequestQueue {
|
|
|
23
87
|
private readonly retryDelay;
|
|
24
88
|
private readonly circuitBreakerThreshold;
|
|
25
89
|
private readonly circuitBreakerTimeout;
|
|
90
|
+
/**
|
|
91
|
+
* Create a new request queue.
|
|
92
|
+
*
|
|
93
|
+
* @param options - Queue configuration options
|
|
94
|
+
*/
|
|
26
95
|
constructor(options?: QueueOptions);
|
|
27
96
|
/**
|
|
28
|
-
* Enqueue a request
|
|
97
|
+
* Enqueue a request for execution.
|
|
98
|
+
*
|
|
99
|
+
* The request will be executed when a slot is available (based on
|
|
100
|
+
* maxConcurrent). If the request fails, it will be automatically
|
|
101
|
+
* retried up to maxRetries times with exponential backoff.
|
|
102
|
+
*
|
|
103
|
+
* @typeParam T - Return type of the request
|
|
104
|
+
* @param request - Async function that performs the request
|
|
105
|
+
* @returns Promise resolving to the request result
|
|
106
|
+
* @throws {CircuitBreakerOpenError} If the circuit breaker is open
|
|
107
|
+
* @throws {Error} If the request fails after all retries
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* const channels = await queue.enqueue(async () => {
|
|
112
|
+
* return client.channels.list();
|
|
113
|
+
* });
|
|
114
|
+
* ```
|
|
29
115
|
*/
|
|
30
116
|
enqueue<T>(request: () => Promise<T>): Promise<T>;
|
|
31
117
|
/**
|
|
32
|
-
* Process the queue
|
|
118
|
+
* Process the queue by executing pending requests.
|
|
119
|
+
* @internal
|
|
33
120
|
*/
|
|
34
121
|
private processQueue;
|
|
35
122
|
/**
|
|
36
|
-
* Execute a single request with retry logic
|
|
123
|
+
* Execute a single request with retry logic.
|
|
124
|
+
* @internal
|
|
37
125
|
*/
|
|
38
126
|
private executeRequest;
|
|
39
127
|
/**
|
|
40
|
-
* Check if an error is retryable
|
|
128
|
+
* Check if an error is retryable.
|
|
129
|
+
* @internal
|
|
41
130
|
*/
|
|
42
131
|
private isRetryable;
|
|
43
132
|
/**
|
|
44
|
-
* Called on successful request
|
|
133
|
+
* Called on successful request to reset failure count.
|
|
134
|
+
* @internal
|
|
45
135
|
*/
|
|
46
136
|
private onSuccess;
|
|
47
137
|
/**
|
|
48
|
-
* Called on failed request
|
|
138
|
+
* Called on failed request to track failures.
|
|
139
|
+
* @internal
|
|
49
140
|
*/
|
|
50
141
|
private onFailure;
|
|
51
142
|
/**
|
|
52
|
-
* Update circuit breaker state based on timeout
|
|
143
|
+
* Update circuit breaker state based on timeout.
|
|
144
|
+
* @internal
|
|
53
145
|
*/
|
|
54
146
|
private updateCircuitState;
|
|
55
147
|
/**
|
|
56
|
-
* Delay helper
|
|
148
|
+
* Delay helper for retry backoff.
|
|
149
|
+
* @internal
|
|
57
150
|
*/
|
|
58
151
|
private delay;
|
|
59
152
|
/**
|
|
60
|
-
* Get current queue length
|
|
153
|
+
* Get the current queue length (pending requests).
|
|
61
154
|
*/
|
|
62
155
|
get length(): number;
|
|
63
156
|
/**
|
|
64
|
-
* Get current active
|
|
157
|
+
* Get the current number of active (executing) requests.
|
|
65
158
|
*/
|
|
66
159
|
get active(): number;
|
|
67
160
|
/**
|
|
68
|
-
* Get current circuit breaker state
|
|
161
|
+
* Get the current circuit breaker state.
|
|
162
|
+
*
|
|
163
|
+
* @returns Current state: 'closed', 'open', or 'half-open'
|
|
69
164
|
*/
|
|
70
165
|
get state(): CircuitState;
|
|
71
166
|
/**
|
|
72
|
-
* Get failure count
|
|
167
|
+
* Get the current consecutive failure count.
|
|
73
168
|
*/
|
|
74
169
|
get failures(): number;
|
|
75
170
|
/**
|
|
76
|
-
* Reset the circuit breaker
|
|
171
|
+
* Reset the circuit breaker to closed state.
|
|
172
|
+
*
|
|
173
|
+
* This clears the failure count and allows requests to proceed normally.
|
|
174
|
+
* Use this after fixing the underlying issue that caused failures.
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```typescript
|
|
178
|
+
* // After fixing the issue
|
|
179
|
+
* queue.reset();
|
|
180
|
+
* console.log(queue.state); // 'closed'
|
|
181
|
+
* ```
|
|
77
182
|
*/
|
|
78
183
|
reset(): void;
|
|
79
184
|
/**
|
|
80
|
-
* Clear the queue
|
|
185
|
+
* Clear the queue and reject all pending requests.
|
|
186
|
+
*
|
|
187
|
+
* Active requests will continue to execute, but pending requests
|
|
188
|
+
* in the queue will be rejected with an error.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```typescript
|
|
192
|
+
* // Cancel all pending requests
|
|
193
|
+
* queue.clear();
|
|
194
|
+
* ```
|
|
81
195
|
*/
|
|
82
196
|
clear(): void;
|
|
83
197
|
}
|
package/dist/queue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AASvD;;;;;;GAMG;AACH,KAAK,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAEpD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;;CAKjD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,eAAe,CAAK;IAE5B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAS;IACjD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAE/C;;;;OAIG;gBACS,OAAO,GAAE,YAAiB;IAQtC;;;;;;;;;;;;;;;;;;;OAmBG;IACG,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAmBvD;;;OAGG;YACW,YAAY;IAuB1B;;;OAGG;YACW,cAAc;IA0B5B;;;OAGG;IACH,OAAO,CAAC,WAAW;IAyBnB;;;OAGG;IACH,OAAO,CAAC,SAAS;IAOjB;;;OAGG;IACH,OAAO,CAAC,SAAS;IAQjB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;;OAGG;IACH,OAAO,CAAC,KAAK;IAIb;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;;;OAIG;IACH,IAAI,KAAK,IAAI,YAAY,CAGxB;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,IAAI,IAAI;IAMb;;;;;;;;;;;OAWG;IACH,KAAK,IAAI,IAAI;CAMd"}
|