@orkestrel/pool 0.0.8 → 0.0.10

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.
@@ -3,252 +3,287 @@ import { EmitterHooks } from '@orkestrel/emitter';
3
3
  import { EmitterInterface } from '@orkestrel/emitter';
4
4
 
5
5
  /**
6
- * Create a resource pool with optional bounded capacity, unique ownership, and FIFO settlement.
6
+ * Creates a resource pool with optional bounded capacity, unique ownership, and FIFO settlement.
7
7
  *
8
8
  * @remarks
9
9
  * Concurrent create and validation hooks may overlap, while acquire promises settle in
10
10
  * request order. `clear` owns its idle snapshot; `destroy` returns one stable barrier and
11
- * waits for every in-flight hook and cleanup before destroying the emitter last.
11
+ * waits for every in-flight create, validation, and destroy attempt before destroying the
12
+ * emitter last.
12
13
  *
13
14
  * @typeParam T - The pooled resource type
14
15
  * @param options - Lifecycle hooks, optional positive safe `max`, and observation hooks
15
16
  * @returns A working {@link PoolInterface}
16
- *
17
- * @example
18
- * ```ts
19
- * import { createPool } from '@orkestrel/pool'
20
- *
21
- * const pool = createPool<Connection>({
22
- * create: () => connect(),
23
- * destroy: (connection) => connection.close(),
24
- * validate: (connection) => connection.alive,
25
- * max: 8,
26
- * })
27
- *
28
- * const token = await pool.acquire()
29
- * try {
30
- * await token.value.query('select 1')
31
- * } finally {
32
- * token.release()
33
- * }
34
- * ```
35
- */
36
- export declare function createPool<T>(options: PoolOptions<T>): PoolInterface<T>;
37
-
38
- /**
39
- * Test whether an unknown value is a {@link PoolError}, returning `false` for hostile proxies.
40
- *
41
- * @param value - The unknown boundary value
42
- * @returns Whether the value is a real `PoolError` instance
43
- *
44
- * @example
45
- * ```ts
46
- * isPoolError(new PoolError({ code: 'destroyed' })) // true
47
- * isPoolError(new Error('other')) // false
48
- * ```
49
- */
50
- export declare function isPoolError(value: unknown): value is PoolError;
51
-
52
- /**
53
- * Test whether a value is a valid finite pool maximum.
54
- *
55
- * @param value - The unknown maximum candidate
56
- * @returns Whether the value is a positive safe integer
57
- *
58
- * @example
59
- * ```ts
60
- * isPoolMax(8) // true
61
- * isPoolMax(Infinity) // false
62
- * ```
63
- */
64
- export declare function isPoolMax(value: unknown): value is number;
65
-
66
- /**
67
- * Test whether a value is a native `AbortSignal`, returning `false` for hostile proxies.
68
- *
69
- * @param value - The unknown signal candidate
70
- * @returns Whether the value is a native `AbortSignal`
71
- *
72
- * @example
73
- * ```ts
74
- * isPoolSignal(new AbortController().signal) // true
75
- * isPoolSignal({ aborted: false }) // false
76
- * ```
77
- */
78
- export declare function isPoolSignal(value: unknown): value is AbortSignal;
79
-
80
- /**
81
- * A capacity-aware resource pool whose opaque ownership records preserve FIFO settlement,
82
- * cancellation, exact lease release, and deterministic teardown under concurrent hooks.
83
- *
84
- * @typeParam T - The pooled resource value
85
- *
86
- * @example
87
- * ```ts
88
- * import { Pool } from '@orkestrel/pool'
89
- *
90
- * const pool = new Pool({ create: () => new Uint8Array(64), max: 2 })
91
- * const token = await pool.acquire()
92
- * try {
93
- * consume(token.value)
94
- * } finally {
95
- * token.release()
96
- * }
97
- * await pool.destroy()
98
- * ```
99
- */
100
- export declare class Pool<T> implements PoolInterface<T> {
101
- #private;
102
- /**
103
- * Construct a pool and synchronously validate its capacity contract.
104
- *
105
- * @param options - Resource hooks, observation hooks, and optional positive safe `max`
106
- */
107
- constructor(options: PoolOptions<T>);
108
- /** The typed synchronous lifecycle observation surface. */
109
- get emitter(): EmitterInterface<PoolEventMap>;
110
- /** All owned records, including records validating or destroying. */
111
- get size(): number;
112
- /** Records immediately available without validation work. */
113
- get idle(): number;
114
- /** Records represented by unsettled released-once lease tokens. */
115
- get active(): number;
116
- /**
117
- * Queue and lease one resource in FIFO settlement order.
17
+ * @throws {@link PoolError} Thrown when `options.max` is present and is not a positive safe
18
+ * integer, with `code: 'invalid'`. Construction validates it synchronously, before the pool exists.
118
19
  *
119
- * @param signal - Optional native cancellation signal
120
- * @returns A promise for the unique resource lease
121
- */
122
- acquire(signal?: AbortSignal): Promise<PoolToken<T>>;
123
- /**
124
- * Destroy the records that are idle at this call's synchronous snapshot.
20
+ * @example
21
+ * ```ts
22
+ * import { createPool } from '@orkestrel/pool'
125
23
  *
126
- * @returns A promise that settles after every snapshot cleanup attempt
127
- */
128
- clear(): Promise<void>;
129
- /**
130
- * Permanently tear down the pool and return its stable completion barrier.
24
+ * const pool = createPool<Connection>({
25
+ * create: () => connect(),
26
+ * destroy: (connection) => connection.close(),
27
+ * validate: (connection) => connection.alive,
28
+ * max: 8,
29
+ * })
131
30
  *
132
- * @returns The exact promise shared by every destroy call
31
+ * const token = await pool.acquire()
32
+ * try {
33
+ * await token.value.query('select 1')
34
+ * } finally {
35
+ * token.release()
36
+ * }
37
+ * ```
133
38
  */
134
- destroy(): Promise<void>;
135
- }
39
+ export declare function createPool<T>(options: PoolOptions<T>): PoolInterface<T>;
136
40
 
