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.
Files changed (287) hide show
  1. package/README.md +12 -2
  2. package/package.json +146 -1
  3. package/src/index.js +1 -0
  4. package/.eslintrc.cjs +0 -22
  5. package/.nojekyll +0 -0
  6. package/.prettierrc +0 -6
  7. package/CONTRIBUTING.md +0 -178
  8. package/assets/1_Caching.md +0 -4
  9. package/assets/2_Parallelizing.md +0 -18
  10. package/assets/3_Logging.md +0 -3
  11. package/assets/404.md +0 -3
  12. package/assets/4_Utils.md +0 -10
  13. package/assets/logo.png +0 -0
  14. package/assets/navigation.md +0 -10
  15. package/bench/README.md +0 -97
  16. package/bench/results.json +0 -94
  17. package/bench/results.md +0 -233
  18. package/bench/run.js +0 -2639
  19. package/bench/worker.js +0 -43
  20. package/docs/README.md +0 -38
  21. package/docs/docs-typedoc.json +0 -38714
  22. package/docs/helpers/constants/README.md +0 -34
  23. package/docs/helpers/constants/variables/DEFAULT_AUTOSCALE_BACKOFF_MAX_MULTIPLIER.md +0 -9
  24. package/docs/helpers/constants/variables/DEFAULT_AUTOSCALE_COOLDOWN_MS.md +0 -9
  25. package/docs/helpers/constants/variables/DEFAULT_AUTOSCALE_INTERVAL_MS.md +0 -9
  26. package/docs/helpers/constants/variables/DEFAULT_AUTOSCALE_MIN_INTERVAL_MS.md +0 -9
  27. package/docs/helpers/constants/variables/DEFAULT_BACKPRESSURE_QUEUE_CAPACITY.md +0 -9
  28. package/docs/helpers/constants/variables/DEFAULT_BACKPRESSURE_REFILL_INTERVAL_MS.md +0 -9
  29. package/docs/helpers/constants/variables/DEFAULT_BATCH_MAX_SIZE.md +0 -9
  30. package/docs/helpers/constants/variables/DEFAULT_CACHE_DEFAULT_TTL_MS.md +0 -9
  31. package/docs/helpers/constants/variables/DEFAULT_CACHE_MAX_POOL_SIZE.md +0 -9
  32. package/docs/helpers/constants/variables/DEFAULT_CACHE_MAX_WEIGHT_BYTES.md +0 -9
  33. package/docs/helpers/constants/variables/DEFAULT_HISTOGRAM_BUCKET_COUNT.md +0 -9
  34. package/docs/helpers/constants/variables/DEFAULT_HISTOGRAM_MAX_VALUE.md +0 -9
  35. package/docs/helpers/constants/variables/DEFAULT_MAX_CLEANUP_PER_TICK.md +0 -9
  36. package/docs/helpers/constants/variables/DEFAULT_QUEUE_CAPACITY.md +0 -9
  37. package/docs/helpers/constants/variables/DEFAULT_REAPER_MIN_INTERVAL_MS.md +0 -9
  38. package/docs/helpers/constants/variables/DEFAULT_REFILL_INTERVAL_MS.md +0 -9
  39. package/docs/helpers/constants/variables/DEFAULT_RETRY_BASE_DELAY_MS.md +0 -9
  40. package/docs/helpers/constants/variables/DEFAULT_RETRY_MAX_DELAY_MS.md +0 -9
  41. package/docs/helpers/constants/variables/DEFAULT_TIMEOUT_MS.md +0 -9
  42. package/docs/helpers/constants/variables/ENCODE_CACHE_LARGE_KEY_LENGTH.md +0 -9
  43. package/docs/helpers/constants/variables/MAX_DEEP_EQUAL_DEPTH.md +0 -9
  44. package/docs/helpers/constants/variables/MS_PER_MIN.md +0 -9
  45. package/docs/helpers/constants/variables/MS_PER_SEC.md +0 -9
  46. package/docs/helpers/constants/variables/default.md +0 -103
  47. package/docs/helpers/jsdoc-types/README.md +0 -33
  48. package/docs/helpers/jsdoc-types/interfaces/BufferDecoder.md +0 -23
  49. package/docs/helpers/jsdoc-types/interfaces/BufferEncoder.md +0 -23
  50. package/docs/helpers/jsdoc-types/interfaces/CacheNode.md +0 -43
  51. package/docs/helpers/jsdoc-types/interfaces/CommonPoolOptions.md +0 -31
  52. package/docs/helpers/jsdoc-types/interfaces/PendingResponseEntry.md +0 -51
  53. package/docs/helpers/jsdoc-types/interfaces/PostMessageOptions.md +0 -39
  54. package/docs/helpers/jsdoc-types/interfaces/PowerBatchOptions.md +0 -13
  55. package/docs/helpers/jsdoc-types/interfaces/PowerCacheOptions.md +0 -115
  56. package/docs/helpers/jsdoc-types/interfaces/PowerChunkingOptions.md +0 -31
  57. package/docs/helpers/jsdoc-types/interfaces/PowerCircuitOptions.md +0 -45
  58. package/docs/helpers/jsdoc-types/interfaces/PowerDeadlineOptions.md +0 -101
  59. package/docs/helpers/jsdoc-types/interfaces/PowerDeferOptions.md +0 -13
  60. package/docs/helpers/jsdoc-types/interfaces/PowerEventBusOptions.md +0 -19
  61. package/docs/helpers/jsdoc-types/interfaces/PowerLatchOptions.md +0 -23
  62. package/docs/helpers/jsdoc-types/interfaces/PowerLoggerOptions.md +0 -51
  63. package/docs/helpers/jsdoc-types/interfaces/PowerObserverOptions.md +0 -25
  64. package/docs/helpers/jsdoc-types/interfaces/PowerPoolOptions.md +0 -85
  65. package/docs/helpers/jsdoc-types/interfaces/PowerQueueOptions.md +0 -13
  66. package/docs/helpers/jsdoc-types/interfaces/PowerRetryOptions.md +0 -83
  67. package/docs/helpers/jsdoc-types/interfaces/PowerSlidingWindowOptions.md +0 -19
  68. package/docs/helpers/jsdoc-types/interfaces/PowerTTLMapOptions.md +0 -27
  69. package/docs/helpers/jsdoc-types/interfaces/PowerThrottleOptions.md +0 -31
  70. package/docs/helpers/jsdoc-types/interfaces/WorkerObj.md +0 -55
  71. package/docs/helpers/powerBackpressure/README.md +0 -17
  72. package/docs/helpers/powerBackpressure/classes/PowerBackpressure.md +0 -368
  73. package/docs/helpers/powerBatch/README.md +0 -17
  74. package/docs/helpers/powerBatch/classes/PowerBatch.md +0 -139
  75. package/docs/helpers/powerBuffer/README.md +0 -26
  76. package/docs/helpers/powerBuffer/functions/b2o.md +0 -25
  77. package/docs/helpers/powerBuffer/functions/o2b.md +0 -23
  78. package/docs/helpers/powerBuffer/functions/o2u8.md +0 -33
  79. package/docs/helpers/powerBuffer/functions/u82o.md +0 -30
  80. package/docs/helpers/powerBulkhead/README.md +0 -17
  81. package/docs/helpers/powerBulkhead/classes/PowerBulkhead.md +0 -302
  82. package/docs/helpers/powerCache/README.md +0 -29
  83. package/docs/helpers/powerCache/classes/PowerCache.md +0 -933
  84. package/docs/helpers/powerCache/classes/PowerMemoizer.md +0 -244
  85. package/docs/helpers/powerCache/classes/PowerTimedCache.md +0 -302
  86. package/docs/helpers/powerCache/functions/simpleArgsKey.md +0 -31
  87. package/docs/helpers/powerChunking/README.md +0 -17
  88. package/docs/helpers/powerChunking/classes/PowerChunker.md +0 -78
  89. package/docs/helpers/powerCircuit/README.md +0 -23
  90. package/docs/helpers/powerCircuit/classes/PowerCircuit.md +0 -167
  91. package/docs/helpers/powerDeadline/README.md +0 -23
  92. package/docs/helpers/powerDeadline/classes/PowerDeadline.md +0 -88
  93. package/docs/helpers/powerDefer/README.md +0 -17
  94. package/docs/helpers/powerDefer/classes/PowerDefer.md +0 -134
  95. package/docs/helpers/powerEventBus/README.md +0 -23
  96. package/docs/helpers/powerEventBus/classes/PowerEventBus.md +0 -330
  97. package/docs/helpers/powerHistogram/README.md +0 -17
  98. package/docs/helpers/powerHistogram/classes/PowerHistogram.md +0 -285
  99. package/docs/helpers/powerLatch/README.md +0 -17
  100. package/docs/helpers/powerLatch/classes/PowerLatch.md +0 -264
  101. package/docs/helpers/powerLogger/README.md +0 -17
  102. package/docs/helpers/powerLogger/classes/PowerLogger.md +0 -290
  103. package/docs/helpers/powerObserver/README.md +0 -23
  104. package/docs/helpers/powerObserver/classes/PowerObserver.md +0 -213
  105. package/docs/helpers/powerPermitGate/README.md +0 -11
  106. package/docs/helpers/powerPermitGate/classes/PowerPermitGate.md +0 -248
  107. package/docs/helpers/powerPool/README.md +0 -36
  108. package/docs/helpers/powerPool/classes/PowerPool.md +0 -973
  109. package/docs/helpers/powerPool/classes/PowerPoolShutdownError.md +0 -67
  110. package/docs/helpers/powerQueue/README.md +0 -11
  111. package/docs/helpers/powerQueue/classes/PowerQueue.md +0 -302
  112. package/docs/helpers/powerRateLimit/README.md +0 -17
  113. package/docs/helpers/powerRateLimit/classes/PowerRateLimit.md +0 -187
  114. package/docs/helpers/powerRetry/README.md +0 -23
  115. package/docs/helpers/powerRetry/classes/PowerRetry.md +0 -106
  116. package/docs/helpers/powerScheduler/README.md +0 -11
  117. package/docs/helpers/powerScheduler/classes/PowerScheduler.md +0 -135
  118. package/docs/helpers/powerSemaphore/README.md +0 -17
  119. package/docs/helpers/powerSemaphore/classes/PowerSemaphore.md +0 -173
  120. package/docs/helpers/powerSlidingWindow/README.md +0 -11
  121. package/docs/helpers/powerSlidingWindow/classes/PowerSlidingWindow.md +0 -83
  122. package/docs/helpers/powerSubscriberSet/README.md +0 -15
  123. package/docs/helpers/powerSubscriberSet/classes/PowerSubscriberSet.md +0 -251
  124. package/docs/helpers/powerSubscriberSet/functions/cleanupWeakRefs.md +0 -21
  125. package/docs/helpers/powerTTLMap/README.md +0 -17
  126. package/docs/helpers/powerTTLMap/classes/PowerTTLMap.md +0 -326
  127. package/docs/helpers/powerThrottle/README.md +0 -17
  128. package/docs/helpers/powerThrottle/classes/PowerThrottle.md +0 -216
  129. package/docs/index/README.md +0 -205
  130. package/docs/utils/errors/README.md +0 -12
  131. package/docs/utils/errors/functions/formatErrorObj.md +0 -30
  132. package/docs/utils/errors/functions/normalizeError.md +0 -50
  133. package/docs/utils/now/README.md +0 -19
  134. package/docs/utils/now/functions/measureAsync.md +0 -37
  135. package/docs/utils/now/functions/measureSync.md +0 -54
  136. package/docs/utils/now/functions/nowMs.md +0 -24
  137. package/guides/autoscale.md +0 -80
  138. package/guides/errors.md +0 -41
  139. package/guides/metaGuide.md +0 -440
  140. package/guides/now.md +0 -56
  141. package/guides/powerBackpressure.md +0 -110
  142. package/guides/powerBatch.md +0 -82
  143. package/guides/powerBuffer.md +0 -86
  144. package/guides/powerBulkhead.md +0 -61
  145. package/guides/powerCache.md +0 -269
  146. package/guides/powerChunking.md +0 -130
  147. package/guides/powerCircuit.md +0 -84
  148. package/guides/powerDeadline.md +0 -99
  149. package/guides/powerDefer.md +0 -56
  150. package/guides/powerEventBus.md +0 -89
  151. package/guides/powerHistogram.md +0 -71
  152. package/guides/powerLatch.md +0 -94
  153. package/guides/powerLogger.md +0 -129
  154. package/guides/powerObserver.md +0 -65
  155. package/guides/powerPermitGate.md +0 -52
  156. package/guides/powerPool.md +0 -321
  157. package/guides/powerQueue.md +0 -112
  158. package/guides/powerRateLimit.md +0 -37
  159. package/guides/powerRetry.md +0 -54
  160. package/guides/powerScheduler.md +0 -41
  161. package/guides/powerSemaphore.md +0 -65
  162. package/guides/powerSlidingWindow.md +0 -63
  163. package/guides/powerSubscriberSet.md +0 -48
  164. package/guides/powerTTLMap.md +0 -58
  165. package/guides/powerThrottle.md +0 -152
  166. package/index.html +0 -57
  167. package/results.json +0 -6692
  168. package/scripts/find-missing-jsdoc.js +0 -62
  169. package/scripts/modernize-optional-chaining.cjs +0 -36
  170. package/scripts/pool-debug.mjs +0 -29
  171. package/scripts/repro_powercache.js +0 -14
  172. package/scripts/static-audit-exports.cjs +0 -93
  173. package/scripts/static-audit-exports.json +0 -518
  174. package/test/powerBackpressure.test.js +0 -114
  175. package/test/powerBatch.branches.extra.test.js +0 -122
  176. package/test/powerBatch.test.js +0 -79
  177. package/test/powerBuffer.test.js +0 -125
  178. package/test/powerBulkhead.test.js +0 -210
  179. package/test/powerCache.branches.test.js +0 -233
  180. package/test/powerCache.bulk.test.js +0 -31
  181. package/test/powerCache.getorset.test.js +0 -110
  182. package/test/powerCache.hitRate.test.js +0 -35
  183. package/test/powerCache.inflight.test.js +0 -24
  184. package/test/powerCache.iterator.test.js +0 -18
  185. package/test/powerCache.misses.test.js +0 -52
  186. package/test/powerCache.more.test.js +0 -118
  187. package/test/powerCache.test.js +0 -37
  188. package/test/powerCache.timeout.test.js +0 -25
  189. package/test/powerCache.touch.test.js +0 -46
  190. package/test/powerChunking.branches.extra.test.js +0 -155
  191. package/test/powerChunking.errors.test.js +0 -177
  192. package/test/powerChunking.test.js +0 -39
  193. package/test/powerCircuit.observability.test.js +0 -71
  194. package/test/powerCircuit.test.js +0 -74
  195. package/test/powerDeadline.test.js +0 -140
  196. package/test/powerDefer.test.js +0 -55
  197. package/test/powerErrors.test.js +0 -32
  198. package/test/powerEventBus.branches.extra.test.js +0 -70
  199. package/test/powerEventBus.extra.test.js +0 -72
  200. package/test/powerEventBus.max.test.js +0 -43
  201. package/test/powerEventBus.more.test.js +0 -121
  202. package/test/powerEventBus.once_off.test.js +0 -17
  203. package/test/powerEventBus.test.js +0 -74
  204. package/test/powerEventBus.uncovered.test.js +0 -57
  205. package/test/powerEventBus.weak.test.js +0 -18
  206. package/test/powerHistogram.test.js +0 -73
  207. package/test/powerLatch.branches.extra.test.js +0 -115
  208. package/test/powerLatch.test.js +0 -57
  209. package/test/powerLogger.branches.test.js +0 -98
  210. package/test/powerLogger.formatter.name.test.js +0 -58
  211. package/test/powerLogger.json.test.js +0 -88
  212. package/test/powerLogger.output.test.js +0 -81
  213. package/test/powerLogger.table.debug.test.js +0 -77
  214. package/test/powerLogger.test.js +0 -59
  215. package/test/powerMemoizer.memoize.test.js +0 -100
  216. package/test/powerMemoizer.test.js +0 -85
  217. package/test/powerObserver.test.js +0 -129
  218. package/test/powerPermitGate.test.js +0 -66
  219. package/test/powerPool.autoTransfer.test.js +0 -100
  220. package/test/powerPool.autoscale.extra.test.js +0 -88
  221. package/test/powerPool.autoscale.test.js +0 -136
  222. package/test/powerPool.awaitDefaultTimeout.test.js +0 -52
  223. package/test/powerPool.awaitTimeout.test.js +0 -22
  224. package/test/powerPool.batch.test.js +0 -170
  225. package/test/powerPool.branches.extra2.test.js +0 -42
  226. package/test/powerPool.branches.test.js +0 -102
  227. package/test/powerPool.browser.messageerror.test.js +0 -45
  228. package/test/powerPool.correlation.test.js +0 -26
  229. package/test/powerPool.correlationId.test.js +0 -63
  230. package/test/powerPool.dispose.test.js +0 -49
  231. package/test/powerPool.drain.test.js +0 -57
  232. package/test/powerPool.events.test.js +0 -131
  233. package/test/powerPool.more.extra.test.js +0 -99
  234. package/test/powerPool.more.test.js +0 -283
  235. package/test/powerPool.node.messageerror.test.js +0 -46
  236. package/test/powerPool.postMessage.promise.test.js +0 -83
  237. package/test/powerPool.queueHigh.test.js +0 -55
  238. package/test/powerPool.queueSaturation.test.js +0 -51
  239. package/test/powerPool.rapidResize.test.js +0 -55
  240. package/test/powerPool.resize.overload.test.js +0 -65
  241. package/test/powerPool.resize.test.js +0 -70
  242. package/test/powerPool.shutdown.test.js +0 -38
  243. package/test/powerPool.stats.test.js +0 -40
  244. package/test/powerPool.stopThePress.test.js +0 -94
  245. package/test/powerPool.terminateShutdown.test.js +0 -22
  246. package/test/powerPool.test.js +0 -525
  247. package/test/powerPool.timers.test.js +0 -55
  248. package/test/powerPool.uncovered.test.js +0 -407
  249. package/test/powerPool.workerId.test.js +0 -47
  250. package/test/powerQueue.iterators.test.js +0 -67
  251. package/test/powerQueue.saturation.test.js +0 -18
  252. package/test/powerQueue.test.js +0 -48
  253. package/test/powerQueue.unshiftMany.test.js +0 -49
  254. package/test/powerRateLimit.atomic.test.js +0 -80
  255. package/test/powerRateLimit.extra.test.js +0 -145
  256. package/test/powerRateLimit.functions.test.js +0 -106
  257. package/test/powerRateLimit.test.js +0 -38
  258. package/test/powerRetry.attemptTimeout.test.js +0 -51
  259. package/test/powerRetry.test.js +0 -121
  260. package/test/powerScheduler.test.js +0 -126
  261. package/test/powerSemaphore.test.js +0 -108
  262. package/test/powerSlidingWindow.pool.test.js +0 -55
  263. package/test/powerSlidingWindow.test.js +0 -25
  264. package/test/powerSubscriberSet.test.js +0 -125
  265. package/test/powerTTLMap.test.js +0 -125
  266. package/test/powerThrottle.pool.test.js +0 -54
  267. package/test/powerThrottle.refill.test.js +0 -22
  268. package/test/powerThrottle.reserve.test.js +0 -46
  269. package/test/powerThrottle.test.js +0 -45
  270. package/test/powerTimedCache.test.js +0 -73
  271. package/test/umd.bundle.branches.test.js +0 -100
  272. package/test/umd.bundle.cache-timers.test.js +0 -48
  273. package/test/umd.bundle.exhaustive.test.js +0 -158
  274. package/test/umd.bundle.fuzz.test.js +0 -86
  275. package/test/umd.bundle.hasEqual.more.test.js +0 -68
  276. package/test/umd.bundle.hasEqual.test.js +0 -104
  277. package/test/umd.bundle.logger-extra.test.js +0 -48
  278. package/test/umd.bundle.more-coverage-2.test.js +0 -67
  279. package/test/umd.bundle.pool.test.js +0 -134
  280. package/test/umd.bundle.test.js +0 -265
  281. package/test/utils.measure.test.js +0 -49
  282. package/test/utils.now.extra.test.js +0 -30
  283. package/test/utils.now.more.test.js +0 -57
  284. package/tsconfig.json +0 -16
  285. package/typedoc.json +0 -25
  286. package/vite.config.js +0 -31
  287. 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
- });
@@ -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
- });