@per_moeller/asterisk-ari 1.0.2 → 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/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 (round-robin)
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
@@ -1 +1 @@
1
- {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAW,SAAS,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;GAEG;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;gBAEhB,OAAO,EAAE,WAAW;IAKhC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAejC;;OAEG;IACH,aAAa,IAAI,SAAS;IAU1B;;OAEG;IACH,sBAAsB,IAAI,SAAS,GAAG,SAAS;IAmB/C;;OAEG;IACH,cAAc,IAAI,SAAS,SAAS,EAAE;IAItC;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACG,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAI3E;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAI9E"}
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 (round-robin)
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":"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"}
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 request count
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 (reject all pending requests)
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
  }
@@ -1 +1 @@
1
- {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AASvD,KAAK,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAEpD;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;;CAKjD;AAED;;GAEG;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;gBAEnC,OAAO,GAAE,YAAiB;IAQtC;;OAEG;IACG,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAmBvD;;OAEG;YACW,YAAY;IAuB1B;;OAEG;YACW,cAAc;IA0B5B;;OAEG;IACH,OAAO,CAAC,WAAW;IAyBnB;;OAEG;IACH,OAAO,CAAC,SAAS;IAOjB;;OAEG;IACH,OAAO,CAAC,SAAS;IAQjB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,KAAK;IAIb;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,YAAY,CAGxB;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,KAAK,IAAI,IAAI;CAMd"}
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"}