137
- /** Machine-readable failure codes produced by {@link PoolError}. */
138
- export declare type PoolCode = 'invalid' | 'destroyed' | 'create' | 'cleanup';
41
+ /**
42
+ * Tests whether an unknown value is a {@link PoolError}, returning `false` for hostile proxies.
43
+ *
44
+ * @param value - The unknown boundary value
45
+ * @returns True if the value is a real `PoolError` instance; false otherwise
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * isPoolError(new PoolError({ code: 'destroyed' })) // true
50
+ * isPoolError(new Error('other')) // false
51
+ * ```
52
+ */
53
+ export declare function isPoolError(value: unknown): value is PoolError;
139
54
 
140
- /** Structured context attached to a {@link PoolError}. */
141
- export declare interface PoolContext {
142
- /** The rejected public input, when the failure is an input-validation error. */
143
- readonly value?: unknown;
144
- /** Distinct cleanup failures collected by `clear()` or `destroy()`. */
145
- readonly failures?: readonly unknown[];
146
- }
55
+ /**
56
+ * Tests whether a value is a valid finite pool maximum.
57
+ *
58
+ * @param value - The unknown maximum candidate
59
+ * @returns True if the value is a positive safe integer; false otherwise
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * isPoolMax(8) // true
64
+ * isPoolMax(Infinity) // false
65
+ * ```
66
+ */
67
+ export declare function isPoolMax(value: unknown): value is number;
147
68
 
148
- /**
149
- * A stable, machine-readable pool failure with the original cause and structured context.
150
- *
151
- * @example
152
- * ```ts
153
- * import { PoolError, isPoolError } from '@orkestrel/pool'
154
- *
155
- * try {
156
- * await pool.acquire()
157
- * } catch (error: unknown) {
158
- * if (isPoolError(error)) console.error(error.code, error.cause)
159
- * }
160
- * ```
161
- */
162
- export declare class PoolError extends Error {
163
- /** Stable machine-readable failure category. */
164
- readonly code: PoolCode;
165
- /** Optional structured input or aggregate-cleanup details. */
166
- readonly context: PoolContext | undefined;
167
- /**
168
- * Create a pool failure without coercing a hostile thrown value.
169
- *
170
- * @param options - Stable code plus optional cause and structured context
171
- */
172
- constructor(options: PoolErrorOptions);
173
- }
69
+ /**
70
+ * Tests whether a value is a native `AbortSignal`, returning `false` for hostile proxies.
71
+ *
72
+ * @param value - The unknown signal candidate
73
+ * @returns True if the value is a native `AbortSignal`; false otherwise
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * isPoolSignal(new AbortController().signal) // true
78
+ * isPoolSignal({ aborted: false }) // false
79
+ * ```
80
+ */
81
+ export declare function isPoolSignal(value: unknown): value is AbortSignal;
174
82
 
