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,63 +0,0 @@
|
|
|
1
|
-
# PowerSlidingWindow
|
|
2
|
-
|
|
3
|
-
A sliding-window rate limiter that allows up to `capacity` events per `windowMs`.
|
|
4
|
-
|
|
5
|
-
## Constructor
|
|
6
|
-
|
|
7
|
-
| option | type | default | description |
|
|
8
|
-
|---|---:|---:|---|
|
|
9
|
-
| `capacity` | `number` | `1` | Maximum allowed events in a window.
|
|
10
|
-
| `windowMs` | `number` | `1000` | Window size in milliseconds.
|
|
11
|
-
|
|
12
|
-
## API
|
|
13
|
-
|
|
14
|
-
- `tryConsume(n = 1)` — Attempt to consume `n` slots (default `1`) in the current rolling window. Returns `true` when the requested slots are available and the call consumes them; otherwise returns `false`.
|
|
15
|
-
|
|
16
|
-
- `available()` — Return the current number of available slots in the window. This performs a prune of stale timestamps before reporting.
|
|
17
|
-
|
|
18
|
-
- `reset()` — Clear internal state and timestamp queue, effectively refilling the window.
|
|
19
|
-
|
|
20
|
-
## Example
|
|
21
|
-
|
|
22
|
-
```javascript
|
|
23
|
-
import { PowerSlidingWindow } from '../src/helpers/powerSlidingWindow.js';
|
|
24
|
-
import { PowerPool } from '../src/index.js';
|
|
25
|
-
|
|
26
|
-
const limiter = new PowerSlidingWindow({ capacity: 5, windowMs: 1000 });
|
|
27
|
-
if (limiter.tryConsume()) {
|
|
28
|
-
// allowed
|
|
29
|
-
} else {
|
|
30
|
-
// rate limited
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Example: cooperating with `PowerPool`
|
|
35
|
-
|
|
36
|
-
Use a `PowerSlidingWindow` to cap how many tasks you dispatch into a `PowerPool` within a rolling window. This example enqueues tasks and keeps a `pending` list for items that must wait until quota becomes available.
|
|
37
|
-
|
|
38
|
-
```javascript
|
|
39
|
-
const limiter = new PowerSlidingWindow({ capacity: 2, windowMs: 1000 });
|
|
40
|
-
const pool = new PowerPool(MyWorker, { size: 2 });
|
|
41
|
-
|
|
42
|
-
const pending = [];
|
|
43
|
-
function scheduleTask(payload) {
|
|
44
|
-
if (limiter.tryConsume()) {
|
|
45
|
-
pool.postMessage({ task: 'do', payload });
|
|
46
|
-
} else {
|
|
47
|
-
pending.push(payload);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
for (let i = 0; i < 10; i++) scheduleTask({ i });
|
|
52
|
-
|
|
53
|
-
// Periodically attempt to drain pending tasks when the window slides.
|
|
54
|
-
const interval = setInterval(() => {
|
|
55
|
-
while (pending.length && limiter.tryConsume()) {
|
|
56
|
-
pool.postMessage({ task: 'do', payload: pending.shift() });
|
|
57
|
-
}
|
|
58
|
-
if (!pending.length) clearInterval(interval);
|
|
59
|
-
}, 200);
|
|
60
|
-
|
|
61
|
-
await pool.drain();
|
|
62
|
-
pool.terminate();
|
|
63
|
-
```
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# PowerSubscriberSet
|
|
2
|
-
|
|
3
|
-
Shared subscriber registry used by `PowerEventBus` and `PowerObserver`.
|
|
4
|
-
|
|
5
|
-
`PowerSubscriberSet` manages listener bookkeeping with optional weak references, once-listeners, and max listener limits. It is useful when you need a reusable listener collection that can prune dead weak refs and keep listener delivery simple.
|
|
6
|
-
|
|
7
|
-
## Constructor
|
|
8
|
-
|
|
9
|
-
| option | type | default | description |
|
|
10
|
-
|---|---:|---|---|
|
|
11
|
-
| `weak` | `boolean` | `false` | Use `WeakRef`-backed entries when available to allow listeners to be garbage collected. |
|
|
12
|
-
| `maxListeners` | `number` | `0` | Maximum number of live listeners (0 means unlimited). |
|
|
13
|
-
|
|
14
|
-
## API
|
|
15
|
-
|
|
16
|
-
- `add(fn)` — Add a listener and return an unsubscribe callback.
|
|
17
|
-
- `addOnce(fn)` — Add a one-time listener that removes itself after invocation.
|
|
18
|
-
- `delete(fn)` — Remove a listener by the original function (or once-wrapper).
|
|
19
|
-
- `clear()` — Remove all listeners.
|
|
20
|
-
- `values()` — Return a safe array copy of currently live listeners.
|
|
21
|
-
- `[Symbol.iterator]()` — Iterate live listeners in insertion order.
|
|
22
|
-
|
|
23
|
-
## Example
|
|
24
|
-
|
|
25
|
-
```js
|
|
26
|
-
import { PowerSubscriberSet } from '../src/helpers/powerSubscriberSet.js';
|
|
27
|
-
|
|
28
|
-
const subs = new PowerSubscriberSet({ weak: true, maxListeners: 10 });
|
|
29
|
-
|
|
30
|
-
const listener = (value) => {
|
|
31
|
-
console.log('event value', value);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const unsubscribe = subs.add(listener);
|
|
35
|
-
subs.addOnce(() => console.log('called once'));
|
|
36
|
-
|
|
37
|
-
for (const fn of subs) {
|
|
38
|
-
fn('payload');
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
unsubscribe();
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## Notes
|
|
45
|
-
|
|
46
|
-
- When `weak: true` is enabled, stale weak references are cleaned up automatically during `values()` and iteration.
|
|
47
|
-
- `addOnce()` works with both strong and weak listeners, and removes the listener after it runs.
|
|
48
|
-
- `PowerSubscriberSet` is intended as a low-level building block for event and observer implementations rather than a general-purpose public utility.
|
package/guides/powerTTLMap.md
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# PowerTTLMap
|
|
2
|
-
|
|
3
|
-
A lightweight Map-like with per-key TTL (milliseconds). Keys expire lazily on access and iteration.
|
|
4
|
-
|
|
5
|
-
## Constructor
|
|
6
|
-
|
|
7
|
-
| Option | Type | Default | Description |
|
|
8
|
-
|---|---:|---:|---|
|
|
9
|
-
| `defaultTTL` | `number` (ms) | `0` | Default TTL applied when `set(key, value)` is called without a `ttl`. `0` disables expiry. |
|
|
10
|
-
| `onExpire` | `Function` | `undefined` | Optional callback called when an entry expires: `(key, value) => void`. Callback errors are swallowed. |
|
|
11
|
-
|
|
12
|
-
## API
|
|
13
|
-
|
|
14
|
-
- `set(key, value, ttl?)` — Set a value for `key`. Optionally provide `ttl` in milliseconds to override the map's `defaultTTL`. Returns the map instance to allow chaining.
|
|
15
|
-
|
|
16
|
-
- `get(key)` — Retrieve the value for `key` or `undefined` if it is missing or expired. Access will lazily purge expired entries.
|
|
17
|
-
|
|
18
|
-
- `has(key)` — Boolean indicating whether the key exists and is not expired.
|
|
19
|
-
|
|
20
|
-
- `delete(key)` — Remove an entry. Returns `true` if an entry was removed.
|
|
21
|
-
|
|
22
|
-
- `clear()` — Remove all entries immediately.
|
|
23
|
-
|
|
24
|
-
- `touch(key, ttl?)` — Refresh the TTL of an existing key; returns `true` when the TTL was updated.
|
|
25
|
-
|
|
26
|
-
- `size` (getter) — Number of non-expired entries; accessing this getter will purge expired entries lazily.
|
|
27
|
-
|
|
28
|
-
- Iteration helpers: `entries()`, `keys()`, `values()` — Iterators over non-expired entries/keys/values respectively. `forEach(cb, thisArg?)` iterates non-expired entries calling `cb(value, key, map)`. `[Symbol.iterator]()` is an alias for `entries()`.
|
|
29
|
-
|
|
30
|
-
## Example
|
|
31
|
-
|
|
32
|
-
```javascript
|
|
33
|
-
import { PowerTTLMap } from '../src/helpers/powerTTLMap.js';
|
|
34
|
-
|
|
35
|
-
// Example — manage expirable object URLs for served images
|
|
36
|
-
|
|
37
|
-
const urls = new PowerTTLMap(30_000); // default TTL 30s
|
|
38
|
-
|
|
39
|
-
// Store an object URL for a generated image and revoke it on expiry
|
|
40
|
-
function storePreview(id, objectUrl) {
|
|
41
|
-
urls.set(id, objectUrl);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
urls.set('img-1', URL.createObjectURL(blob));
|
|
45
|
-
|
|
46
|
-
// register onExpire to revoke underlying resources when entries age out
|
|
47
|
-
const m = new PowerTTLMap(30_000);
|
|
48
|
-
m.set('img-1', URL.createObjectURL(blob));
|
|
49
|
-
m.onExpire = (key, value) => {
|
|
50
|
-
try {
|
|
51
|
-
URL.revokeObjectURL(value);
|
|
52
|
-
} catch (e) {
|
|
53
|
-
/* ignore */
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
if (m.has('img-1')) console.log('preview ready');
|
|
58
|
-
```
|
package/guides/powerThrottle.md
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
# PowerThrottle
|
|
2
|
-
|
|
3
|
-
A small token-bucket rate limiter useful for pacing work (API calls, renders, or cooperating with `PowerPool`).
|
|
4
|
-
|
|
5
|
-
## Constructor
|
|
6
|
-
|
|
7
|
-
| option | type | default | description |
|
|
8
|
-
|---|---:|---:|---|
|
|
9
|
-
| `capacity` | `number` | `1` | Maximum tokens the bucket can hold.
|
|
10
|
-
| `tokens` | `number` | `capacity` | Initial token count (clamped to `capacity`).
|
|
11
|
-
| `refillRate` | `number` | `0` | Tokens added per second (fractional accumulation supported).
|
|
12
|
-
| `refillInterval` | `number` | `1000` | Internal bookkeeping interval (ms) used for refill math.
|
|
13
|
-
|
|
14
|
-
## API
|
|
15
|
-
|
|
16
|
-
- `tryConsume(n = 1)` — Attempt to consume `n` tokens (default `1`). Returns `true` when tokens were available and consumed; otherwise returns `false`.
|
|
17
|
-
|
|
18
|
-
- `available()` — Return the current number of available tokens (performs a refill calculation before reporting).
|
|
19
|
-
|
|
20
|
-
- `addTokens(n)` — Forcefully add up to `n` tokens to the bucket (clamped to `capacity`). Handy for tests or to manually replenish tokens.
|
|
21
|
-
|
|
22
|
-
- `reset(count?)` — Reset the token count to `count`. When omitted the bucket is refilled to full `capacity`.
|
|
23
|
-
|
|
24
|
-
- `reserve(n = 1)` — Reserve `n` tokens without committing them permanently. Returns a token object when successful (useful to later `release()` or `rollback()`), or `null` when reservation fails.
|
|
25
|
-
|
|
26
|
-
- `release(tokenOrN)` — Release a prior reservation token or numeric token count back into the bucket. Accepts either a token returned from `reserve()` or a numeric value.
|
|
27
|
-
|
|
28
|
-
- `rollback(nOrToken)` — Alias for `release()` for compatibility with undo patterns.
|
|
29
|
-
|
|
30
|
-
## Example
|
|
31
|
-
|
|
32
|
-
```javascript
|
|
33
|
-
import { PowerThrottle } from '../src/helpers/powerThrottle.js';
|
|
34
|
-
|
|
35
|
-
const limiter = new PowerThrottle({ capacity: 5, refillRate: 1 }); // burst 5, 1 token/sec
|
|
36
|
-
const pending = [];
|
|
37
|
-
|
|
38
|
-
async function sendEvent(payload) {
|
|
39
|
-
if (!limiter.tryConsume()) {
|
|
40
|
-
pending.push(payload);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
try {
|
|
45
|
-
await fetch('https://api.example.com/events', {
|
|
46
|
-
method: 'POST',
|
|
47
|
-
headers: { 'content-type': 'application/json' },
|
|
48
|
-
body: JSON.stringify(payload),
|
|
49
|
-
});
|
|
50
|
-
} catch (error) {
|
|
51
|
-
console.error('send failed', error);
|
|
52
|
-
pending.push(payload);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const drainInterval = setInterval(async () => {
|
|
57
|
-
while (pending.length && limiter.tryConsume()) {
|
|
58
|
-
const payload = pending.shift();
|
|
59
|
-
await sendEvent(payload);
|
|
60
|
-
}
|
|
61
|
-
if (!pending.length) {
|
|
62
|
-
clearInterval(drainInterval);
|
|
63
|
-
}
|
|
64
|
-
}, 250);
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### Example: cooperating with `PowerPool`
|
|
68
|
-
|
|
69
|
-
Use a `PowerThrottle` to pace messages enqueued to a `PowerPool` so the pool only processes at most N tasks per second. This is useful when downstream rate limits or external APIs require pacing.
|
|
70
|
-
|
|
71
|
-
```javascript
|
|
72
|
-
// limiter: 3 tokens/sec, burst capacity 3
|
|
73
|
-
const limiter = new PowerThrottle({ capacity: 3, refillRate: 3 });
|
|
74
|
-
const pool = new PowerPool(MyWorker, { size: 2 });
|
|
75
|
-
const pending = [];
|
|
76
|
-
|
|
77
|
-
function scheduleTask(payload) {
|
|
78
|
-
// tryConsume returns true when a token is available
|
|
79
|
-
if (!limiter.tryConsume()) {
|
|
80
|
-
// requeue for later processing
|
|
81
|
-
pending.push(payload);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
// dispatch to the pool; optionally target a worker
|
|
85
|
-
pool.postMessage({ task: 'do', payload });
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// enqueue tasks from some source
|
|
89
|
-
for (let i = 0; i < 10; i++) scheduleTask({ i });
|
|
90
|
-
|
|
91
|
-
// Periodically attempt to drain pending tasks when tokens become available.
|
|
92
|
-
const drainInterval = setInterval(() => {
|
|
93
|
-
while (pending.length && limiter.tryConsume()) {
|
|
94
|
-
const p = pending.shift();
|
|
95
|
-
pool.postMessage({ task: 'do', payload: p });
|
|
96
|
-
}
|
|
97
|
-
// stop when no pending tasks
|
|
98
|
-
if (!pending.length) clearInterval(drainInterval);
|
|
99
|
-
}, 200);
|
|
100
|
-
|
|
101
|
-
// drain when done
|
|
102
|
-
await pool.drain();
|
|
103
|
-
pool.terminate();
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### Reservation example
|
|
107
|
-
|
|
108
|
-
You can reserve tokens when you need to prepare work that should only consume a token once the work is actually dispatched. This is useful when coordinating with composed limiters that expect an atomic reservation step.
|
|
109
|
-
|
|
110
|
-
```javascript
|
|
111
|
-
const limiter = new PowerThrottle({ capacity: 2, tokens: 2, refillRate: 0 });
|
|
112
|
-
const token = limiter.reserve(1);
|
|
113
|
-
if (token) {
|
|
114
|
-
// do preparation work (serialize payload, open resources)
|
|
115
|
-
// when ready to dispatch:
|
|
116
|
-
// if something goes wrong before dispatch, release the reservation
|
|
117
|
-
limiter.release(token);
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
### Real-world: reserve before expensive serialization
|
|
122
|
-
|
|
123
|
-
Use `reserve()` when you want to claim capacity before performing expensive
|
|
124
|
-
preparation work (serialization, file reads). If preparation fails, release the
|
|
125
|
-
reservation so the token is not consumed.
|
|
126
|
-
|
|
127
|
-
```javascript
|
|
128
|
-
const limiter = new PowerThrottle({ capacity: 3, refillRate: 3 });
|
|
129
|
-
|
|
130
|
-
async function sendLargePayload(payload) {
|
|
131
|
-
const token = limiter.reserve(1);
|
|
132
|
-
if (!token) {
|
|
133
|
-
// no capacity: fallback (persist, retry later)
|
|
134
|
-
await persistForRetry(payload);
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
try {
|
|
139
|
-
// expensive synchronous or async serialization
|
|
140
|
-
const body = await heavySerialize(payload);
|
|
141
|
-
// dispatch network call (does not consume extra tokens)
|
|
142
|
-
await fetch('/api/upload', { method: 'POST', body });
|
|
143
|
-
return true;
|
|
144
|
-
} catch (err) {
|
|
145
|
-
// something went wrong during preparation or send
|
|
146
|
-
throw err;
|
|
147
|
-
} finally {
|
|
148
|
-
// always return the reserved token
|
|
149
|
-
limiter.release(token);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
```
|
package/index.html
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="utf-8">
|
|
6
|
-
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
7
|
-
<title>performance-helpers</title>
|
|
8
|
-
<meta name="description" content="Highly tuned lightweight toolbox for high-performance Node/browser code: zero-copy buffer helpers for worker messaging, an LRU TTL cache with a memoizer, a small worker pool wrapper, a tiny runtime debug logger, and much more.">
|
|
9
|
-
|
|
10
|
-
<meta property="og:title" content="performance-helpers">
|
|
11
|
-
<meta property="og:description" content="Highly tuned lightweight toolbox for high-performance Node/browser code: zero-copy buffer helpers for worker messaging, an LRU TTL cache with a memoizer, a small worker pool wrapper, a tiny runtime debug logger, and much more.">
|
|
12
|
-
<meta property="og:type" content="website">
|
|
13
|
-
<meta property="og:image" content="https://abelvm.github.io/nimbiCMS/assets/logo.png">
|
|
14
|
-
|
|
15
|
-
<meta name="twitter:card" content="summary_large_image">
|
|
16
|
-
<meta name="twitter:title" content="performance-helpers">
|
|
17
|
-
<meta name="twitter:description" content="Highly tuned lightweight toolbox for high-performance Node/browser code: zero-copy buffer helpers for worker messaging, an LRU TTL cache with a memoizer, a small worker pool wrapper, a tiny runtime debug logger, and much more.">
|
|
18
|
-
<meta name="twitter:image" content="https://abelvm.github.io/nimbiCMS/assets/logo.png">
|
|
19
|
-
|
|
20
|
-
<link rel="icon" href="./assets/logo.png">
|
|
21
|
-
<style>
|
|
22
|
-
html,
|
|
23
|
-
body,
|
|
24
|
-
#app {
|
|
25
|
-
height: 100vh;
|
|
26
|
-
max-height: 100vh;
|
|
27
|
-
margin: 0;
|
|
28
|
-
display: block;
|
|
29
|
-
}
|
|
30
|
-
</style>
|
|
31
|
-
<link rel="preload" href="https://unpkg.com/nimbi-cms@1.0.8/dist/nimbi-cms.css" as="style"
|
|
32
|
-
onload="this.rel='stylesheet'">
|
|
33
|
-
<noscript>
|
|
34
|
-
<link rel="stylesheet" href="https://unpkg.com/nimbi-cms@1.0.8/dist/nimbi-cms.css">
|
|
35
|
-
</noscript>
|
|
36
|
-
<script src="https://unpkg.com/nimbi-cms@1.0.8/dist/nimbi-cms.js"></script>
|
|
37
|
-
</head>
|
|
38
|
-
|
|
39
|
-
<body>
|
|
40
|
-
<div id="app"></div>
|
|
41
|
-
<script defer>
|
|
42
|
-
window.addEventListener('DOMContentLoaded', function () {
|
|
43
|
-
nimbiCMS.initCMS({
|
|
44
|
-
el: '#app',
|
|
45
|
-
contentPath: './',
|
|
46
|
-
indexDepth: 3,
|
|
47
|
-
defaultStyle: 'system',
|
|
48
|
-
homePage: 'README.md',
|
|
49
|
-
notFoundPage: 'assets/404.md',
|
|
50
|
-
navigationPage: 'assets/navigation.md',
|
|
51
|
-
debugLevel: 0,
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
</script>
|
|
55
|
-
</body>
|
|
56
|
-
|
|
57
|
-
</html>
|