@venizia/ignis-helpers 0.0.8-10 → 0.0.8-13

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.
Files changed (56) hide show
  1. package/dist/modules/index.d.ts +1 -0
  2. package/dist/modules/index.d.ts.map +1 -1
  3. package/dist/modules/index.js +1 -0
  4. package/dist/modules/index.js.map +1 -1
  5. package/dist/modules/pool/helper.d.ts +100 -0
  6. package/dist/modules/pool/helper.d.ts.map +1 -0
  7. package/dist/modules/pool/helper.js +326 -0
  8. package/dist/modules/pool/helper.js.map +1 -0
  9. package/dist/modules/pool/index.d.ts +3 -0
  10. package/dist/modules/pool/index.d.ts.map +1 -0
  11. package/dist/modules/pool/index.js +19 -0
  12. package/dist/modules/pool/index.js.map +1 -0
  13. package/dist/modules/pool/types.d.ts +62 -0
  14. package/dist/modules/pool/types.d.ts.map +1 -0
  15. package/dist/modules/pool/types.js +3 -0
  16. package/dist/modules/pool/types.js.map +1 -0
  17. package/dist/modules/queue/internal/hf/helper.d.ts +37 -0
  18. package/dist/modules/queue/internal/hf/helper.d.ts.map +1 -0
  19. package/dist/modules/queue/internal/hf/helper.js +82 -0
  20. package/dist/modules/queue/internal/hf/helper.js.map +1 -0
  21. package/dist/modules/queue/internal/hf/index.d.ts +3 -0
  22. package/dist/modules/queue/internal/hf/index.d.ts.map +1 -0
  23. package/dist/modules/queue/internal/hf/index.js +19 -0
  24. package/dist/modules/queue/internal/hf/index.js.map +1 -0
  25. package/dist/modules/queue/internal/hf/types.d.ts +9 -0
  26. package/dist/modules/queue/internal/hf/types.d.ts.map +1 -0
  27. package/dist/modules/queue/internal/hf/types.js +3 -0
  28. package/dist/modules/queue/internal/hf/types.js.map +1 -0
  29. package/dist/modules/queue/internal/index.d.ts +2 -1
  30. package/dist/modules/queue/internal/index.d.ts.map +1 -1
  31. package/dist/modules/queue/internal/index.js +2 -1
  32. package/dist/modules/queue/internal/index.js.map +1 -1
  33. package/dist/modules/queue/internal/sequential/helper.d.ts +40 -0
  34. package/dist/modules/queue/internal/sequential/helper.d.ts.map +1 -0
  35. package/dist/modules/queue/internal/{helper.js → sequential/helper.js} +26 -32
  36. package/dist/modules/queue/internal/sequential/helper.js.map +1 -0
  37. package/dist/modules/queue/internal/sequential/index.d.ts +3 -0
  38. package/dist/modules/queue/internal/sequential/index.d.ts.map +1 -0
  39. package/dist/modules/queue/internal/sequential/index.js +19 -0
  40. package/dist/modules/queue/internal/sequential/index.js.map +1 -0
  41. package/dist/modules/queue/internal/sequential/types.d.ts +35 -0
  42. package/dist/modules/queue/internal/sequential/types.d.ts.map +1 -0
  43. package/dist/modules/queue/internal/sequential/types.js +15 -0
  44. package/dist/modules/queue/internal/sequential/types.js.map +1 -0
  45. package/dist/modules/queue/kafka/base.d.ts +3 -1
  46. package/dist/modules/queue/kafka/base.d.ts.map +1 -1
  47. package/dist/modules/queue/kafka/base.js +11 -0
  48. package/dist/modules/queue/kafka/base.js.map +1 -1
  49. package/dist/modules/queue/kafka/consumer.d.ts +8 -0
  50. package/dist/modules/queue/kafka/consumer.d.ts.map +1 -1
  51. package/dist/modules/queue/kafka/consumer.js +124 -33
  52. package/dist/modules/queue/kafka/consumer.js.map +1 -1
  53. package/package.json +1 -1
  54. package/dist/modules/queue/internal/helper.d.ts +0 -69
  55. package/dist/modules/queue/internal/helper.d.ts.map +0 -1
  56. package/dist/modules/queue/internal/helper.js.map +0 -1
@@ -4,6 +4,7 @@ export * from './env';
4
4
  export * from './error';
5
5
  export * from './logger';
6
6
  export * from './network';
7
+ export * from './pool';
7
8
  export * from './queue';