175
- /** Construction options for {@link PoolError}. */
176
- export declare interface PoolErrorOptions {
177
- /** The stable machine-readable failure category. */
178
- readonly code: PoolCode;
179
- /** The original thrown value, retained without unsafe string coercion. */
180
- readonly cause?: unknown;
181
- /** Optional structured failure details. */
182
- readonly context?: PoolContext;
183
- }
83
+ /**
84
+ * Represents a capacity-aware resource pool whose opaque ownership records preserve FIFO
85
+ * settlement, cancellation, exact lease release, and deterministic teardown under concurrent
86
+ * hooks.
87
+ *
88
+ * @typeParam T - The pooled resource value
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * import { Pool } from '@orkestrel/pool'
93
+ *
94
+ * const pool = new Pool({ create: () => new Uint8Array(64), max: 2 })
95
+ * const token = await pool.acquire()
96
+ * try {
97
+ * consume(token.value)
98
+ * } finally {
99
+ * token.release()
100
+ * }
101
+ * await pool.destroy()
102
+ * ```
103
+ */
104
+ export declare class Pool<T> implements PoolInterface<T> {
105
+ #private;
106
+ /**
107
+ * Constructs a pool and synchronously validates its capacity contract.
108
+ *
109
+ * @param options - Resource hooks, observation hooks, and optional positive safe `max`
110
+ * @throws {@link PoolError} Thrown when `options.max` is present and is not a positive safe
111
+ * integer, with `code: 'invalid'`.
112
+ */
113
+ constructor(options: PoolOptions<T>);
114
+ /** Holds the typed synchronous lifecycle observation surface. */
115
+ get emitter(): EmitterInterface<PoolEventMap>;
116
+ /** Counts all owned records, including records validating or destroying. */
117
+ get size(): number;
118
+ /** Counts the records immediately available without validation work. */
119
+ get idle(): number;
120
+ /** Counts the records represented by unsettled released-once lease tokens. */
121
+ get active(): number;
122
+ /**
123
+ * Queues and leases one resource in FIFO settlement order.
124
+ *
125
+ * @param signal - Optional native cancellation signal
126
+ * @returns A promise for the unique resource lease
127
+ * @throws {@link PoolError} Thrown when `signal` is present and is not a native `AbortSignal`,
128
+ * with `code: 'invalid'`. This throw is synchronous rather than a rejected promise, so a caller
129
+ * that handles failures with `.catch()` alone misses it.
130
+ * @throws {@link PoolError} Thrown as a rejection when `destroy()` has already begun, with
131
+ * `code: 'destroyed'`; when the create hook fails, with `code: 'create'` and the hook's thrown
132
+ * value as `cause`; and when an invalid record's cleanup fails, with `code: 'cleanup'`. A
133
+ * `signal` that aborts rejects with the caller's exact `signal.reason` instead.
134
+ */
135
+ acquire(signal?: AbortSignal): Promise<PoolToken<T>>;
136
+ /**
137
+ * Destroys the records that are idle at this call's synchronous snapshot.
138
+ *
139
+ * @returns A promise that settles after every snapshot cleanup attempt
140
+ * @throws {@link PoolError} Thrown when `destroy()` has already begun, with `code: 'destroyed'`.
141
+ * @throws {@link PoolError} Thrown when a claimed record's destroy hook fails, with
142
+ * `code: 'cleanup'` and every distinct failure in `context.failures`. Each arrives as a rejected
143
+ * promise rather than a synchronous throw.
144
+ */
145
+ clear(): Promise<void>;
146
+ /**
147
+ * Tears down the pool permanently and returns its stable completion barrier.
148
+ *
149
+ * @returns The exact promise shared by every destroy call
150
+ * @throws {@link PoolError} Thrown when a destroy hook failed during teardown, with
151
+ * `code: 'cleanup'` and every distinct failure in `context.failures`. The barrier rejects; it
152
+ * never throws synchronously, and a repeat call receives the same rejected promise.
153
+ */
154
+ destroy(): Promise<void>;
155
+ }
184
156
 
185
- /** Observable resource lifecycle events emitted by a {@link PoolInterface}. */
186
- export declare type PoolEventMap = {
187
- /** A created resource entered pool ownership. */
188
- readonly create: readonly [];
189
- /** A token settled successfully and its exact resource became leased. */
190
- readonly acquire: readonly [];
191
- /** A released resource became immediately idle. */
192
- readonly release: readonly [];
193
- /** A resource cleanup hook completed or was attempted when absent. */
194
- readonly destroy: readonly [];
195
- };
157
+ /** Names the machine-readable failure codes produced by {@link PoolError}. */
158
+ export declare type PoolCode = 'invalid' | 'destroyed' | 'create' | 'cleanup';
196
159
 
