@venizia/ignis-helpers 0.0.8-12 → 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.
- package/dist/modules/index.d.ts +1 -0
- package/dist/modules/index.d.ts.map +1 -1
- package/dist/modules/index.js +1 -0
- package/dist/modules/index.js.map +1 -1
- package/dist/modules/pool/helper.d.ts +100 -0
- package/dist/modules/pool/helper.d.ts.map +1 -0
- package/dist/modules/pool/helper.js +326 -0
- package/dist/modules/pool/helper.js.map +1 -0
- package/dist/modules/pool/index.d.ts +3 -0
- package/dist/modules/pool/index.d.ts.map +1 -0
- package/dist/modules/pool/index.js +19 -0
- package/dist/modules/pool/index.js.map +1 -0
- package/dist/modules/pool/types.d.ts +62 -0
- package/dist/modules/pool/types.d.ts.map +1 -0
- package/dist/modules/pool/types.js +3 -0
- package/dist/modules/pool/types.js.map +1 -0
- package/dist/modules/queue/internal/hf/helper.d.ts +37 -0
- package/dist/modules/queue/internal/hf/helper.d.ts.map +1 -0
- package/dist/modules/queue/internal/hf/helper.js +82 -0
- package/dist/modules/queue/internal/hf/helper.js.map +1 -0
- package/dist/modules/queue/internal/hf/index.d.ts +3 -0
- package/dist/modules/queue/internal/hf/index.d.ts.map +1 -0
- package/dist/modules/queue/internal/hf/index.js +19 -0
- package/dist/modules/queue/internal/hf/index.js.map +1 -0
- package/dist/modules/queue/internal/hf/types.d.ts +9 -0
- package/dist/modules/queue/internal/hf/types.d.ts.map +1 -0
- package/dist/modules/queue/internal/hf/types.js +3 -0
- package/dist/modules/queue/internal/hf/types.js.map +1 -0
- package/dist/modules/queue/internal/index.d.ts +2 -1
- package/dist/modules/queue/internal/index.d.ts.map +1 -1
- package/dist/modules/queue/internal/index.js +2 -1
- package/dist/modules/queue/internal/index.js.map +1 -1
- package/dist/modules/queue/internal/sequential/helper.d.ts +40 -0
- package/dist/modules/queue/internal/sequential/helper.d.ts.map +1 -0
- package/dist/modules/queue/internal/{helper.js → sequential/helper.js} +26 -32
- package/dist/modules/queue/internal/sequential/helper.js.map +1 -0
- package/dist/modules/queue/internal/sequential/index.d.ts +3 -0
- package/dist/modules/queue/internal/sequential/index.d.ts.map +1 -0
- package/dist/modules/queue/internal/sequential/index.js +19 -0
- package/dist/modules/queue/internal/sequential/index.js.map +1 -0
- package/dist/modules/queue/internal/sequential/types.d.ts +35 -0
- package/dist/modules/queue/internal/sequential/types.d.ts.map +1 -0
- package/dist/modules/queue/internal/sequential/types.js +15 -0
- package/dist/modules/queue/internal/sequential/types.js.map +1 -0
- package/dist/modules/queue/kafka/consumer.js +4 -4
- package/dist/modules/queue/kafka/consumer.js.map +1 -1
- package/package.json +1 -1
- package/dist/modules/queue/internal/helper.d.ts +0 -69
- package/dist/modules/queue/internal/helper.d.ts.map +0 -1
- package/dist/modules/queue/internal/helper.js.map +0 -1
package/dist/modules/index.d.ts
CHANGED
|
@@ -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"}
|
package/dist/modules/index.js
CHANGED
|
@@ -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":"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"}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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"}
|