performance-helpers 1.0.0 → 1.0.1
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/README.md +12 -2
- package/package.json +146 -1
- package/src/index.js +1 -0
- package/.eslintrc.cjs +0 -22
- package/.nojekyll +0 -0
- package/.prettierrc +0 -6
- package/CONTRIBUTING.md +0 -178
- package/assets/1_Caching.md +0 -4
- package/assets/2_Parallelizing.md +0 -18
- package/assets/3_Logging.md +0 -3
- package/assets/404.md +0 -3
- package/assets/4_Utils.md +0 -10
- package/assets/logo.png +0 -0
- package/assets/navigation.md +0 -10
- package/bench/README.md +0 -97
- package/bench/results.json +0 -94
- package/bench/results.md +0 -233
- package/bench/run.js +0 -2639
- package/bench/worker.js +0 -43
- package/docs/README.md +0 -38
- package/docs/docs-typedoc.json +0 -38714
- package/docs/helpers/constants/README.md +0 -34
- package/docs/helpers/constants/variables/DEFAULT_AUTOSCALE_BACKOFF_MAX_MULTIPLIER.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_AUTOSCALE_COOLDOWN_MS.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_AUTOSCALE_INTERVAL_MS.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_AUTOSCALE_MIN_INTERVAL_MS.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_BACKPRESSURE_QUEUE_CAPACITY.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_BACKPRESSURE_REFILL_INTERVAL_MS.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_BATCH_MAX_SIZE.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_CACHE_DEFAULT_TTL_MS.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_CACHE_MAX_POOL_SIZE.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_CACHE_MAX_WEIGHT_BYTES.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_HISTOGRAM_BUCKET_COUNT.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_HISTOGRAM_MAX_VALUE.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_MAX_CLEANUP_PER_TICK.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_QUEUE_CAPACITY.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_REAPER_MIN_INTERVAL_MS.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_REFILL_INTERVAL_MS.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_RETRY_BASE_DELAY_MS.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_RETRY_MAX_DELAY_MS.md +0 -9
- package/docs/helpers/constants/variables/DEFAULT_TIMEOUT_MS.md +0 -9
- package/docs/helpers/constants/variables/ENCODE_CACHE_LARGE_KEY_LENGTH.md +0 -9
- package/docs/helpers/constants/variables/MAX_DEEP_EQUAL_DEPTH.md +0 -9
- package/docs/helpers/constants/variables/MS_PER_MIN.md +0 -9
- package/docs/helpers/constants/variables/MS_PER_SEC.md +0 -9
- package/docs/helpers/constants/variables/default.md +0 -103
- package/docs/helpers/jsdoc-types/README.md +0 -33
- package/docs/helpers/jsdoc-types/interfaces/BufferDecoder.md +0 -23
- package/docs/helpers/jsdoc-types/interfaces/BufferEncoder.md +0 -23
- package/docs/helpers/jsdoc-types/interfaces/CacheNode.md +0 -43
- package/docs/helpers/jsdoc-types/interfaces/CommonPoolOptions.md +0 -31
- package/docs/helpers/jsdoc-types/interfaces/PendingResponseEntry.md +0 -51
- package/docs/helpers/jsdoc-types/interfaces/PostMessageOptions.md +0 -39
- package/docs/helpers/jsdoc-types/interfaces/PowerBatchOptions.md +0 -13
- package/docs/helpers/jsdoc-types/interfaces/PowerCacheOptions.md +0 -115
- package/docs/helpers/jsdoc-types/interfaces/PowerChunkingOptions.md +0 -31
- package/docs/helpers/jsdoc-types/interfaces/PowerCircuitOptions.md +0 -45
- package/docs/helpers/jsdoc-types/interfaces/PowerDeadlineOptions.md +0 -101
- package/docs/helpers/jsdoc-types/interfaces/PowerDeferOptions.md +0 -13
- package/docs/helpers/jsdoc-types/interfaces/PowerEventBusOptions.md +0 -19
- package/docs/helpers/jsdoc-types/interfaces/PowerLatchOptions.md +0 -23
- package/docs/helpers/jsdoc-types/interfaces/PowerLoggerOptions.md +0 -51
- package/docs/helpers/jsdoc-types/interfaces/PowerObserverOptions.md +0 -25
- package/docs/helpers/jsdoc-types/interfaces/PowerPoolOptions.md +0 -85
- package/docs/helpers/jsdoc-types/interfaces/PowerQueueOptions.md +0 -13
- package/docs/helpers/jsdoc-types/interfaces/PowerRetryOptions.md +0 -83
- package/docs/helpers/jsdoc-types/interfaces/PowerSlidingWindowOptions.md +0 -19
- package/docs/helpers/jsdoc-types/interfaces/PowerTTLMapOptions.md +0 -27
- package/docs/helpers/jsdoc-types/interfaces/PowerThrottleOptions.md +0 -31
- package/docs/helpers/jsdoc-types/interfaces/WorkerObj.md +0 -55
- package/docs/helpers/powerBackpressure/README.md +0 -17
- package/docs/helpers/powerBackpressure/classes/PowerBackpressure.md +0 -368
- package/docs/helpers/powerBatch/README.md +0 -17
- package/docs/helpers/powerBatch/classes/PowerBatch.md +0 -139
- package/docs/helpers/powerBuffer/README.md +0 -26
- package/docs/helpers/powerBuffer/functions/b2o.md +0 -25
- package/docs/helpers/powerBuffer/functions/o2b.md +0 -23
- package/docs/helpers/powerBuffer/functions/o2u8.md +0 -33
- package/docs/helpers/powerBuffer/functions/u82o.md +0 -30
- package/docs/helpers/powerBulkhead/README.md +0 -17
- package/docs/helpers/powerBulkhead/classes/PowerBulkhead.md +0 -302
- package/docs/helpers/powerCache/README.md +0 -29
- package/docs/helpers/powerCache/classes/PowerCache.md +0 -933
- package/docs/helpers/powerCache/classes/PowerMemoizer.md +0 -244
- package/docs/helpers/powerCache/classes/PowerTimedCache.md +0 -302
- package/docs/helpers/powerCache/functions/simpleArgsKey.md +0 -31
- package/docs/helpers/powerChunking/README.md +0 -17
- package/docs/helpers/powerChunking/classes/PowerChunker.md +0 -78
- package/docs/helpers/powerCircuit/README.md +0 -23
- package/docs/helpers/powerCircuit/classes/PowerCircuit.md +0 -167
- package/docs/helpers/powerDeadline/README.md +0 -23
- package/docs/helpers/powerDeadline/classes/PowerDeadline.md +0 -88
- package/docs/helpers/powerDefer/README.md +0 -17
- package/docs/helpers/powerDefer/classes/PowerDefer.md +0 -134
- package/docs/helpers/powerEventBus/README.md +0 -23
- package/docs/helpers/powerEventBus/classes/PowerEventBus.md +0 -330
- package/docs/helpers/powerHistogram/README.md +0 -17
- package/docs/helpers/powerHistogram/classes/PowerHistogram.md +0 -285
- package/docs/helpers/powerLatch/README.md +0 -17
- package/docs/helpers/powerLatch/classes/PowerLatch.md +0 -264
- package/docs/helpers/powerLogger/README.md +0 -17
- package/docs/helpers/powerLogger/classes/PowerLogger.md +0 -290
- package/docs/helpers/powerObserver/README.md +0 -23
- package/docs/helpers/powerObserver/classes/PowerObserver.md +0 -213
- package/docs/helpers/powerPermitGate/README.md +0 -11
- package/docs/helpers/powerPermitGate/classes/PowerPermitGate.md +0 -248
- package/docs/helpers/powerPool/README.md +0 -36
- package/docs/helpers/powerPool/classes/PowerPool.md +0 -973
- package/docs/helpers/powerPool/classes/PowerPoolShutdownError.md +0 -67
- package/docs/helpers/powerQueue/README.md +0 -11
- package/docs/helpers/powerQueue/classes/PowerQueue.md +0 -302
- package/docs/helpers/powerRateLimit/README.md +0 -17
- package/docs/helpers/powerRateLimit/classes/PowerRateLimit.md +0 -187
- package/docs/helpers/powerRetry/README.md +0 -23
- package/docs/helpers/powerRetry/classes/PowerRetry.md +0 -106
- package/docs/helpers/powerScheduler/README.md +0 -11
- package/docs/helpers/powerScheduler/classes/PowerScheduler.md +0 -135
- package/docs/helpers/powerSemaphore/README.md +0 -17
- package/docs/helpers/powerSemaphore/classes/PowerSemaphore.md +0 -173
- package/docs/helpers/powerSlidingWindow/README.md +0 -11
- package/docs/helpers/powerSlidingWindow/classes/PowerSlidingWindow.md +0 -83
- package/docs/helpers/powerSubscriberSet/README.md +0 -15
- package/docs/helpers/powerSubscriberSet/classes/PowerSubscriberSet.md +0 -251
- package/docs/helpers/powerSubscriberSet/functions/cleanupWeakRefs.md +0 -21
- package/docs/helpers/powerTTLMap/README.md +0 -17
- package/docs/helpers/powerTTLMap/classes/PowerTTLMap.md +0 -326
- package/docs/helpers/powerThrottle/README.md +0 -17
- package/docs/helpers/powerThrottle/classes/PowerThrottle.md +0 -216
- package/docs/index/README.md +0 -205
- package/docs/utils/errors/README.md +0 -12
- package/docs/utils/errors/functions/formatErrorObj.md +0 -30
- package/docs/utils/errors/functions/normalizeError.md +0 -50
- package/docs/utils/now/README.md +0 -19
- package/docs/utils/now/functions/measureAsync.md +0 -37
- package/docs/utils/now/functions/measureSync.md +0 -54
- package/docs/utils/now/functions/nowMs.md +0 -24
- package/guides/autoscale.md +0 -80
- package/guides/errors.md +0 -41
- package/guides/metaGuide.md +0 -440
- package/guides/now.md +0 -56
- package/guides/powerBackpressure.md +0 -110
- package/guides/powerBatch.md +0 -82
- package/guides/powerBuffer.md +0 -86
- package/guides/powerBulkhead.md +0 -61
- package/guides/powerCache.md +0 -269
- package/guides/powerChunking.md +0 -130
- package/guides/powerCircuit.md +0 -84
- package/guides/powerDeadline.md +0 -99
- package/guides/powerDefer.md +0 -56
- package/guides/powerEventBus.md +0 -89
- package/guides/powerHistogram.md +0 -71
- package/guides/powerLatch.md +0 -94
- package/guides/powerLogger.md +0 -129
- package/guides/powerObserver.md +0 -65
- package/guides/powerPermitGate.md +0 -52
- package/guides/powerPool.md +0 -321
- package/guides/powerQueue.md +0 -112
- package/guides/powerRateLimit.md +0 -37
- package/guides/powerRetry.md +0 -54
- package/guides/powerScheduler.md +0 -41
- package/guides/powerSemaphore.md +0 -65
- package/guides/powerSlidingWindow.md +0 -63
- package/guides/powerSubscriberSet.md +0 -48
- package/guides/powerTTLMap.md +0 -58
- package/guides/powerThrottle.md +0 -152
- package/index.html +0 -57
- package/results.json +0 -6692
- package/scripts/find-missing-jsdoc.js +0 -62
- package/scripts/modernize-optional-chaining.cjs +0 -36
- package/scripts/pool-debug.mjs +0 -29
- package/scripts/repro_powercache.js +0 -14
- package/scripts/static-audit-exports.cjs +0 -93
- package/scripts/static-audit-exports.json +0 -518
- package/test/powerBackpressure.test.js +0 -114
- package/test/powerBatch.branches.extra.test.js +0 -122
- package/test/powerBatch.test.js +0 -79
- package/test/powerBuffer.test.js +0 -125
- package/test/powerBulkhead.test.js +0 -210
- package/test/powerCache.branches.test.js +0 -233
- package/test/powerCache.bulk.test.js +0 -31
- package/test/powerCache.getorset.test.js +0 -110
- package/test/powerCache.hitRate.test.js +0 -35
- package/test/powerCache.inflight.test.js +0 -24
- package/test/powerCache.iterator.test.js +0 -18
- package/test/powerCache.misses.test.js +0 -52
- package/test/powerCache.more.test.js +0 -118
- package/test/powerCache.test.js +0 -37
- package/test/powerCache.timeout.test.js +0 -25
- package/test/powerCache.touch.test.js +0 -46
- package/test/powerChunking.branches.extra.test.js +0 -155
- package/test/powerChunking.errors.test.js +0 -177
- package/test/powerChunking.test.js +0 -39
- package/test/powerCircuit.observability.test.js +0 -71
- package/test/powerCircuit.test.js +0 -74
- package/test/powerDeadline.test.js +0 -140
- package/test/powerDefer.test.js +0 -55
- package/test/powerErrors.test.js +0 -32
- package/test/powerEventBus.branches.extra.test.js +0 -70
- package/test/powerEventBus.extra.test.js +0 -72
- package/test/powerEventBus.max.test.js +0 -43
- package/test/powerEventBus.more.test.js +0 -121
- package/test/powerEventBus.once_off.test.js +0 -17
- package/test/powerEventBus.test.js +0 -74
- package/test/powerEventBus.uncovered.test.js +0 -57
- package/test/powerEventBus.weak.test.js +0 -18
- package/test/powerHistogram.test.js +0 -73
- package/test/powerLatch.branches.extra.test.js +0 -115
- package/test/powerLatch.test.js +0 -57
- package/test/powerLogger.branches.test.js +0 -98
- package/test/powerLogger.formatter.name.test.js +0 -58
- package/test/powerLogger.json.test.js +0 -88
- package/test/powerLogger.output.test.js +0 -81
- package/test/powerLogger.table.debug.test.js +0 -77
- package/test/powerLogger.test.js +0 -59
- package/test/powerMemoizer.memoize.test.js +0 -100
- package/test/powerMemoizer.test.js +0 -85
- package/test/powerObserver.test.js +0 -129
- package/test/powerPermitGate.test.js +0 -66
- package/test/powerPool.autoTransfer.test.js +0 -100
- package/test/powerPool.autoscale.extra.test.js +0 -88
- package/test/powerPool.autoscale.test.js +0 -136
- package/test/powerPool.awaitDefaultTimeout.test.js +0 -52
- package/test/powerPool.awaitTimeout.test.js +0 -22
- package/test/powerPool.batch.test.js +0 -170
- package/test/powerPool.branches.extra2.test.js +0 -42
- package/test/powerPool.branches.test.js +0 -102
- package/test/powerPool.browser.messageerror.test.js +0 -45
- package/test/powerPool.correlation.test.js +0 -26
- package/test/powerPool.correlationId.test.js +0 -63
- package/test/powerPool.dispose.test.js +0 -49
- package/test/powerPool.drain.test.js +0 -57
- package/test/powerPool.events.test.js +0 -131
- package/test/powerPool.more.extra.test.js +0 -99
- package/test/powerPool.more.test.js +0 -283
- package/test/powerPool.node.messageerror.test.js +0 -46
- package/test/powerPool.postMessage.promise.test.js +0 -83
- package/test/powerPool.queueHigh.test.js +0 -55
- package/test/powerPool.queueSaturation.test.js +0 -51
- package/test/powerPool.rapidResize.test.js +0 -55
- package/test/powerPool.resize.overload.test.js +0 -65
- package/test/powerPool.resize.test.js +0 -70
- package/test/powerPool.shutdown.test.js +0 -38
- package/test/powerPool.stats.test.js +0 -40
- package/test/powerPool.stopThePress.test.js +0 -94
- package/test/powerPool.terminateShutdown.test.js +0 -22
- package/test/powerPool.test.js +0 -525
- package/test/powerPool.timers.test.js +0 -55
- package/test/powerPool.uncovered.test.js +0 -407
- package/test/powerPool.workerId.test.js +0 -47
- package/test/powerQueue.iterators.test.js +0 -67
- package/test/powerQueue.saturation.test.js +0 -18
- package/test/powerQueue.test.js +0 -48
- package/test/powerQueue.unshiftMany.test.js +0 -49
- package/test/powerRateLimit.atomic.test.js +0 -80
- package/test/powerRateLimit.extra.test.js +0 -145
- package/test/powerRateLimit.functions.test.js +0 -106
- package/test/powerRateLimit.test.js +0 -38
- package/test/powerRetry.attemptTimeout.test.js +0 -51
- package/test/powerRetry.test.js +0 -121
- package/test/powerScheduler.test.js +0 -126
- package/test/powerSemaphore.test.js +0 -108
- package/test/powerSlidingWindow.pool.test.js +0 -55
- package/test/powerSlidingWindow.test.js +0 -25
- package/test/powerSubscriberSet.test.js +0 -125
- package/test/powerTTLMap.test.js +0 -125
- package/test/powerThrottle.pool.test.js +0 -54
- package/test/powerThrottle.refill.test.js +0 -22
- package/test/powerThrottle.reserve.test.js +0 -46
- package/test/powerThrottle.test.js +0 -45
- package/test/powerTimedCache.test.js +0 -73
- package/test/umd.bundle.branches.test.js +0 -100
- package/test/umd.bundle.cache-timers.test.js +0 -48
- package/test/umd.bundle.exhaustive.test.js +0 -158
- package/test/umd.bundle.fuzz.test.js +0 -86
- package/test/umd.bundle.hasEqual.more.test.js +0 -68
- package/test/umd.bundle.hasEqual.test.js +0 -104
- package/test/umd.bundle.logger-extra.test.js +0 -48
- package/test/umd.bundle.more-coverage-2.test.js +0 -67
- package/test/umd.bundle.pool.test.js +0 -134
- package/test/umd.bundle.test.js +0 -265
- package/test/utils.measure.test.js +0 -49
- package/test/utils.now.extra.test.js +0 -30
- package/test/utils.now.more.test.js +0 -57
- package/tsconfig.json +0 -16
- package/typedoc.json +0 -25
- package/vite.config.js +0 -31
- package/vitest.config.js +0 -17
|
@@ -1,407 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import { PowerPool } from '../src/helpers/powerPool.js';
|
|
3
|
-
|
|
4
|
-
describe('PowerPool uncovered branches', () => {
|
|
5
|
-
it('onidle setter swallows thrown handlers and logs error', () => {
|
|
6
|
-
// Use a minimal stub underlying to avoid actual worker behavior
|
|
7
|
-
function Stub() {}
|
|
8
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
9
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
10
|
-
pool.onidle = () => {
|
|
11
|
-
throw new Error('boom onidle');
|
|
12
|
-
};
|
|
13
|
-
// setting when pool is already idle should invoke handler immediately
|
|
14
|
-
expect(pool._logger.error).toHaveBeenCalled();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('onidle setter swallows thrown handlers when pool has workers', () => {
|
|
18
|
-
function Stub() {}
|
|
19
|
-
const pool = new PowerPool(Stub, { minSize: 1, lazy: false });
|
|
20
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
21
|
-
// pool has workers but no active tasks -> considered idle
|
|
22
|
-
pool.onidle = () => {
|
|
23
|
-
throw new Error('boom onidle2');
|
|
24
|
-
};
|
|
25
|
-
expect(pool._logger.error).toHaveBeenCalled();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('getters for onmessage/onerror/onidle return underlying handlers', () => {
|
|
29
|
-
function Stub() {}
|
|
30
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
31
|
-
const m = () => {};
|
|
32
|
-
const e = () => {};
|
|
33
|
-
const i = () => {};
|
|
34
|
-
pool._onmessage = m;
|
|
35
|
-
pool._onerror = e;
|
|
36
|
-
pool._onidle = i;
|
|
37
|
-
expect(pool.onmessage).toBe(m);
|
|
38
|
-
expect(pool.onerror).toBe(e);
|
|
39
|
-
expect(pool.onidle).toBe(i);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('getter for onresize returns underlying handler', () => {
|
|
43
|
-
function Stub() {}
|
|
44
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
45
|
-
const r = () => {};
|
|
46
|
-
pool._onresize = r;
|
|
47
|
-
expect(pool.onresize).toBe(r);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('logs when bus.emit("idle") throws during _emitIdle', () => {
|
|
51
|
-
function Stub() {}
|
|
52
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
53
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
54
|
-
// make bus.emit throw when emitting 'idle'
|
|
55
|
-
const origEmit = pool._bus.emit.bind(pool._bus);
|
|
56
|
-
pool._bus.emit = (type, ev) => {
|
|
57
|
-
if (type === 'idle') throw new Error('boom idle emit');
|
|
58
|
-
return origEmit(type, ev);
|
|
59
|
-
};
|
|
60
|
-
// call internal emitter directly
|
|
61
|
-
pool._emitIdle();
|
|
62
|
-
expect(pool._logger.error).toHaveBeenCalled();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('logs when bus.emit("message") throws during _emitIdle', () => {
|
|
66
|
-
function Stub() {}
|
|
67
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
68
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
69
|
-
// make bus.emit throw when emitting 'message'
|
|
70
|
-
const origEmit = pool._bus.emit.bind(pool._bus);
|
|
71
|
-
pool._bus.emit = (type, ev) => {
|
|
72
|
-
if (type === 'message') throw new Error('boom message emit');
|
|
73
|
-
return origEmit(type, ev);
|
|
74
|
-
};
|
|
75
|
-
pool._emitIdle();
|
|
76
|
-
expect(pool._logger.error).toHaveBeenCalled();
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('setters for onmessage/onerror/onresize assign via property', () => {
|
|
80
|
-
function Stub() {}
|
|
81
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
82
|
-
const m = () => {};
|
|
83
|
-
const e = () => {};
|
|
84
|
-
const r = () => {};
|
|
85
|
-
pool.onmessage = m;
|
|
86
|
-
pool.onerror = e;
|
|
87
|
-
pool.onresize = r;
|
|
88
|
-
expect(pool._onmessage).toBe(m);
|
|
89
|
-
expect(pool._onerror).toBe(e);
|
|
90
|
-
expect(pool._onresize).toBe(r);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('_emitIdle catches thrown _onmessage and _onidle handlers and logs errors', () => {
|
|
94
|
-
function Stub() {}
|
|
95
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
96
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
97
|
-
pool._onmessage = () => {
|
|
98
|
-
throw new Error('boom onmessage internal');
|
|
99
|
-
};
|
|
100
|
-
pool._onidle = () => {
|
|
101
|
-
throw new Error('boom onidle internal');
|
|
102
|
-
};
|
|
103
|
-
pool._emitIdle();
|
|
104
|
-
expect(pool._logger.error).toHaveBeenCalled();
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('_reapIdleWorkers removes a single non-last worker via swap-and-pop without throwing', () => {
|
|
108
|
-
function Stub() {}
|
|
109
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true, idleTimeout: 1 });
|
|
110
|
-
// create multiple workers
|
|
111
|
-
const w = pool.addWorker();
|
|
112
|
-
// ensure underlying wrapper has a working postMessage
|
|
113
|
-
w.worker.postMessage = vi.fn();
|
|
114
|
-
pool.addWorker();
|
|
115
|
-
pool.addWorker();
|
|
116
|
-
const now = Date.now();
|
|
117
|
-
// make only the middle worker idle beyond idleTimeout
|
|
118
|
-
for (let i = 0; i < pool.workers.length; i++) {
|
|
119
|
-
const w = pool.workers[i];
|
|
120
|
-
if (i === 1) {
|
|
121
|
-
w.tasks = 0;
|
|
122
|
-
w.lastActive = now - 10000;
|
|
123
|
-
} else {
|
|
124
|
-
w.tasks = 1; // busy
|
|
125
|
-
w.lastActive = now;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
expect(() => pool._reapIdleWorkers()).not.toThrow();
|
|
129
|
-
expect(pool.workers.length).toBeLessThan(3);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it('stopThePressBatch clears reaper interval when recreateWorkers is false', () => {
|
|
133
|
-
function Stub() {}
|
|
134
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
135
|
-
pool._reaperInterval = setInterval(() => {}, 10000);
|
|
136
|
-
pool.stopThePressBatch([], { recreateWorkers: false });
|
|
137
|
-
expect(pool._reaperInterval).toBeNull();
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('stopThePressBatch logs when terminating workers throws unexpectedly', () => {
|
|
141
|
-
function Stub() {}
|
|
142
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
143
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
144
|
-
// make workers.length readable but accessing an index throws inside the try
|
|
145
|
-
const proxy = new Proxy(
|
|
146
|
-
{ length: 1, 0: { worker: { terminate: () => {} }, completedTasks: 0 } },
|
|
147
|
-
{
|
|
148
|
-
get(target, prop) {
|
|
149
|
-
if (prop === 'length') return 1;
|
|
150
|
-
if (String(prop) === '0') throw new Error('boom term');
|
|
151
|
-
return Reflect.get(target, prop);
|
|
152
|
-
},
|
|
153
|
-
}
|
|
154
|
-
);
|
|
155
|
-
Object.defineProperty(pool, 'workers', {
|
|
156
|
-
get: () => proxy,
|
|
157
|
-
configurable: true,
|
|
158
|
-
});
|
|
159
|
-
pool.stopThePressBatch([], { recreateWorkers: false });
|
|
160
|
-
expect(pool._logger.error).toHaveBeenCalled();
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('postMessageBatch logs when queue.pushMany throws', () => {
|
|
164
|
-
function Stub() {}
|
|
165
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true, maxSize: 0 });
|
|
166
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
167
|
-
pool.taskQueueEnabled = true;
|
|
168
|
-
pool.queue = {
|
|
169
|
-
pushMany: () => {
|
|
170
|
-
throw new Error('boom pushMany');
|
|
171
|
-
},
|
|
172
|
-
};
|
|
173
|
-
pool.postMessageBatch([{ message: 'x' }]);
|
|
174
|
-
expect(pool._logger.error).toHaveBeenCalled();
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it('stopThePressBatch logs when queue.clear throws', () => {
|
|
178
|
-
function Stub() {}
|
|
179
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
180
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
181
|
-
pool.queue = {
|
|
182
|
-
clear: () => {
|
|
183
|
-
throw new Error('boom clear');
|
|
184
|
-
},
|
|
185
|
-
};
|
|
186
|
-
pool.stopThePressBatch([], { recreateWorkers: false });
|
|
187
|
-
expect(pool._logger.error).toHaveBeenCalled();
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
it('stopThePressBatch logs when pendingResponses.entries throws', () => {
|
|
191
|
-
function Stub() {}
|
|
192
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
193
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
194
|
-
pool._pendingResponses = {
|
|
195
|
-
entries: () => {
|
|
196
|
-
throw new Error('boom pending');
|
|
197
|
-
},
|
|
198
|
-
};
|
|
199
|
-
pool.stopThePressBatch([], { recreateWorkers: false });
|
|
200
|
-
expect(pool._logger.error).toHaveBeenCalled();
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('postMessageBatch handles _addWorkerInstance throwing and marks result false', () => {
|
|
204
|
-
function Stub() {}
|
|
205
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true, maxSize: 1 });
|
|
206
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
207
|
-
// force worker creation path to throw
|
|
208
|
-
pool._addWorkerInstance = () => {
|
|
209
|
-
throw new Error('boom add');
|
|
210
|
-
};
|
|
211
|
-
const res = pool.postMessageBatch([{ message: 'x' }]);
|
|
212
|
-
expect(res[0]).toBe(false);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
it('postMessageBatch fallback to existing worker logs when fallback.postMessage throws', () => {
|
|
216
|
-
function Stub() {}
|
|
217
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true, maxSize: 1 });
|
|
218
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
219
|
-
// ensure one existing worker to trigger fallback path
|
|
220
|
-
const wobj = pool.addWorker();
|
|
221
|
-
// make fallback worker.postMessage throw and force fallback path
|
|
222
|
-
wobj.worker.postMessage = () => {
|
|
223
|
-
throw new Error('boom fallback');
|
|
224
|
-
};
|
|
225
|
-
pool.taskQueueEnabled = false;
|
|
226
|
-
pool._maxTasksPerWorker = 0;
|
|
227
|
-
const res = pool.postMessageBatch([{ message: 'x' }]);
|
|
228
|
-
expect(pool._logger.error).toHaveBeenCalled();
|
|
229
|
-
expect(res[0]).toBe(false);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it('postMessageBatch fallback to existing worker success path updates worker state', () => {
|
|
233
|
-
function Stub() {}
|
|
234
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true, maxSize: 1 });
|
|
235
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
236
|
-
const wobj = pool.addWorker();
|
|
237
|
-
wobj._startTimes = [];
|
|
238
|
-
// successful postMessage with transfer
|
|
239
|
-
const pm = vi.fn();
|
|
240
|
-
wobj.worker.postMessage = pm;
|
|
241
|
-
pool.taskQueueEnabled = false;
|
|
242
|
-
pool._maxTasksPerWorker = 0;
|
|
243
|
-
const transfer = [new ArrayBuffer(1)];
|
|
244
|
-
const res = pool.postMessageBatch([{ message: 'ok', transfer }]);
|
|
245
|
-
expect(res[0]).toBe(true);
|
|
246
|
-
expect(pm).toHaveBeenCalledWith('ok', transfer);
|
|
247
|
-
expect(Array.isArray(wobj._startTimes) && wobj._startTimes.length).toBeTruthy();
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('postMessageBatch creates a new worker when pool can grow and succeeds', () => {
|
|
251
|
-
function Stub() {}
|
|
252
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true, maxSize: 1 });
|
|
253
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
254
|
-
// stub _addWorkerInstance to create and register a worker
|
|
255
|
-
pool._addWorkerInstance = () => {
|
|
256
|
-
const o = { worker: { postMessage: vi.fn() }, tasks: 0, _startTimes: [], lastActive: 0 };
|
|
257
|
-
pool.workers.push(o);
|
|
258
|
-
return o;
|
|
259
|
-
};
|
|
260
|
-
const res = pool.postMessageBatch([{ message: 'new' }]);
|
|
261
|
-
expect(res[0]).toBe(true);
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it('postMessageBatch least-worker postMessage throwing marks result false', () => {
|
|
265
|
-
function Stub() {}
|
|
266
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true, maxSize: 1 });
|
|
267
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
268
|
-
const w = pool.addWorker();
|
|
269
|
-
// ensure least path is taken
|
|
270
|
-
pool._maxTasksPerWorker = 1;
|
|
271
|
-
w.worker.postMessage = () => {
|
|
272
|
-
throw new Error('boom least');
|
|
273
|
-
};
|
|
274
|
-
const res = pool.postMessageBatch([{ message: 'x' }]);
|
|
275
|
-
expect(res[0]).toBe(false);
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
it('postMessageBatch create-new-worker uses transfer when provided', () => {
|
|
279
|
-
function Stub() {}
|
|
280
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true, maxSize: 1 });
|
|
281
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
282
|
-
// stub _addWorkerInstance to create and register a worker
|
|
283
|
-
pool._addWorkerInstance = () => {
|
|
284
|
-
const o = { worker: { postMessage: vi.fn() }, tasks: 0, _startTimes: [], lastActive: 0 };
|
|
285
|
-
pool.workers.push(o);
|
|
286
|
-
return o;
|
|
287
|
-
};
|
|
288
|
-
const transfer = [new ArrayBuffer(1)];
|
|
289
|
-
const res = pool.postMessageBatch([{ message: 'new', transfer }]);
|
|
290
|
-
expect(res[0]).toBe(true);
|
|
291
|
-
// ensure new worker postMessage was called with transfer
|
|
292
|
-
expect(pool.workers[0].worker.postMessage).toHaveBeenCalledWith('new', transfer);
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
it('postMessageBatch returns false when no workers and cannot grow', () => {
|
|
296
|
-
function Stub() {}
|
|
297
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true, maxSize: 0 });
|
|
298
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
299
|
-
pool.taskQueueEnabled = false;
|
|
300
|
-
const res = pool.postMessageBatch([{ message: 'nope' }]);
|
|
301
|
-
expect(res[0]).toBe(false);
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
it('stopThePress clears reaper interval when recreateWorkers is false', () => {
|
|
305
|
-
function Stub() {}
|
|
306
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
307
|
-
pool._reaperInterval = setInterval(() => {}, 10000);
|
|
308
|
-
pool.stopThePress('x', undefined, { recreateWorkers: false });
|
|
309
|
-
expect(pool._reaperInterval).toBeNull();
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
it('postMessageBatch throws when items is not an array', () => {
|
|
313
|
-
function Stub() {}
|
|
314
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
315
|
-
expect(() => pool.postMessageBatch('not-an-array')).toThrow();
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
it('postMessageBatch with awaitResponse defers to postMessage and returns Promises', () => {
|
|
319
|
-
function Stub() {}
|
|
320
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true, maxSize: 1 });
|
|
321
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
322
|
-
// ensure a worker exists so postMessage awaitResponse can post
|
|
323
|
-
const w = pool.addWorker();
|
|
324
|
-
w.worker.postMessage = vi.fn();
|
|
325
|
-
// use postMessageBatch with awaitResponse option; it should call postMessage per item
|
|
326
|
-
const res = pool.postMessageBatch([{ message: { hello: 'p' } }], { awaitResponse: true });
|
|
327
|
-
expect(res).toBeInstanceOf(Array);
|
|
328
|
-
expect(typeof res[0].then).toBe('function');
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
it('postMessageBatch with workerId uses targeted worker find path', () => {
|
|
332
|
-
function Stub() {}
|
|
333
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true, maxSize: 1 });
|
|
334
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
335
|
-
const w = pool.addWorker();
|
|
336
|
-
w.id = 'worker-1';
|
|
337
|
-
const pm = vi.fn();
|
|
338
|
-
w.worker.postMessage = pm;
|
|
339
|
-
pool.postMessageBatch([{ message: 't' }], { workerId: 'worker-1' });
|
|
340
|
-
expect(pm).toHaveBeenCalled();
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
it('postMessageBatch with a fixed correlationId and multiple items throws', () => {
|
|
344
|
-
function Stub() {}
|
|
345
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true, maxSize: 1 });
|
|
346
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
347
|
-
expect(() =>
|
|
348
|
-
pool.postMessageBatch([{ message: { hello: 'a' } }, { message: { hello: 'b' } }], {
|
|
349
|
-
awaitResponse: true,
|
|
350
|
-
correlationId: 'shared-id',
|
|
351
|
-
})
|
|
352
|
-
).toThrow(
|
|
353
|
-
'postMessageBatch cannot use a fixed correlationId for multiple items; provide options.correlationIdFactory or omit correlationId'
|
|
354
|
-
);
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
it('prepareBuffers supports raw ArrayBuffer transfer optimization', () => {
|
|
358
|
-
function Stub() {}
|
|
359
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
360
|
-
const buffer = new ArrayBuffer(16);
|
|
361
|
-
const result = pool.prepareBuffers([buffer]);
|
|
362
|
-
expect(result).toEqual([{ message: buffer, transfer: [buffer] }]);
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
it('prepareBuffers supports typed array transfer optimization', () => {
|
|
366
|
-
function Stub() {}
|
|
367
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
368
|
-
const view = new Uint8Array(new ArrayBuffer(16));
|
|
369
|
-
const result = pool.prepareBuffers([view]);
|
|
370
|
-
expect(result).toEqual([{ message: view, transfer: [view.buffer] }]);
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
it('prepareBuffers supports DataView transfer optimization', () => {
|
|
374
|
-
function Stub() {}
|
|
375
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true });
|
|
376
|
-
const buffer = new ArrayBuffer(16);
|
|
377
|
-
const view = new DataView(buffer);
|
|
378
|
-
const result = pool.prepareBuffers([view]);
|
|
379
|
-
expect(result).toEqual([{ message: view, transfer: [buffer] }]);
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
it('postMessageBatch with unknown targeted worker fails immediately', () => {
|
|
383
|
-
function Stub() {}
|
|
384
|
-
const pool = new PowerPool(Stub, { minSize: 0, lazy: true, maxSize: 1 });
|
|
385
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
386
|
-
const res = pool.postMessageBatch([{ message: 't' }], { workerId: 'missing' });
|
|
387
|
-
expect(res).toEqual([false]);
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
it('postMessageBatch with a busy targeted worker fails instead of queueing', () => {
|
|
391
|
-
function Stub() {}
|
|
392
|
-
const pool = new PowerPool(Stub, {
|
|
393
|
-
minSize: 0,
|
|
394
|
-
lazy: true,
|
|
395
|
-
maxSize: 1,
|
|
396
|
-
maxTasksPerWorker: 1,
|
|
397
|
-
taskQueueEnabled: true,
|
|
398
|
-
});
|
|
399
|
-
pool._logger = { error: vi.fn(), log: () => {} };
|
|
400
|
-
const w = pool.addWorker();
|
|
401
|
-
w.id = 'worker-1';
|
|
402
|
-
w.tasks = 1;
|
|
403
|
-
const res = pool.postMessageBatch([{ message: 't' }], { workerId: 'worker-1' });
|
|
404
|
-
expect(res).toEqual([false]);
|
|
405
|
-
expect(pool.queue.length).toBe(0);
|
|
406
|
-
});
|
|
407
|
-
});
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import { PowerPool } from '../src/helpers/powerPool.js';
|
|
3
|
-
|
|
4
|
-
describe('PowerPool per-worker targeting', () => {
|
|
5
|
-
it('routes a message to the specified workerId when available', () => {
|
|
6
|
-
class MockUnderlying {
|
|
7
|
-
constructor() {
|
|
8
|
-
this.onmessage = null;
|
|
9
|
-
this.postMessage = vi.fn();
|
|
10
|
-
this.terminate = vi.fn();
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const pool = new PowerPool(MockUnderlying, { size: 2, minSize: 2, idleTimeout: 1000 });
|
|
15
|
-
try {
|
|
16
|
-
expect(pool.workers.length).toBeGreaterThanOrEqual(2);
|
|
17
|
-
const target = pool.workers[0];
|
|
18
|
-
const other = pool.workers[1];
|
|
19
|
-
// ensure spies are on the underlying implementations
|
|
20
|
-
const underlyingTarget = target.worker._underlying || target.worker._underlying;
|
|
21
|
-
const underlyingOther = other.worker._underlying || other.worker._underlying;
|
|
22
|
-
pool.postMessage({ hello: 'targeted' }, null, { workerId: target.id });
|
|
23
|
-
expect(underlyingTarget.postMessage).toHaveBeenCalled();
|
|
24
|
-
// other worker should not have been called for this targeted message
|
|
25
|
-
expect(underlyingOther.postMessage).not.toHaveBeenCalled();
|
|
26
|
-
} finally {
|
|
27
|
-
pool.terminate();
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('returns false when targeted worker does not exist', () => {
|
|
32
|
-
class MockUnderlying {
|
|
33
|
-
constructor() {
|
|
34
|
-
this.onmessage = null;
|
|
35
|
-
this.postMessage = vi.fn();
|
|
36
|
-
this.terminate = vi.fn();
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
const pool = new PowerPool(MockUnderlying, { size: 1, minSize: 1 });
|
|
40
|
-
try {
|
|
41
|
-
const res = pool.postMessage({ x: 1 }, null, { workerId: 9999 });
|
|
42
|
-
expect(res).toBe(false);
|
|
43
|
-
} finally {
|
|
44
|
-
pool.terminate();
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
});
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { PowerQueue } from '../src/helpers/powerQueue.js';
|
|
3
|
-
|
|
4
|
-
describe('PowerQueue iterators and helpers', () => {
|
|
5
|
-
it('values() and Symbol.iterator yield values in FIFO order without consuming', () => {
|
|
6
|
-
const q = new PowerQueue(4);
|
|
7
|
-
q.push(1);
|
|
8
|
-
q.push(2);
|
|
9
|
-
q.push(3);
|
|
10
|
-
|
|
11
|
-
// values()
|
|
12
|
-
expect(Array.from(q.values())).toEqual([1, 2, 3]);
|
|
13
|
-
|
|
14
|
-
// default iterator (for...of / spread)
|
|
15
|
-
expect([...q]).toEqual([1, 2, 3]);
|
|
16
|
-
|
|
17
|
-
// original queue must be intact
|
|
18
|
-
expect(q.length).toBe(3);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('keys() yields zero-based indexes corresponding to positions', () => {
|
|
22
|
-
const q = new PowerQueue(4);
|
|
23
|
-
q.push('a');
|
|
24
|
-
q.push('b');
|
|
25
|
-
q.push('c');
|
|
26
|
-
expect(Array.from(q.keys())).toEqual([0, 1, 2]);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('entries() yields [index, value] pairs non-destructively', () => {
|
|
30
|
-
const q = new PowerQueue(4);
|
|
31
|
-
q.push('x');
|
|
32
|
-
q.push('y');
|
|
33
|
-
expect(Array.from(q.entries())).toEqual([
|
|
34
|
-
[0, 'x'],
|
|
35
|
-
[1, 'y'],
|
|
36
|
-
]);
|
|
37
|
-
// still intact
|
|
38
|
-
expect(q.length).toBe(2);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('toArray() returns a shallow FIFO snapshot without consuming', () => {
|
|
42
|
-
const q = new PowerQueue(4);
|
|
43
|
-
q.push(10);
|
|
44
|
-
q.push(20);
|
|
45
|
-
expect(q.toArray()).toEqual([10, 20]);
|
|
46
|
-
expect(q.length).toBe(2);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('drain() consumes the queue and yields items in FIFO order', () => {
|
|
50
|
-
const q = new PowerQueue(4);
|
|
51
|
-
q.push(7);
|
|
52
|
-
q.push(8);
|
|
53
|
-
const result = [];
|
|
54
|
-
for (const v of q.drain()) result.push(v);
|
|
55
|
-
expect(result).toEqual([7, 8]);
|
|
56
|
-
expect(q.length).toBe(0);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('iterators behave correctly on empty queue', () => {
|
|
60
|
-
const q = new PowerQueue(4);
|
|
61
|
-
expect(Array.from(q.values())).toEqual([]);
|
|
62
|
-
expect(Array.from(q.keys())).toEqual([]);
|
|
63
|
-
expect(Array.from(q.entries())).toEqual([]);
|
|
64
|
-
expect(q.toArray()).toEqual([]);
|
|
65
|
-
expect(Array.from(q.drain())).toEqual([]);
|
|
66
|
-
});
|
|
67
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { it, expect } from 'vitest';
|
|
2
|
-
import { PowerQueue } from '../src/helpers/powerQueue.js';
|
|
3
|
-
|
|
4
|
-
it('grows and preserves FIFO order under heavy pushMany usage', () => {
|
|
5
|
-
const q = new PowerQueue(4);
|
|
6
|
-
const N = 1000;
|
|
7
|
-
const arr = new Array(N);
|
|
8
|
-
for (let i = 0; i < N; i++) arr[i] = i;
|
|
9
|
-
q.pushMany(arr);
|
|
10
|
-
expect(q.length).toBe(N);
|
|
11
|
-
// ensure capacity grew at least once
|
|
12
|
-
expect(q.capacity).toBeGreaterThanOrEqual(4);
|
|
13
|
-
for (let i = 0; i < N; i++) {
|
|
14
|
-
const v = q.shift();
|
|
15
|
-
expect(v).toBe(i);
|
|
16
|
-
}
|
|
17
|
-
expect(q.length).toBe(0);
|
|
18
|
-
});
|
package/test/powerQueue.test.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { PowerQueue } from '../src/helpers/powerQueue.js';
|
|
3
|
-
|
|
4
|
-
describe('PowerQueue', () => {
|
|
5
|
-
it('push/shift preserves order and length updates', () => {
|
|
6
|
-
const q = new PowerQueue(4);
|
|
7
|
-
expect(q.length).toBe(0);
|
|
8
|
-
q.push(1);
|
|
9
|
-
q.push(2);
|
|
10
|
-
q.push(3);
|
|
11
|
-
expect(q.length).toBe(3);
|
|
12
|
-
expect(q.shift()).toBe(1);
|
|
13
|
-
expect(q.shift()).toBe(2);
|
|
14
|
-
expect(q.shift()).toBe(3);
|
|
15
|
-
expect(q.shift()).toBeUndefined();
|
|
16
|
-
expect(q.length).toBe(0);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('grows capacity when full and preserves order', () => {
|
|
20
|
-
const q = new PowerQueue(2);
|
|
21
|
-
const pushed = [];
|
|
22
|
-
for (let i = 0; i < 10; i++) {
|
|
23
|
-
q.push(i);
|
|
24
|
-
pushed.push(i);
|
|
25
|
-
}
|
|
26
|
-
expect(q.capacity).toBeGreaterThanOrEqual(10);
|
|
27
|
-
const got = [];
|
|
28
|
-
while (!q.isEmpty) got.push(q.shift());
|
|
29
|
-
expect(got).toEqual(pushed);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('peek returns next item without removing it', () => {
|
|
33
|
-
const q = new PowerQueue(4);
|
|
34
|
-
q.push('a');
|
|
35
|
-
expect(q.peek()).toBe('a');
|
|
36
|
-
expect(q.length).toBe(1);
|
|
37
|
-
expect(q.shift()).toBe('a');
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('clear empties the queue', () => {
|
|
41
|
-
const q = new PowerQueue(4);
|
|
42
|
-
q.push(1);
|
|
43
|
-
q.push(2);
|
|
44
|
-
q.clear();
|
|
45
|
-
expect(q.length).toBe(0);
|
|
46
|
-
expect(q.shift()).toBeUndefined();
|
|
47
|
-
});
|
|
48
|
-
});
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { PowerQueue } from '../src/helpers/powerQueue.js';
|
|
3
|
-
|
|
4
|
-
describe('PowerQueue.unshiftMany', () => {
|
|
5
|
-
it('prepends items to an empty queue and grows as needed', () => {
|
|
6
|
-
const q = new PowerQueue(2);
|
|
7
|
-
const items = [0, 1, 2, 3, 4, 5];
|
|
8
|
-
q.unshiftMany(items);
|
|
9
|
-
expect(q.length).toBe(items.length);
|
|
10
|
-
expect(q.capacity).toBeGreaterThanOrEqual(items.length);
|
|
11
|
-
const got = [];
|
|
12
|
-
while (!q.isEmpty) got.push(q.shift());
|
|
13
|
-
expect(got).toEqual(items);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('preserves order when prepending to a wrapped buffer', () => {
|
|
17
|
-
const q = new PowerQueue(4);
|
|
18
|
-
// fill then consume to cause head/tail to wrap
|
|
19
|
-
q.push(0);
|
|
20
|
-
q.push(1);
|
|
21
|
-
q.push(2);
|
|
22
|
-
q.push(3);
|
|
23
|
-
expect(q.shift()).toBe(0);
|
|
24
|
-
expect(q.shift()).toBe(1);
|
|
25
|
-
// now head points to 2, tail wrapped
|
|
26
|
-
q.unshiftMany(['a', 'b', 'c']);
|
|
27
|
-
expect(q.length).toBe(5);
|
|
28
|
-
const got = [];
|
|
29
|
-
while (!q.isEmpty) got.push(q.shift());
|
|
30
|
-
expect(got).toEqual(['a', 'b', 'c', 2, 3]);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('handles large prepend that forces multiple resizes and keeps order', () => {
|
|
34
|
-
const q = new PowerQueue(4);
|
|
35
|
-
// create some existing items
|
|
36
|
-
q.push('x');
|
|
37
|
-
q.push('y');
|
|
38
|
-
const many = Array.from({ length: 50 }, (_, i) => `p${i}`);
|
|
39
|
-
q.unshiftMany(many);
|
|
40
|
-
expect(q.length).toBe(52);
|
|
41
|
-
const first = q.shift();
|
|
42
|
-
expect(first).toBe('p0');
|
|
43
|
-
// consume some and ensure tail data preserved
|
|
44
|
-
const tail = [];
|
|
45
|
-
while (!q.isEmpty) tail.push(q.shift());
|
|
46
|
-
expect(tail.slice(0, many.length - 1)).toEqual(many.slice(1));
|
|
47
|
-
expect(tail.slice(-2)).toEqual(['x', 'y']);
|
|
48
|
-
});
|
|
49
|
-
});
|