197
- /** A FIFO resource pool with optional bounded capacity and deterministic teardown. */
198
- export declare interface PoolInterface<T> {
199
- /** The typed synchronous lifecycle observation surface. */
200
- readonly emitter: EmitterInterface<PoolEventMap>;
201
- /** All owned records, including records validating or destroying. */
202
- readonly size: number;
203
- /** Records immediately available without validation work. */
204
- readonly idle: number;
205
- /** Records represented by unsettled released-once lease tokens. */
206
- readonly active: number;
207
- /**
208
- * Queue and lease one resource in FIFO settlement order.
209
- *
210
- * @param signal - Optional native cancellation signal
211
- * @returns A promise for the unique resource lease
212
- */
213
- acquire(signal?: AbortSignal): Promise<PoolToken<T>>;
214
- /**
215
- * Destroy the records that are idle at this call's synchronous snapshot.
216
- *
217
- * @returns A promise that settles after every snapshot cleanup attempt
218
- */
219
- clear(): Promise<void>;
220
- /**
221
- * Permanently tear down the pool and return its stable completion barrier.
222
- *
223
- * @returns The exact promise shared by every destroy call
224
- */
225
- destroy(): Promise<void>;
226
- }
160
+ /** Represents the structured context attached to a {@link PoolError}. */
161
+ export declare interface PoolContext {
162
+ /** Holds the rejected public input, when the failure is an input-validation error. */
163
+ readonly value?: unknown;
164
+ /** Holds distinct destroy-hook failures collected by `clear()` or `destroy()`. */
165
+ readonly failures?: readonly unknown[];
166
+ }
227
167
 