8
9
  export * from './redis';
9
10
  export * from './socket';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/modules/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AAEvB,cAAc,UAAU,CAAC;AACzB,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,OAAO,CAAC;AACtB,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/modules/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AAEvB,cAAc,UAAU,CAAC;AACzB,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,OAAO,CAAC;AACtB,cAAc,iBAAiB,CAAC"}
@@ -20,6 +20,7 @@ __exportStar(require("./env"), exports);
20
20
  __exportStar(require("./error"), exports);
21
21
  __exportStar(require("./logger"), exports);
22
22
  __exportStar(require("./network"), exports);
23
+ __exportStar(require("./pool"), exports);
23
24
  __exportStar(require("./queue"), exports);
24
25
  __exportStar(require("./redis"), exports);
25
26
  __exportStar(require("./socket"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/modules/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yCAAuB;AAEvB,2CAAyB;AACzB,wCAAsB;AACtB,0CAAwB;AACxB,2CAAyB;AACzB,4CAA0B;AAC1B,0CAAwB;AACxB,0CAAwB;AACxB,2CAAyB;AACzB,4CAA0B;AAC1B,4CAA0B;AAC1B,wCAAsB;AACtB,kDAAgC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/modules/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yCAAuB;AAEvB,2CAAyB;AACzB,wCAAsB;AACtB,0CAAwB;AACxB,2CAAyB;AACzB,4CAA0B;AAC1B,yCAAuB;AACvB,0CAAwB;AACxB,0CAAwB;AACxB,2CAAyB;AACzB,4CAA0B;AAC1B,4CAA0B;AAC1B,wCAAsB;AACtB,kDAAgC"}
@@ -0,0 +1,100 @@
1
+ import { ValueOrPromise } from '../../common/types';
2
+ import { BaseHelper } from '../../modules/base';
3
+ import { IPool, IPoolControlOptions, IPoolOptions, IPoolStats } from './types';
4
+ /**
5
+ * Generic single-borrower object pool — skeleton.
6
+ *
7
+ * Holds all pool state and the pairing logic; subclasses supply the resource lifecycle by overriding
8
+ * {@link create} (required) and, optionally, {@link validateResource} / {@link resetResource} /
9
+ * {@link onDestroyResource}. {@link BasePoolHelper} is the concrete, callback-configured subclass.
10
+ *
11
+ * Every pairing of a resource with a waiting acquirer flows through ONE re-entrancy-guarded
12
+ * `dispatch()` loop, so `acquire`/`release`/`use`/`discard`/`warmup` stay thin; each loop branch
13
+ * delegates to a single-purpose helper (`takeIdleResource`, `createAndHand`, `handToWaiter`).
14
+ *
15
+ * The waiter queue is a generic O(1) {@link HfQueueHelper}: enqueue pushes, dequeue advances a head index
16
+ * (skipping cancelled nodes), and a timed-out acquirer is cancelled in O(1) — no Array.shift/splice
17
+ * on the hot path.
18
+ */
19
+ export declare abstract class AbstractPoolHelper<T> extends BaseHelper implements IPool<T> {
20
+ protected readonly size: number;
21
+ protected readonly acquireTimeoutMs?: number;
22
+ protected readonly maxWaitingClients?: number;
23
+ private readonly idle;
24
+ private readonly borrowed;
25
+ private readonly waiterQueue;
26
+ private total;
27
+ private isDispatching;
28
+ private isDestroyed;
29
+ constructor(opts: IPoolControlOptions);
30
+ /** Create one resource. Required. */
31
+ protected abstract create(): ValueOrPromise<T>;
32
+ /** Validate an idle resource just before hand-out; false → destroyed + replaced. Default: always valid. */
33
+ protected validateResource(_opts: {
34
+ resource: T;
35
+ }): ValueOrPromise<boolean>;
36
+ /** Reset an idle resource before hand-out (e.g. clear state). Throw → resource discarded. Default: no-op. */
37
+ protected resetResource(_opts: {
38
+ resource: T;
39
+ }): ValueOrPromise<void>;
40
+ /** Tear down a resource being removed from the pool. Default: no-op. */
41
+ protected onDestroyResource(_opts: {
42
+ resource: T;
43
+ }): ValueOrPromise<void>;
44
+ getStats(): IPoolStats;
45
+ acquire(): Promise<T>;
46
+ release(opts: {
47
+ resource: T;
48
+ }): void;
49
+ warmup(): Promise<void>;
50
+ use<R>(opts: {
51
+ fn: (resource: T) => ValueOrPromise<R>;
52
+ }): Promise<R>;
53
+ discard(opts: {
54
+ resource: T;
55
+ }): Promise<void>;
56
+ destroy(): Promise<void>;
57
+ private createResource;
58
+ private destroyResource;
59
+ /** Fire-and-forget dispatch with logged rejection; shared by all dispatch call sites. */
60
+ private safeDispatch;
61
+ /**
62
+ * Pair servable resources with waiting acquirers, one at a time, until the queue drains or the
63
+ * pool is exhausted. Re-entrancy-guarded so only one loop runs at a time (others no-op and let this
64
+ * loop finish). Each branch delegates to a single-purpose helper.
65
+ */
66
+ private dispatch;
67
+ /** Pop an idle resource and validate+reset it; on ANY failure destroy it and return null (caller retries). */
68
+ private takeIdleResource;
69
+ /** Create a fresh resource and hand it to the next waiter; on create failure, reject that waiter. */
70
+ private createAndHand;
71
+ /**
72
+ * Give a ready resource to the next live waiter. Returns false when no live waiter remains
73
+ * (raced — e.g. it timed out during an await): the resource is returned to idle instead.
74
+ */
75
+ private handToWaiter;
76
+ /** Dequeue the next live waiter and disarm its acquire-timeout so it cannot fire after settlement. */
77
+ private takeNextWaiter;
78
+ private clearWaiterTimer;
79
+ }
80
+ /**
81
+ * Concrete object pool configured by callbacks ({@link IPoolOptions}). Implements the
82
+ * AbstractPoolHelper lifecycle hooks by delegating to `create`/`validate`/`reset`/`destroy`.
83
+ *
84
+ * Each borrow is exclusive until released; `use()` is leak-safe (destroys the resource on error).
85
+ */
86
+ export declare class BasePoolHelper<T> extends AbstractPoolHelper<T> {
87
+ private readonly factory;
88
+ constructor(options: IPoolOptions<T>);
89
+ protected create(): ValueOrPromise<T>;
90
+ protected validateResource(opts: {
91
+ resource: T;
92
+ }): ValueOrPromise<boolean>;
93
+ protected resetResource(opts: {
94
+ resource: T;
95
+ }): ValueOrPromise<void>;
96
+ protected onDestroyResource(opts: {
97
+ resource: T;
98
+ }): ValueOrPromise<void>;
99
+ }
100
+ //# sourceMappingURL=helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../../../src/modules/pool/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,UAAU,EAAe,MAAM,SAAS,CAAC;AAE5F;;;;;;;;;;;;;;GAcG;AACH,8BAAsB,kBAAkB,CAAC,CAAC,CAAE,SAAQ,UAAW,YAAW,KAAK,CAAC,CAAC,CAAC;IAChF,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAChC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC7C,SAAS,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAW;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuC;IAEnE,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAS;gBAEhB,IAAI,EAAE,mBAAmB;IASrC,qCAAqC;IACrC,SAAS,CAAC,QAAQ,CAAC,MAAM,IAAI,cAAc,CAAC,CAAC,CAAC;IAE9C,2GAA2G;IAC3G,SAAS,CAAC,gBAAgB,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,CAAC,CAAA;KAAE,GAAG,cAAc,CAAC,OAAO,CAAC;IAI3E,6GAA6G;IAC7G,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,CAAC,CAAA;KAAE,GAAG,cAAc,CAAC,IAAI,CAAC;IAIrE,wEAAwE;IACxE,SAAS,CAAC,iBAAiB,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,CAAC,CAAA;KAAE,GAAG,cAAc,CAAC,IAAI,CAAC;IAMzE,QAAQ,IAAI,UAAU;IAShB,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC;IAuC3B,OAAO,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,CAAC,CAAA;KAAE,GAAG,IAAI;IAqB9B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBvB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE;QAAE,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,cAAc,CAAC,CAAC,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,CAAC;IAgBpE,OAAO,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAgBhB,cAAc;YAed,eAAe;IAY7B,yFAAyF;IACzF,OAAO,CAAC,YAAY;IAQpB;;;;OAIG;YACW,QAAQ;IAuCtB,8GAA8G;YAChG,gBAAgB;IA+B9B,qGAAqG;YACvF,aAAa;IAY3B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAYpB,sGAAsG;IACtG,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,gBAAgB;CAOzB;AAED;;;;;GAKG;AACH,qBAAa,cAAc,CAAC,CAAC,CAAE,SAAQ,kBAAkB,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;gBAE9B,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IAUpC,SAAS,CAAC,MAAM,IAAI,cAAc,CAAC,CAAC,CAAC;cAIlB,gBAAgB,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,CAAC,CAAA;KAAE,GAAG,cAAc,CAAC,OAAO,CAAC;cAIhE,aAAa,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,CAAC,CAAA;KAAE,GAAG,cAAc,CAAC,IAAI,CAAC;cAI1D,iBAAiB,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,CAAC,CAAA;KAAE,GAAG,cAAc,CAAC,IAAI,CAAC;CAGlF"}
@@ -0,0 +1,326 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BasePoolHelper = exports.AbstractPoolHelper = void 0;
4
+ const base_1 = require("../../modules/base");
5
+ const error_1 = require("../../modules/error");
6
+ const hf_1 = require("../../modules/queue/internal/hf");
7
+ /**
8
+ * Generic single-borrower object pool — skeleton.
9
+ *
10
+ * Holds all pool state and the pairing logic; subclasses supply the resource lifecycle by overriding
11
+ * {@link create} (required) and, optionally, {@link validateResource} / {@link resetResource} /
12
+ * {@link onDestroyResource}. {@link BasePoolHelper} is the concrete, callback-configured subclass.
13
+ *
14
+ * Every pairing of a resource with a waiting acquirer flows through ONE re-entrancy-guarded
15
+ * `dispatch()` loop, so `acquire`/`release`/`use`/`discard`/`warmup` stay thin; each loop branch
16
+ * delegates to a single-purpose helper (`takeIdleResource`, `createAndHand`, `handToWaiter`).
17
+ *
18
+ * The waiter queue is a generic O(1) {@link HfQueueHelper}: enqueue pushes, dequeue advances a head index
19
+ * (skipping cancelled nodes), and a timed-out acquirer is cancelled in O(1) — no Array.shift/splice
20
+ * on the hot path.
21
+ */
22
+ class AbstractPoolHelper extends base_1.BaseHelper {
23
+ constructor(opts) {
24
+ super({ scope: opts.scope ?? 'BasePoolHelper' });
25
+ this.idle = [];
26
+ this.borrowed = new Set();
27
+ this.waiterQueue = new hf_1.HfQueueHelper();
28
+ this.total = 0; // live or being-created resources
29
+ this.isDispatching = false;
30
+ this.isDestroyed = false;
31
+ this.size = opts.size;
32
+ this.acquireTimeoutMs = opts.acquireTimeoutMs;
33
+ this.maxWaitingClients = opts.maxWaitingClients;
34
+ }
35
+ /** Validate an idle resource just before hand-out; false → destroyed + replaced. Default: always valid. */
36
+ validateResource(_opts) {
37
+ return true;
38
+ }
39
+ /** Reset an idle resource before hand-out (e.g. clear state). Throw → resource discarded. Default: no-op. */
40
+ resetResource(_opts) {
41
+ return undefined;
42
+ }
43
+ /** Tear down a resource being removed from the pool. Default: no-op. */
44
+ onDestroyResource(_opts) {
45
+ return undefined;
46
+ }
47
+ // ----------------------------------------------------------------------------------------------------------
48
+ getStats() {
49
+ return {
50
+ size: this.size,
51
+ available: this.idle.length,
52
+ borrowed: this.borrowed.size,
53
+ pending: this.waiterQueue.size,
54
+ };
55
+ }
56
+ async acquire() {
57
+ if (this.isDestroyed) {
58
+ throw (0, error_1.getError)({ message: '[acquire] Pool has been destroyed.' });
59
+ }
60
+ if (this.maxWaitingClients !== undefined && this.maxWaitingClients > 0) {
61
+ // Only reject when this acquire would actually have to WAIT: no idle resource and the pool is at
62
+ // capacity. With a free/creatable resource the caller is served, so maxWaitingClients:0 means
63
+ // "serve if available, never queue" rather than "reject everything".
64
+ const isWaitRequired = !this.idle.length && this.total >= this.size;
65
+ if (isWaitRequired && this.waiterQueue.size >= this.maxWaitingClients) {
66
+ throw (0, error_1.getError)({
67
+ message: `[acquire] Too many waiting clients (>= ${this.maxWaitingClients}).`,
68
+ });
69
+ }
70
+ }
71
+ const promise = new Promise((resolve, reject) => {
72
+ const waiter = { resolve, reject, timer: null };
73
+ const node = this.waiterQueue.enqueue({ value: waiter });
74
+ if (this.acquireTimeoutMs !== undefined && this.acquireTimeoutMs > 0) {
75
+ waiter.timer = setTimeout(() => {
76
+ this.waiterQueue.cancel({ node }); // O(1) — dispatch skips it when reached
77
+ reject((0, error_1.getError)({
78
+ message: `[acquire] Acquire timed out after ${this.acquireTimeoutMs}ms.`,
79
+ }));
80
+ }, this.acquireTimeoutMs);
81
+ }
82
+ });
83
+ this.safeDispatch({ action: 'acquire' });
84
+ return promise;
85
+ }
86
+ release(opts) {
87
+ const { resource } = opts;
88
+ const logger = this.logger.for(this.release.name);
89
+ if (!this.borrowed.has(resource)) {
90
+ logger.warn('Called with a foreign/already-released resource; ignoring.');
91
+ return;
92
+ }
93
+ this.borrowed.delete(resource);
94
+ if (this.isDestroyed) {
95
+ this.destroyResource({ resource }).catch(error => {
96
+ logger.warn('destroyResource error on release: %s', error);
97
+ });
98
+ return;
99
+ }
100
+ this.idle.push(resource);
101
+ this.safeDispatch({ action: 'release' });
102
+ }
103
+ async warmup() {
104
+ if (this.isDestroyed) {
105
+ throw (0, error_1.getError)({ message: '[warmup] Pool has been destroyed.' });
106
+ }
107
+ // Create sequentially, re-checking the live `total` before each create so the `size` cap holds
108
+ // under concurrent warmup()/acquire(). createResource() bumps `total` synchronously (before its
109
+ // await), so a re-check here observes in-flight creations from other callers → no overshoot.
110
+ while (this.total < this.size) {
111
+ const resource = await this.createResource();
112
+ this.idle.push(resource);
113
+ }
114
+ this.safeDispatch({ action: 'warmup' });
115
+ }
116
+ async use(opts) {
117
+ const resource = await this.acquire();
118
+ try {
119
+ const result = await opts.fn(resource);
120
+ this.release({ resource });
121
+ return result;
122
+ }
123
+ catch (error) {
124
+ this.logger
125
+ .for(this.use.name)
126
+ .error('fn threw → release skipped, force DISCARD | Error: %s', error);
127
+ await this.discard({ resource });
128
+ throw error;
129
+ }
130
+ }
131
+ async discard(opts) {
132
+ const { resource } = opts;
133
+ if (!this.borrowed.delete(resource)) {
134
+ this.logger.for(this.discard.name).warn('Called with a non-borrowed resource; ignoring.');
135
+ return;
136
+ }
137
+ await this.destroyResource({ resource });
138
+ this.safeDispatch({ action: 'discard' });
139
+ }
140
+ async destroy() {
141
+ this.isDestroyed = true;
142
+ const error = (0, error_1.getError)({ message: '[destroy] Pool destroyed while awaiting a resource.' });
143
+ const draineds = this.waiterQueue.drain();
144
+ for (const waiter of draineds) {
145
+ this.clearWaiterTimer({ waiter });
146
+ waiter.reject(error);
147
+ }
148
+ const toDestroy = this.idle.splice(0);
149
+ await Promise.all(toDestroy.map(resource => this.destroyResource({ resource })));
150
+ }
151
+ // ----------------------------------------------------------------------------------------------------------
152
+ async createResource() {
153
+ this.total += 1; // bump BEFORE await so concurrent dispatch/warmup see the in-flight create (no overshoot)
154
+ try {
155
+ const resource = await this.create();
156
+ return resource;
157
+ }
158
+ catch (error) {
159
+ this.total -= 1;
160
+ this.logger
161
+ .for(this.createResource.name)
162
+ .error('Error creating pool resource | Error: %s', error);
163
+ throw error;
164
+ }
165
+ }
166
+ async destroyResource(opts) {
167
+ this.total -= 1;
168
+ try {
169
+ await this.onDestroyResource(opts);
170
+ }
171
+ catch (error) {
172
+ this.logger.for(this.destroyResource.name).warn('destroy hook threw: %s', error);
173
+ }
174
+ }
175
+ // ----------------------------------------------------------------------------------------------------------
176
+ /** Fire-and-forget dispatch with logged rejection; shared by all dispatch call sites. */
177
+ safeDispatch(opts) {
178
+ this.dispatch().catch(error => {
179
+ this.logger
180
+ .for(this.dispatch.name)
181
+ .warn('dispatch error | action: %s | Error: %s', opts.action, error);
182
+ });
183
+ }
184
+ /**
185
+ * Pair servable resources with waiting acquirers, one at a time, until the queue drains or the
186
+ * pool is exhausted. Re-entrancy-guarded so only one loop runs at a time (others no-op and let this
187
+ * loop finish). Each branch delegates to a single-purpose helper.
188
+ */
189
+ async dispatch() {
190
+ if (this.isDispatching) {
191
+ return;
192
+ }
193
+ this.isDispatching = true;
194
+ try {
195
+ while (this.waiterQueue.size > 0) {
196
+ // Prefer a warm idle resource (LIFO) over creating a new one.
197
+ if (this.idle.length > 0) {
198
+ const resource = await this.takeIdleResource();
199
+ if (resource === null) {
200
+ continue; // bad idle resource was discarded → try the next one
201
+ }
202
+ if (!this.handToWaiter({ resource })) {
203
+ return;
204
+ }
205
+ continue;
206
+ }
207
+ // No idle, but room to grow → create one for the next waiter.
208
+ if (this.total < this.size) {
209
+ await this.createAndHand();
210
+ continue;
211
+ }
212
+ return;
213
+ }
214
+ }
215
+ catch (error) {
216
+ this.logger
217
+ .for(this.dispatch.name)
218
+ .error('[dispatch] Error while dispatching pool element | Error: %s', error);
219
+ }
220
+ finally {
221
+ this.isDispatching = false;
222
+ }
223
+ }
224
+ /** Pop an idle resource and validate+reset it; on ANY failure destroy it and return null (caller retries). */
225
+ async takeIdleResource() {
226
+ const resource = this.idle.pop();
227
+ const logger = this.logger.for(this.takeIdleResource.name);
228
+ let isValid;
229
+ try {
230
+ isValid = await this.validateResource({ resource });
231
+ }
232
+ catch (error) {
233
+ // A throwing validate must NOT leak the popped candidate (would corrupt `total` and can
234
+ // permanently starve the pool); treat it like an invalid resource: discard + retry.
235
+ logger.warn('validate hook threw; discarding resource: %s', error);
236
+ await this.destroyResource({ resource });
237
+ return null;
238
+ }
239
+ if (!isValid) {
240
+ await this.destroyResource({ resource });
241
+ return null;
242
+ }
243
+ try {
244
+ await this.resetResource({ resource });
245
+ }
246
+ catch (error) {
247
+ logger.warn('reset hook threw; discarding resource: %s', error);
248
+ await this.destroyResource({ resource });
249
+ return null;
250
+ }
251
+ return resource;
252
+ }
253
+ /** Create a fresh resource and hand it to the next waiter; on create failure, reject that waiter. */
254
+ async createAndHand() {
255
+ let resource;
256
+ try {
257
+ resource = await this.createResource();
258
+ }
259
+ catch (error) {
260
+ this.takeNextWaiter()?.reject(error);
261
+ return;
262
+ }
263
+ this.handToWaiter({ resource });
264
+ }
265
+ /**
266
+ * Give a ready resource to the next live waiter. Returns false when no live waiter remains
267
+ * (raced — e.g. it timed out during an await): the resource is returned to idle instead.
268
+ */
269
+ handToWaiter(opts) {
270
+ const waiter = this.takeNextWaiter();
271
+ if (!waiter) {
272
+ this.idle.push(opts.resource);
273
+ return false;
274
+ }
275
+ this.borrowed.add(opts.resource);
276
+ waiter.resolve(opts.resource);
277
+ return true;
278
+ }
279
+ /** Dequeue the next live waiter and disarm its acquire-timeout so it cannot fire after settlement. */
280
+ takeNextWaiter() {
281
+ const waiter = this.waiterQueue.dequeue();
282
+ if (waiter) {
283
+ this.clearWaiterTimer({ waiter });
284
+ }
285
+ return waiter;
286
+ }
287
+ clearWaiterTimer(opts) {
288
+ const { waiter } = opts;
289
+ if (waiter.timer) {
290
+ clearTimeout(waiter.timer);
291
+ waiter.timer = null;
292
+ }
293
+ }
294
+ }
295
+ exports.AbstractPoolHelper = AbstractPoolHelper;
296
+ /**
297
+ * Concrete object pool configured by callbacks ({@link IPoolOptions}). Implements the
298
+ * AbstractPoolHelper lifecycle hooks by delegating to `create`/`validate`/`reset`/`destroy`.
299
+ *
300
+ * Each borrow is exclusive until released; `use()` is leak-safe (destroys the resource on error).
301
+ */
302
+ class BasePoolHelper extends AbstractPoolHelper {
303
+ constructor(options) {
304
+ super({
305
+ size: options.size,
306
+ acquireTimeoutMs: options.acquireTimeoutMs,
307
+ maxWaitingClients: options.maxWaitingClients,
308
+ scope: options.scope ?? BasePoolHelper.name,
309
+ });
310
+ this.factory = options;
311
+ }
312
+ create() {
313
+ return this.factory.create();
314
+ }
315
+ validateResource(opts) {
316
+ return this.factory.validate ? this.factory.validate(opts.resource) : true;
317
+ }
318
+ resetResource(opts) {
319
+ return this.factory.reset?.(opts.resource);
320
+ }
321
+ onDestroyResource(opts) {
322
+ return this.factory.destroy?.(opts.resource);
323
+ }
324
+ }
325
+ exports.BasePoolHelper = BasePoolHelper;
326
+ //# sourceMappingURL=helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helper.js","sourceRoot":"","sources":["../../../src/modules/pool/helper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './helper';
2
+ export * from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/pool/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./helper"), exports);
18
+ __exportStar(require("./types"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/pool/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,0CAAwB"}
@@ -0,0 +1,62 @@
1
+ import { TNullable, ValueOrPromise } from '../../common/types';
2
+ export interface IPoolStats {
3
+ size: number;
4
+ available: number;
5
+ borrowed: number;
6
+ pending: number;
7
+ }
8
+ /** Public contract of an object pool (implemented by AbstractPoolHelper). */
9
+ export interface IPool<T> {
10
+ /** Borrow a resource (creating/waiting as needed). Single-borrower until released/discarded. */
11
+ acquire(): Promise<T>;
12
+ /** Return a borrowed resource to the pool (or destroy it if the pool is being torn down). */
13
+ release(opts: {
14
+ resource: T;
15
+ }): void;
16
+ /** acquire → run fn → release on success; on ANY error DISCARD (destroy) the resource + rethrow. */
17
+ use<R>(opts: {
18
+ fn: (resource: T) => ValueOrPromise<R>;
19
+ }): Promise<R>;
20
+ /** Remove a borrowed resource from the pool and destroy it. */
21
+ discard(opts: {
22
+ resource: T;
23
+ }): Promise<void>;
24
+ /** Pre-create resources up to `size` and place them idle. */
25
+ warmup(): Promise<void>;
26
+ /** Drain the pool: reject waiters, destroy idle resources, block new acquires. */
27
+ destroy(): Promise<void>;
28
+ getStats(): IPoolStats;
29
+ }
30
+ /** Sizing/timeout knobs shared by every pool (no resource-lifecycle callbacks). */
31
+ export interface IPoolControlOptions {
32
+ /** Max number of resources the pool will hold/create. */
33
+ size: number;
34
+ /** Max ms to wait for a free resource; omitted → wait forever. */
35
+ acquireTimeoutMs?: number;
36
+ /** Max queued acquirers; omitted → unlimited. Exceeded → acquire() rejects (load-shed). */
37
+ maxWaitingClients?: number;
38
+ /** Logger scope; default 'BasePoolHelper'. */
39
+ scope?: string;
40
+ }
41
+ /**
42
+ * Options for the callback-configured {@link BasePoolHelper}: control knobs plus the resource
43
+ * lifecycle as callbacks. (Subclasses of AbstractPoolHelper may instead override the protected
44
+ * `create`/`validateResource`/`resetResource`/`onDestroyResource` hooks directly.)
45
+ */
46
+ export interface IPoolOptions<T> extends IPoolControlOptions {
47
+ /** Factory to create one resource. */
48
+ create: () => ValueOrPromise<T>;
49
+ /** Teardown on destroy()/discard()/validate-fail/reset-fail. */
50
+ destroy?: (resource: T) => ValueOrPromise<void>;
51
+ /** Checked when an idle resource is about to be handed out; false → destroyed + replaced. */
52
+ validate?: (resource: T) => ValueOrPromise<boolean>;
53
+ /** Run on an idle resource just before hand-out (e.g. clear state). Throw → resource discarded. */
54
+ reset?: (resource: T) => ValueOrPromise<void>;
55
+ }
56
+ /** One queued acquirer. Cancellation/skip is owned by the FifoQueue; this only carries the settlers. */
57
+ export interface IPoolWaiter<T> {
58
+ resolve: (resource: T) => void;
59
+ reject: (error: unknown) => void;
60
+ timer: TNullable<NodeJS.Timeout>;
61
+ }
62
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/modules/pool/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE3D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,6EAA6E;AAC7E,MAAM,WAAW,KAAK,CAAC,CAAC;IACtB,gGAAgG;IAChG,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IACtB,6FAA6F;IAC7F,OAAO,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC;IACrC,oGAAoG;IACpG,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE;QAAE,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,cAAc,CAAC,CAAC,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACrE,+DAA+D;IAC/D,OAAO,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,6DAA6D;IAC7D,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,kFAAkF;IAClF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,QAAQ,IAAI,UAAU,CAAC;CACxB;AAED,mFAAmF;AACnF,MAAM,WAAW,mBAAmB;IAClC,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2FAA2F;IAC3F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,CAAE,SAAQ,mBAAmB;IAC1D,sCAAsC;IACtC,MAAM,EAAE,MAAM,cAAc,CAAC,CAAC,CAAC,CAAC;IAChC,gEAAgE;IAChE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,cAAc,CAAC,IAAI,CAAC,CAAC;IAChD,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,cAAc,CAAC,OAAO,CAAC,CAAC;IACpD,mGAAmG;IACnG,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,cAAc,CAAC,IAAI,CAAC,CAAC;CAC/C;AAED,wGAAwG;AACxG,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/B,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;CAClC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/modules/pool/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ import { TNullable } from '../../../../common/types';
2
+ import { BaseHelper } from '../../../../modules/base';
3
+ import { IHfQueueNode } from './types';
4
+ /**
5
+ * High-frequency, single-consumer FIFO queue with O(1) enqueue / dequeue / cancel.
6
+ *
7
+ * Backed by an array plus a moving head index (no `Array.shift()`, which is O(n)); cancellation flags
8
+ * the node so {@link dequeue} skips it instead of splicing. The consumed prefix is compacted only
9
+ * occasionally to reclaim memory, keeping every operation amortized O(1).
10
+ *
11
+ * Not thread-safe — intended for single-threaded (event-loop) use, e.g. a pool's waiter queue.
12
+ */
13
+ export declare class HfQueueHelper<T> extends BaseHelper {
14
+ private readonly nodes;
15
+ private head;
16
+ private liveCount;
17
+ private static readonly COMPACT_THRESHOLD;
18
+ constructor(opts?: {
19
+ scope?: string;
20
+ });
21
+ /** Number of live entries (enqueued, not yet dequeued or cancelled). */
22
+ get size(): number;
23
+ /** Append a value and return a node handle usable to cancel it later. O(1). */
24
+ enqueue(opts: {
25
+ value: T;
26
+ }): IHfQueueNode<T>;
27
+ /** Remove + return the next live value in FIFO order, skipping cancelled nodes. Null when empty. */
28
+ dequeue(): TNullable<T>;
29
+ /** Mark a still-queued node cancelled so {@link dequeue} and {@link size} skip it. Idempotent. O(1). */
30
+ cancel(opts: {
31
+ node: IHfQueueNode<T>;
32
+ }): void;
33
+ /** Remove and return every remaining LIVE value in FIFO order (e.g. on shutdown), emptying the queue. */
34
+ drain(): T[];
35
+ private reset;
36
+ }
37
+ //# sourceMappingURL=helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../../../../../src/modules/queue/internal/hf/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC;;;;;;;;GAQG;AACH,qBAAa,aAAa,CAAC,CAAC,CAAE,SAAQ,UAAU;IAC9C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAE/C,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,SAAS,CAAK;IAGtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAO;gBAEpC,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAIrC,wEAAwE;IACxE,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,+EAA+E;IAC/E,OAAO,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,CAAC,CAAA;KAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IAQ5C,oGAAoG;IACpG,OAAO,IAAI,SAAS,CAAC,CAAC,CAAC;IAyBvB,wGAAwG;IACxG,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,CAAA;KAAE,GAAG,IAAI;IAS7C,yGAAyG;IACzG,KAAK,IAAI,CAAC,EAAE;IAaZ,OAAO,CAAC,KAAK;CAKd"}