228
- /**
229
- * Resource lifecycle options for {@link Pool} and `createPool`.
230
- *
231
- * @remarks
232
- * `create` lazily produces resources. `destroy` tears down a claimed resource.
233
- * `validate` checks a previously owned resource before reuse. `max` is a positive
234
- * safe integer; omission is the only unbounded form. `on` installs initial emitter
235
- * listeners and `error` receives isolated listener failures.
236
- */
237
- export declare interface PoolOptions<T> {
238
- readonly on?: EmitterHooks<PoolEventMap>;
239
- readonly error?: EmitterErrorHandler;
240
- readonly create: () => Promise<T> | T;
241
- readonly destroy?: (value: T) => Promise<void> | void;
242
- readonly validate?: (value: T) => Promise<boolean> | boolean;
243
- readonly max?: number;
244
- }
168
+ /**
169
+ * Represents a stable, machine-readable pool failure with the original cause and structured
170
+ * context.
171
+ *
172
+ * @example
173
+ * ```ts
174
+ * import { PoolError, isPoolError } from '@orkestrel/pool'
175
+ *
176
+ * try {
177
+ * await pool.acquire()
178
+ * } catch (error: unknown) {
179
+ * if (isPoolError(error)) console.error(error.code, error.cause)
180
+ * }
181
+ * ```
182
+ */
183
+ export declare class PoolError extends Error {
184
+ /** Holds the stable machine-readable failure category. */
185
+ readonly code: PoolCode;
186
+ /** Holds optional structured input or aggregate destroy-hook failure details. */
187
+ readonly context: PoolContext | undefined;
188
+ /**
189
+ * Creates a pool failure without coercing a hostile thrown value.
190
+ *
191
+ * @param options - Stable code plus optional cause and structured context
192
+ */
193
+ constructor(options: PoolErrorOptions);
194
+ }
195
+
196
+ /** Represents the construction options for {@link PoolError}. */
197
+ export declare interface PoolErrorOptions {
198
+ /** Holds the stable machine-readable failure category. */
199
+ readonly code: PoolCode;
200
+ /** Holds the original thrown value, retained without unsafe string coercion. */
201
+ readonly cause?: unknown;
202
+ /** Holds optional structured failure details. */
203
+ readonly context?: PoolContext;
204
+ }
205
+
206
+ /** Represents the observable resource lifecycle events emitted by a {@link PoolInterface}. */
207
+ export declare type PoolEventMap = {
208
+ /** Signals that a created resource entered pool ownership. */
209
+ readonly create: readonly [];
210
+ /** Signals that a token settled successfully and its exact resource became leased. */
211
+ readonly acquire: readonly [];
212
+ /** Signals that a released resource became immediately idle. */
213
+ readonly release: readonly [];
214
+ /** Signals that a resource destroy hook completed or was attempted when absent. */
215
+ readonly destroy: readonly [];
216
+ };
217
+
218
+ /** Represents a FIFO resource pool with optional bounded capacity and deterministic teardown. */
219
+ export declare interface PoolInterface<T> {
220
+ /** Holds the typed synchronous lifecycle observation surface. */
221
+ readonly emitter: EmitterInterface<PoolEventMap>;
222
+ /** Counts all owned records, including records validating or destroying. */
223
+ readonly size: number;
224
+ /** Counts the records immediately available without validation work. */
225
+ readonly idle: number;
226
+ /** Counts the records represented by unsettled released-once lease tokens. */
227
+ readonly active: number;
228
+ /**
229
+ * Queues and leases one resource in FIFO settlement order.
230
+ *
231
+ * @param signal - Optional native cancellation signal
232
+ * @returns A promise for the unique resource lease
233
+ * @throws {@link PoolError} Thrown when `signal` is present and is not a native `AbortSignal`,
234
+ * with `code: 'invalid'`. This throw is synchronous rather than a rejected promise, so a caller
235
+ * that handles failures with `.catch()` alone misses it.
236
+ * @throws {@link PoolError} Thrown as a rejection when `destroy()` has already begun, with
237
+ * `code: 'destroyed'`; when the create hook fails, with `code: 'create'` and the hook's thrown
238
+ * value as `cause`; and when an invalid record's cleanup fails, with `code: 'cleanup'`. A
239
+ * `signal` that aborts rejects with the caller's exact `signal.reason` instead.
240
+ */
241
+ acquire(signal?: AbortSignal): Promise<PoolToken<T>>;
242
+ /**
243
+ * Destroys the records that are idle at this call's synchronous snapshot.
244
+ *
245
+ * @returns A promise that settles after every snapshot cleanup attempt
246
+ * @throws {@link PoolError} Thrown when `destroy()` has already begun, with `code: 'destroyed'`.
247
+ * @throws {@link PoolError} Thrown when a claimed record's destroy hook fails, with
248
+ * `code: 'cleanup'` and every distinct failure in `context.failures`. Each arrives as a rejected
249
+ * promise rather than a synchronous throw.
250
+ */
251
+ clear(): Promise<void>;
252
+ /**
253
+ * Tears down the pool permanently and returns its stable completion barrier.
254
+ *
255
+ * @returns The exact promise shared by every destroy call
256
+ * @throws {@link PoolError} Thrown when a destroy hook failed during teardown, with
257
+ * `code: 'cleanup'` and every distinct failure in `context.failures`. The barrier rejects; it
258
+ * never throws synchronously, and a repeat call receives the same rejected promise.
259
+ */
260
+ destroy(): Promise<void>;
261
+ }
262
+
263
+ /**
264
+ * Represents the resource lifecycle options for {@link Pool} and `createPool`.
265
+ *
266
+ * @remarks
267
+ * `create` lazily produces resources. `destroy` tears down a claimed resource.
268
+ * `validate` checks a previously owned resource before reuse. `max` is a positive
269
+ * safe integer; omission is the only unbounded form. `on` installs initial emitter
270
+ * listeners and `error` receives isolated listener failures.
271
+ */
272
+ export declare interface PoolOptions<T> {
273
+ readonly on?: EmitterHooks<PoolEventMap>;
274
+ readonly error?: EmitterErrorHandler;
275
+ readonly create: () => Promise<T> | T;
276
+ readonly destroy?: (value: T) => Promise<void> | void;
277
+ readonly validate?: (value: T) => Promise<boolean> | boolean;
278
+ readonly max?: number;
279
+ }
245
280
 
246
- /** A unique lease over one pool-owned resource record. */
247
- export declare interface PoolToken<T> {
248
- /** The leased value. Duplicate values still belong to independent records. */
249
- readonly value: T;
250
- /** Return this exact lease once; subsequent calls are no-ops. */
251
- release(): void;
252
- }
281
+ /** Represents a unique lease over one pool-owned resource record. */
282
+ export declare interface PoolToken<T> {
283
+ /** Holds the leased value. Duplicate values still belong to independent records. */
284
+ readonly value: T;
285
+ /** Gives this exact lease back once; subsequent calls are no-ops. */
286
+ release(): void;
287
+ }
253
288
 
254
- export { }
289
+ export { }