dynamic-throttled-queue 2.2.0-rc.e9be515 → 2.2.1-rc.b3d1777

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 CHANGED
@@ -26,7 +26,7 @@ throttle(() => {
26
26
  });
27
27
  ```
28
28
 
29
- Callbacks can return `false` to signal a failure (used for dynamic rate adjustment and retry). Async callbacks (returning a Promise) are also supported — rejections and `false` resolutions count as failures. By default, every failure reduces the adaptive rate; use `rateOutcomeClassifier` when only selected failures should do so.
29
+ Callbacks can return `false` to signal a failure (used for dynamic rate adjustment and retry). Async callbacks (returning a Promise) are also supported — rejections and `false` resolutions count as failures. By default, every failure reduces the adaptive rate; use `rateOutcomeClassifier` when only selected failures should do so. Use `retryClassifier` to separately decide whether a failure is eligible for retry.
30
30
 
31
31
  Each callback receives an execution context containing the queue-owned `AbortSignal`. Existing zero-argument callbacks remain supported. Use the signal to cooperatively cancel in-flight work:
32
32
 
@@ -39,6 +39,8 @@ throttle(async ({ signal }) => {
39
39
 
40
40
  Set `concurrency` to bound callbacks that are still awaiting asynchronous completion. This limit is independent of the request-start rate; omitting it preserves the existing unlimited in-flight behavior.
41
41
 
42
+ Set `maxQueueSize` to bound accepted work. Capacity is reserved from enqueue through terminal success or failure, including pending callbacks, active callbacks, and retries. A full queue makes `enqueue()` throw synchronously in v2; unlimited capacity remains the default. In v3, a full queue will return `false` instead.
43
+
42
44
  ## Options
43
45
 
44
46
  | Param | Type | Default | Description |
@@ -50,14 +52,19 @@ Set `concurrency` to bound callbacks that are still awaiting asynchronous comple
50
52
  | `errors_per_interval` | `number` | `5` | Positive integer error threshold per interval before adjusting rate |
51
53
  | `back_off` | `boolean` | `false` | Back off for 1 full interval when error threshold is hit |
52
54
  | `retry` | `number` | `0` | Non-negative integer number of times to retry failed callbacks |
55
+ | `retryBackoff` | `RetryBackoff` | — | Per-retry fixed, linear, or exponential delay policy; omit for immediate retries |
53
56
  | `concurrency` | `number` | — | Maximum callbacks awaiting asynchronous completion; omit for no limit |
57
+ | `maxQueueSize` | `number` | — | Maximum accepted callbacks not yet terminal, including pending, active, and retried work; omit for no limit |
54
58
  | `compact_threshold` | `number` | `512` | Non-negative integer minimum dead slots before internal queue compaction triggers; `0` compacts at the earliest eligible point |
55
59
  | `rateStrategy` | `RateStrategy` | `linear` | Pure policy that requests the next rate and an optional backoff after each observation window |
56
60
  | `rateOutcomeClassifier` | `RateOutcomeClassifier` | — | Decides whether a failed callback outcome contributes to adaptive-rate error counting |
57
61
  | `adjustmentTiming` | `"interval" \| "settled"` | `"interval"` | Defines whether rate decisions use outcomes settled each interval or complete started-attempt sets |
62
+ | `retryClassifier` | `RetryClassifier` | — | Decides whether a failed callback outcome is eligible for another attempt |
58
63
  | `onRateChange` | `(rate: number) => void` | — | Called when the current rate changes |
59
64
 
60
- `retry`, `errors_per_interval`, and `compact_threshold` reject fractional and non-finite values. `errors_per_interval` must be at least `1`; `retry` and `compact_threshold` may be `0`.
65
+ `retry`, `errors_per_interval`, `compact_threshold`, and `maxQueueSize` reject fractional and non-finite values. `errors_per_interval` must be at least `1`; `retry` and `compact_threshold` may be `0`. `retryBackoff.baseDelay` and optional `maxDelay` are finite non-negative millisecond values (fractional values are accepted); optional `jitter` is finite from `0` through `1`.
66
+
67
+ `retryBackoff` is `{ strategy: "fixed" | "linear" | "exponential"; baseDelay: number; maxDelay?: number; jitter?: number; random?: () => number }`. The first retry has index `1`: fixed uses `baseDelay`, linear uses `baseDelay × retryIndex`, and exponential uses `baseDelay × 2^(retryIndex - 1)`. The calculated delay is capped at `maxDelay`, when supplied, then optional symmetric percentage jitter is applied and capped again. `random` makes jitter deterministic for tests; a thrown, non-finite, or out-of-range result safely falls back to no jitter. Retry backoff begins when the failed attempt settles and is independent of adaptive-rate `back_off`.
61
68
 
62
69
  ### Adaptive-rate timing
63
70
 
@@ -75,7 +82,9 @@ With `adjustmentTiming: "settled"`, an observation window contains every callbac
75
82
  | `resume()` | `() => void` | Resume a paused queue with a fresh pacing and observation window |
76
83
  | `stop()` | `() => void` | Stop processing the queue immediately |
77
84
  | `abort()` | `() => void` | Terminally discard queued work and signal active callbacks |
78
- | `pending` | `number` (readonly) | Number of callbacks still waiting in the queue |
85
+ | `waitForIdle()` | `() => Promise<void>` | Resolves when all pending, active, and delayed-retry work has completed |
86
+ | `getState()` | `() => QueueState` | Returns a frozen point-in-time snapshot of queue state and counters |
87
+ | `pending` | `number` (readonly) | Number of callbacks waiting in the queue, including delayed retries |
79
88
 
80
89
  ```ts
81
90
  const throttle = createThrottledQueue({ min_rpi: 5, interval: 1000 });
@@ -91,18 +100,22 @@ throttle.stop(); // halt processing
91
100
  | State | Pending work and enqueue | Active work | Scheduling and lifecycle operations |
92
101
  | ----- | ------------------------ | ----------- | ----------------------------------- |
93
102
  | Running | Pending work can start; new callbacks are accepted. | Continues normally. | `pause()` retains work and stops new starts. `stop()` retains work and clears timers. `abort()` is terminal. |
94
- | Paused | Pending work, newly enqueued callbacks, and retries are retained but do not start. | Continues and settles normally. | `resume()` restarts pacing at the current rate and begins a fresh adaptive-rate observation window. `pause()` is idempotent. `stop()` clears the paused state. |
95
- | Stopped | Pending work is retained. A later enqueue restarts scheduling. | Continues and settles normally. | `pause()` and `resume()` are no-ops. `stop()` is idempotent. |
103
+ | Paused | Pending work, newly enqueued callbacks, and retries are retained but do not start. | Continues and settles normally. | `resume()` restarts pacing at the current rate and begins a fresh adaptive-rate observation window. Delayed retries freeze their remaining delay and continue only after resume. `pause()` is idempotent. `stop()` clears the paused state. |
104
+ | Stopped | Pending work is retained. A later enqueue restarts scheduling. | Continues and settles normally. | Delayed retries freeze their remaining delay; the later enqueue resumes them. `pause()` and `resume()` are no-ops. `stop()` is idempotent. |
96
105
  | Aborted | Pending work is discarded and future enqueues throw. | Receives the shared abort signal and may finish cooperatively. | `pause()`, `resume()`, `stop()`, and `abort()` do not restart scheduling; `abort()` is idempotent. |
97
106
 
98
107
  While paused, callback outcomes do not contribute to adaptive-rate adjustment. A failed active callback may still create a configured retry, but that retry remains pending until `resume()`.
99
108
 
100
109
  In settled timing, `pause()` discards the in-progress observation window rather than making a partial or late rate decision. `stop()` retains its non-restarting behavior, and `abort()` remains terminal: neither produces post-stop or post-abort settled-window accounting.
101
110
 
102
- `stop()` clears scheduler timers and retains callbacks that have not started. It cannot cancel an active asynchronous callback; if that callback later succeeds, returns `false`, or rejects, its settlement does not restart scheduling. A retry created by a failed active callback is retained with the pending work. Enqueueing another callback resumes the queue.
111
+ `stop()` clears scheduler timers and retains callbacks that have not started. It cannot cancel an active asynchronous callback; if that callback later succeeds, returns `false`, or rejects, its settlement does not restart scheduling. A retry created by a failed active callback is retained with the pending work. Enqueueing another callback resumes the queue and any frozen delayed retries.
103
112
 
104
113
  `abort()` is terminal and idempotent. It clears scheduler timers, discards pending callbacks, and aborts the one shared signal supplied to active callbacks. Future enqueue attempts throw. Cancellation is cooperative: callbacks that ignore the signal can continue running, but their later success or failure does not retry work or affect adaptive-rate accounting.
105
114
 
115
+ `getState()` returns a frozen `QueueState` snapshot. Each call is independent; mutations to the returned object do not affect the queue. Fields: `rate` (current rate), `pending` (queued + delayed retries), `active` (callbacks executing), `state` (`"running"` | `"paused"` | `"stopped"` | `"aborted"`), and monotonic lifetime counters `started`, `succeeded`, `failed`, `retried`, `rateIncreases`, `rateDecreases`. `started`/`succeeded`/`failed` count callback attempts: a retry is a new attempt; a failure is counted even when a later retry succeeds. `retried` increments only when another attempt is actually scheduled. Rate-direction counters match applied rate changes and `onRateChange` notifications exactly. Counters do not change for settlements after `abort()`.
116
+
117
+ `waitForIdle()` returns a `Promise<void>` that resolves once all pending callbacks, active executions, and delayed retries have reached a terminal outcome. If the queue is already idle the promise resolves immediately. Each call is one-shot: a later enqueue does not affect a promise that has already resolved. Multiple simultaneous callers all resolve at the same idle transition without retaining waiter state. A callback failure that triggers a retry never exposes a transient idle transition between the failed attempt and the retry. `stop()` retains pending work, so existing waiters remain pending until that work completes after a later enqueue resumes the queue. `abort()` discards pending work but waiters remain pending until every active callback settles; post-abort settlements do not create new retry work. A paused queue resolves waiters only when both pending and active work are zero.
118
+
106
119
  ## Examples
107
120
 
108
121
  ### Basic
@@ -181,6 +194,23 @@ const throttle = createThrottledQueue({
181
194
 
182
195
  The normalized outcomes are `{ kind: "returned-false" }`, `{ kind: "thrown", error }`, and `{ kind: "rejected", error }`. Omitting the classifier preserves the default behavior: every failure reduces the adaptive rate. If the classifier throws, the original failure safely counts as rate-reducing and no separate classifier error is surfaced.
183
196
 
197
+ ### Retry classification
198
+
199
+ `retryClassifier` receives the same normalized failure outcome and a one-based attempt number, including the initial callback start. It must return literal `true` for the failure to be retried; any other value makes it permanent. The configured `retry` value remains the hard cap on additional attempts, so the classifier is not called after that budget is exhausted. If it throws, the queue preserves legacy behavior and retries subject to the remaining budget.
200
+
201
+ Retry eligibility is independent from adaptive-rate accounting. A failure can be retryable, rate-reducing, both, or neither:
202
+
203
+ ```ts
204
+ const throttle = createThrottledQueue({
205
+ min_rpi: 1,
206
+ interval: 1000,
207
+ retry: 2,
208
+ retryClassifier: (outcome, attempt) =>
209
+ outcome.kind === "rejected" && attempt < 3,
210
+ rateOutcomeClassifier: outcome => outcome.kind === "rejected",
211
+ });
212
+ ```
213
+
184
214
  ### Rate strategies
185
215
 
186
216
  The default `linear` strategy preserves the adaptive behavior above: it changes the rate by one request per interval. Use `aimd` when a capacity signal should reduce throughput more quickly while recovery remains gradual. AIMD increases by a fixed amount after a clean eligible observation window and reduces the rate by a multiplier when the error threshold is reached.
@@ -258,6 +288,24 @@ throttle(async () => {
258
288
  });
259
289
  ```
260
290
 
291
+ ### Retry backoff
292
+
293
+ ```ts
294
+ const throttle = createThrottledQueue({
295
+ min_rpi: 5,
296
+ interval: 1000,
297
+ retry: 3,
298
+ retryBackoff: {
299
+ strategy: "exponential",
300
+ baseDelay: 250,
301
+ maxDelay: 10_000,
302
+ jitter: 0.2,
303
+ },
304
+ });
305
+ ```
306
+
307
+ Delayed retries remain pending, return to the normal queue tail when due, and then obey normal scheduler pacing. Equal due times preserve the order their retry delays were scheduled. `abort()` discards delayed retries along with other pending work.
308
+
261
309
  ## Migration from v1
262
310
 
263
311
  - `errors_per_second` removed — use `errors_per_interval` (counts errors per full interval window, not per second).
@@ -0,0 +1,48 @@
1
+ import type { AdjustmentTiming, RateFailureOutcome, RateOutcomeClassifier, RateStrategy } from "./dynamic-throttled-queue.js";
2
+ /**
3
+ * Whether callbacks may start. `open` allows paced starts, `held` blocks starts until the module
4
+ * reopens them, and `idle` means the module is not observing and waits for `start()`.
5
+ */
6
+ export type Pacing = "idle" | "open" | "held";
7
+ /** Reports how one started callback settled: `undefined` for success, otherwise the failure. */
8
+ export type SettlementReporter = (outcome: RateFailureOutcome | undefined) => void;
9
+ export type AdaptiveRateOptions = {
10
+ min_rpi: number;
11
+ max_rpi: number;
12
+ interval: number;
13
+ errors_per_interval: number;
14
+ back_off: boolean;
15
+ adjustmentTiming: AdjustmentTiming;
16
+ rateStrategy: RateStrategy;
17
+ rateOutcomeClassifier?: RateOutcomeClassifier;
18
+ onRateChange?: (rate: number) => void;
19
+ };
20
+ export type AdaptiveRateHost = {
21
+ /** Whether accepted work is waiting to start. */
22
+ hasPendingWork: () => boolean;
23
+ /** Begins fresh pacing: the next paced start is one spacing from now. */
24
+ resumeStarts: () => void;
25
+ /** Cancels the next paced start, or reschedules it `deferBy` ms beyond one spacing from now. */
26
+ holdStarts: (deferBy?: number) => void;
27
+ /** Observation ended: cancel the next paced start. */
28
+ idle: () => void;
29
+ };
30
+ export type AdaptiveRate = {
31
+ readonly rate: number;
32
+ readonly rateIncreases: number;
33
+ readonly rateDecreases: number;
34
+ readonly pacing: Pacing;
35
+ /** Ends a pause, then begins observing if idle and work is pending. */
36
+ start: () => void;
37
+ /** Reports that every queued callback has started. */
38
+ drained: () => void;
39
+ /** Ends observation. Settled timing discards its in-progress window. */
40
+ stop: () => void;
41
+ /** Stops and discards the observation. Settlements are ignored until `start()` or `stop()`. */
42
+ pause: () => void;
43
+ /** Reports a callback start. Call the returned reporter once when that callback settles. */
44
+ started: () => SettlementReporter;
45
+ /** Throws the strategy failure that permanently halted adaptive rate, if one occurred. */
46
+ throwIfFailed: () => void;
47
+ };
48
+ export declare function createAdaptiveRate(options: AdaptiveRateOptions, host: AdaptiveRateHost): AdaptiveRate;
@@ -0,0 +1,237 @@
1
+ const ignoreSettlement = () => { };
2
+ function validateDecision(decision) {
3
+ if (typeof decision !== "object" || decision === null) {
4
+ throw new TypeError("rate strategy must return a decision object");
5
+ }
6
+ const candidate = decision;
7
+ if (!Number.isFinite(candidate.nextRate) || !Number.isInteger(candidate.nextRate)) {
8
+ throw new TypeError("rate strategy must return a finite integer nextRate");
9
+ }
10
+ if (typeof candidate.shouldBackOff !== "boolean") {
11
+ throw new TypeError("rate strategy must return a boolean shouldBackOff");
12
+ }
13
+ return candidate;
14
+ }
15
+ /** Decides every interval from the outcomes that settled during it, whenever those callbacks started. */
16
+ function intervalTiming(context) {
17
+ let tick;
18
+ let run = 0;
19
+ function adjust() {
20
+ tick = undefined;
21
+ const current = run;
22
+ const hold = context.decide();
23
+ if (current !== run)
24
+ return;
25
+ if (hold)
26
+ context.hold(context.interval);
27
+ else if (context.pacing === "held")
28
+ context.reopen();
29
+ tick = setTimeout(adjust, context.interval);
30
+ }
31
+ function stop() {
32
+ clearTimeout(tick);
33
+ tick = undefined;
34
+ run++;
35
+ context.idle();
36
+ }
37
+ return {
38
+ start() {
39
+ context.resume();
40
+ tick = setTimeout(adjust, context.interval);
41
+ },
42
+ started: () => context.record,
43
+ drained: stop,
44
+ stop,
45
+ };
46
+ }
47
+ /** Decides once every callback that started during one collection interval has settled. */
48
+ function settledTiming(context) {
49
+ let timer;
50
+ let window = 0;
51
+ let collecting = false;
52
+ let outstanding = 0;
53
+ function open() {
54
+ timer = undefined;
55
+ if (!context.hasPendingWork()) {
56
+ context.idle();
57
+ return;
58
+ }
59
+ window++;
60
+ collecting = true;
61
+ outstanding = 0;
62
+ context.resume();
63
+ timer = setTimeout(close, context.interval);
64
+ }
65
+ function close() {
66
+ timer = undefined;
67
+ collecting = false;
68
+ context.hold();
69
+ if (outstanding === 0)
70
+ finish();
71
+ }
72
+ function finish() {
73
+ const current = window;
74
+ const hold = context.decide();
75
+ if (current !== window)
76
+ return;
77
+ if (hold)
78
+ timer = setTimeout(endBackoff, context.interval);
79
+ else
80
+ open();
81
+ }
82
+ function endBackoff() {
83
+ timer = undefined;
84
+ context.endBackoff();
85
+ if (context.hasPendingWork())
86
+ open();
87
+ }
88
+ return {
89
+ start: open,
90
+ started() {
91
+ if (!collecting)
92
+ return ignoreSettlement;
93
+ const startedIn = window;
94
+ outstanding++;
95
+ return outcome => {
96
+ if (startedIn !== window)
97
+ return;
98
+ context.record(outcome);
99
+ outstanding--;
100
+ if (!collecting && outstanding === 0)
101
+ finish();
102
+ };
103
+ },
104
+ drained() { },
105
+ stop() {
106
+ clearTimeout(timer);
107
+ timer = undefined;
108
+ collecting = false;
109
+ window++;
110
+ context.idle();
111
+ },
112
+ };
113
+ }
114
+ export function createAdaptiveRate(options, host) {
115
+ const { min_rpi, max_rpi, errors_per_interval, back_off, rateStrategy, rateOutcomeClassifier, onRateChange } = options;
116
+ let rate = Math.ceil((max_rpi + min_rpi) / 2);
117
+ let rateIncreases = 0;
118
+ let rateDecreases = 0;
119
+ let errorCount = 0;
120
+ let wasBackedOff = false;
121
+ let ignoringSettlements = false;
122
+ let pacing = "idle";
123
+ let failure;
124
+ function isRateReducing(outcome) {
125
+ try {
126
+ return rateOutcomeClassifier?.(outcome) ?? true;
127
+ }
128
+ catch {
129
+ return true;
130
+ }
131
+ }
132
+ function applyRate(next) {
133
+ if (next === rate)
134
+ return;
135
+ if (next > rate)
136
+ rateIncreases++;
137
+ else
138
+ rateDecreases++;
139
+ rate = next;
140
+ onRateChange?.(rate);
141
+ }
142
+ function decide() {
143
+ const observation = Object.freeze({
144
+ currentRate: rate,
145
+ minRate: min_rpi,
146
+ maxRate: max_rpi,
147
+ errorCount,
148
+ errorThreshold: errors_per_interval,
149
+ hasPendingWork: host.hasPendingWork(),
150
+ wasBackedOff,
151
+ });
152
+ let decision;
153
+ try {
154
+ decision = validateDecision(rateStrategy(observation));
155
+ }
156
+ catch (error) {
157
+ failure = { error };
158
+ timing.stop();
159
+ throw error;
160
+ }
161
+ const hold = back_off && decision.shouldBackOff;
162
+ errorCount = 0;
163
+ wasBackedOff = hold;
164
+ applyRate(Math.min(max_rpi, Math.max(min_rpi, decision.nextRate)));
165
+ return hold;
166
+ }
167
+ const context = {
168
+ interval: options.interval,
169
+ get pacing() {
170
+ return pacing;
171
+ },
172
+ hasPendingWork: host.hasPendingWork,
173
+ record(outcome) {
174
+ if (!ignoringSettlements && outcome && isRateReducing(outcome))
175
+ errorCount++;
176
+ },
177
+ decide,
178
+ resume() {
179
+ pacing = "open";
180
+ host.resumeStarts();
181
+ },
182
+ hold(deferBy) {
183
+ pacing = "held";
184
+ host.holdStarts(deferBy);
185
+ },
186
+ reopen() {
187
+ pacing = "open";
188
+ },
189
+ endBackoff() {
190
+ wasBackedOff = false;
191
+ },
192
+ idle() {
193
+ wasBackedOff = false;
194
+ pacing = "idle";
195
+ host.idle();
196
+ },
197
+ };
198
+ const timing = options.adjustmentTiming === "settled" ? settledTiming(context) : intervalTiming(context);
199
+ return {
200
+ get rate() {
201
+ return rate;
202
+ },
203
+ get rateIncreases() {
204
+ return rateIncreases;
205
+ },
206
+ get rateDecreases() {
207
+ return rateDecreases;
208
+ },
209
+ get pacing() {
210
+ return pacing;
211
+ },
212
+ start() {
213
+ ignoringSettlements = false;
214
+ if (pacing !== "idle" || !host.hasPendingWork())
215
+ return;
216
+ timing.start();
217
+ },
218
+ drained() {
219
+ timing.drained();
220
+ },
221
+ stop() {
222
+ ignoringSettlements = false;
223
+ timing.stop();
224
+ },
225
+ pause() {
226
+ timing.stop();
227
+ errorCount = 0;
228
+ ignoringSettlements = true;
229
+ },
230
+ started: () => timing.started(),
231
+ throwIfFailed() {
232
+ if (failure)
233
+ throw failure.error;
234
+ },
235
+ };
236
+ }
237
+ //# sourceMappingURL=adaptive-rate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptive-rate.js","sourceRoot":"","sources":["../src/adaptive-rate.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,10 @@
1
+ export type RetryBackoff = {
2
+ strategy: "fixed" | "linear" | "exponential";
3
+ baseDelay: number;
4
+ maxDelay?: number;
5
+ jitter?: number;
6
+ random?: () => number;
7
+ };
1
8
  export type RateStrategyObservation = Readonly<{
2
9
  currentRate: number;
3
10
  minRate: number;
@@ -26,6 +33,7 @@ export type RateFailureOutcome = Readonly<{
26
33
  error: unknown;
27
34
  }>;
28
35
  export type RateOutcomeClassifier = (outcome: RateFailureOutcome) => boolean;
36
+ export type RetryClassifier = (outcome: RateFailureOutcome, attempt: number) => boolean;
29
37
  export type AdjustmentTiming = "interval" | "settled";
30
38
  export declare const linear: RateStrategy;
31
39
  export declare function aimd({ increaseBy, decreaseFactor }?: AimdOptions): RateStrategy;
@@ -44,24 +52,45 @@ export type ThrottleOptions = {
44
52
  back_off?: boolean;
45
53
  /** Non-negative integer retries for each failed callback. Default 0. */
46
54
  retry?: number;
55
+ /** Per-retry delay policy. Omit to preserve immediate retries. */
56
+ retryBackoff?: RetryBackoff;
47
57
  /** Maximum number of callbacks awaiting asynchronous settlement. Omit for no limit. */
48
58
  concurrency?: number;
59
+ /** Maximum accepted callbacks that have not reached a terminal outcome. Omit for no limit. */
60
+ maxQueueSize?: number;
49
61
  /** Non-negative integer dead slots before queue compaction triggers. Default 512. */
50
62
  compact_threshold?: number;
51
63
  /** Policy used to request the next rate and any backoff after each observation window. */
52
64
  rateStrategy?: RateStrategy;
53
65
  /** Decides whether a failed callback outcome contributes to adaptive-rate error counting. */
54
66
  rateOutcomeClassifier?: RateOutcomeClassifier;
67
+ /** Decides whether a failed callback outcome is eligible for another attempt. */
68
+ retryClassifier?: RetryClassifier;
55
69
  /** When adaptive-rate observations are adjusted. Defaults to interval compatibility behavior. */
56
70
  adjustmentTiming?: AdjustmentTiming;
57
71
  onRateChange?: (rate: number) => void;
58
72
  };
59
73
  export type ThrottleFn = (callback: ThrottleCallback) => void;
74
+ export type QueueLifecycleState = "running" | "paused" | "stopped" | "aborted";
75
+ export type QueueState = Readonly<{
76
+ rate: number;
77
+ pending: number;
78
+ active: number;
79
+ state: QueueLifecycleState;
80
+ started: number;
81
+ succeeded: number;
82
+ failed: number;
83
+ retried: number;
84
+ rateIncreases: number;
85
+ rateDecreases: number;
86
+ }>;
60
87
  export type ThrottleHandle = ThrottleFn & {
61
88
  pause: () => void;
62
89
  resume: () => void;
63
90
  stop: () => void;
64
91
  abort: () => void;
92
+ waitForIdle: () => Promise<void>;
93
+ getState: () => QueueState;
65
94
  readonly pending: number;
66
95
  };
67
96
  export declare function createThrottledQueue(options: ThrottleOptions): ThrottleHandle;
@@ -1,4 +1,3 @@
1
- import { createRateController } from "./rate-controller.js";
2
1
  import { createScheduler } from "./scheduler.js";
3
2
  const adjustmentTimings = new Set(["interval", "settled"]);
4
3
  export const linear = ({ minRate, maxRate, currentRate, errorCount, errorThreshold, hasPendingWork, wasBackedOff, }) => {
@@ -27,8 +26,21 @@ export function aimd({ increaseBy = 1, decreaseFactor = 0.5 } = {}) {
27
26
  return { nextRate: currentRate, shouldBackOff: false };
28
27
  };
29
28
  }
29
+ function validateRetryBackoff(retryBackoff) {
30
+ if (retryBackoff === undefined)
31
+ return;
32
+ if (!Number.isFinite(retryBackoff.baseDelay) || retryBackoff.baseDelay < 0) {
33
+ throw new Error("retryBackoff.baseDelay must be a finite non-negative number");
34
+ }
35
+ if (retryBackoff.maxDelay !== undefined && (!Number.isFinite(retryBackoff.maxDelay) || retryBackoff.maxDelay < 0)) {
36
+ throw new Error("retryBackoff.maxDelay must be a finite non-negative number");
37
+ }
38
+ if (retryBackoff.jitter !== undefined && (!Number.isFinite(retryBackoff.jitter) || retryBackoff.jitter < 0 || retryBackoff.jitter > 1)) {
39
+ throw new Error("retryBackoff.jitter must be a finite number from 0 through 1");
40
+ }
41
+ }
30
42
  export function createThrottledQueue(options) {
31
- const { min_rpi, interval, max_rpi = min_rpi, concurrency, retry = 0, compact_threshold = 512 } = options;
43
+ const { min_rpi, interval, max_rpi = min_rpi, concurrency, maxQueueSize, retry = 0, compact_threshold = 512 } = options;
32
44
  const errors_per_interval = options.errors_per_interval ?? 5;
33
45
  if (!Number.isInteger(min_rpi) || min_rpi < 1) {
34
46
  throw new Error("min_rpi must be a positive integer");
@@ -42,6 +54,9 @@ export function createThrottledQueue(options) {
42
54
  if (concurrency !== undefined && (!Number.isInteger(concurrency) || concurrency < 1)) {
43
55
  throw new Error("concurrency must be a positive integer");
44
56
  }
57
+ if (maxQueueSize !== undefined && (!Number.isSafeInteger(maxQueueSize) || maxQueueSize < 0)) {
58
+ throw new Error("maxQueueSize must be a non-negative safe integer");
59
+ }
45
60
  if (!Number.isInteger(errors_per_interval) || errors_per_interval < 1) {
46
61
  throw new Error("errors_per_interval must be a positive integer");
47
62
  }
@@ -54,10 +69,17 @@ export function createThrottledQueue(options) {
54
69
  if (options.adjustmentTiming !== undefined && !adjustmentTimings.has(options.adjustmentTiming)) {
55
70
  throw new Error("adjustmentTiming must be either interval or settled");
56
71
  }
57
- return createScheduler(options, createRateController({
72
+ validateRetryBackoff(options.retryBackoff);
73
+ return createScheduler(options, {
58
74
  min_rpi,
59
75
  max_rpi,
76
+ interval,
60
77
  errors_per_interval,
61
- }, options.rateStrategy ?? linear));
78
+ back_off: options.back_off ?? false,
79
+ adjustmentTiming: options.adjustmentTiming ?? "interval",
80
+ rateStrategy: options.rateStrategy ?? linear,
81
+ rateOutcomeClassifier: options.rateOutcomeClassifier,
82
+ onRateChange: options.onRateChange,
83
+ });
62
84
  }
63
85
  //# sourceMappingURL=dynamic-throttled-queue.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-throttled-queue.js","sourceRoot":"","sources":["../src/dynamic-throttled-queue.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dynamic-throttled-queue.js","sourceRoot":"","sources":["../src/dynamic-throttled-queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { RetryBackoff } from "./dynamic-throttled-queue.js";
2
+ export declare function calculateRetryDelay(policy: RetryBackoff, retryIndex: number): number;
@@ -0,0 +1,31 @@
1
+ function readRandom(random) {
2
+ try {
3
+ // eslint-disable-next-line sonarjs/pseudo-random -- Default jitter requires a random source.
4
+ const value = random?.() ?? Math.random();
5
+ return Number.isFinite(value) && value >= 0 && value <= 1 ? value : undefined;
6
+ }
7
+ catch {
8
+ return undefined;
9
+ }
10
+ }
11
+ export function calculateRetryDelay(policy, retryIndex) {
12
+ let delay;
13
+ switch (policy.strategy) {
14
+ case "linear":
15
+ delay = policy.baseDelay * retryIndex;
16
+ break;
17
+ case "exponential":
18
+ delay = policy.baseDelay * 2 ** (retryIndex - 1);
19
+ break;
20
+ default: delay = policy.baseDelay;
21
+ }
22
+ const cappedDelay = policy.maxDelay === undefined ? delay : Math.min(delay, policy.maxDelay);
23
+ if (policy.jitter === undefined)
24
+ return cappedDelay;
25
+ const random = readRandom(policy.random);
26
+ if (random === undefined)
27
+ return cappedDelay;
28
+ const jitteredDelay = cappedDelay * (1 + (random * 2 - 1) * policy.jitter);
29
+ return policy.maxDelay === undefined ? jitteredDelay : Math.min(jitteredDelay, policy.maxDelay);
30
+ }
31
+ //# sourceMappingURL=retry-backoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry-backoff.js","sourceRoot":"","sources":["../src/retry-backoff.ts"],"names":[],"mappings":"AAEA,SAAS,UAAU,CAAC,MAAkC;IACpD,IAAI,CAAC;QACH,6FAA6F;QAC7F,MAAM,KAAK,GAAG,MAAM,EAAE,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1C,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAChF,CAAC;IACD,MAAM,CAAC;QACL,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAoB,EAAE,UAAkB;IAC1E,IAAI,KAAa,CAAC;IAClB,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,QAAQ;YAAE,KAAK,GAAG,MAAM,CAAC,SAAS,GAAG,UAAU,CAAC;YAAC,MAAM;QAC5D,KAAK,aAAa;YAAE,KAAK,GAAG,MAAM,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;YAAC,MAAM;QAC5E,OAAO,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC;IACpC,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC7F,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC;IACpD,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC;IAC7C,MAAM,aAAa,GAAG,WAAW,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3E,OAAO,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;AAClG,CAAC"}
@@ -1,3 +1,3 @@
1
+ import type { AdaptiveRateOptions } from "./adaptive-rate.js";
1
2
  import type { ThrottleHandle, ThrottleOptions } from "./dynamic-throttled-queue.js";
2
- import type { RateController } from "./rate-controller.js";
3
- export declare function createScheduler(options: ThrottleOptions, rateController: RateController): ThrottleHandle;
3
+ export declare function createScheduler(options: ThrottleOptions, adaptiveRateOptions: AdaptiveRateOptions): ThrottleHandle;
package/dist/scheduler.js CHANGED
@@ -1,138 +1,194 @@
1
- export function createScheduler(options, rateController) {
2
- const { interval, evenly_spaced = true, retry = 0, concurrency, compact_threshold = 512, back_off = false, rateOutcomeClassifier, onRateChange, adjustmentTiming = "interval", } = options;
3
- const usesSettledTiming = adjustmentTiming === "settled";
4
- let current_rpi = rateController.rate;
5
- let dyn_interval = evenly_spaced ? interval / current_rpi : interval;
6
- let dyn_requests_per_interval = evenly_spaced ? 1 : current_rpi;
7
- let skippedLast = false;
8
- let isRunning = false;
1
+ import { createAdaptiveRate } from "./adaptive-rate.js";
2
+ import { calculateRetryDelay } from "./retry-backoff.js";
3
+ export function createScheduler(options, adaptiveRateOptions) {
4
+ const { interval, evenly_spaced = true, retry = 0, retryBackoff, concurrency, maxQueueSize, compact_threshold = 512, retryClassifier, } = options;
9
5
  let last_called = 0;
10
6
  let timeout;
11
- let dynTimeout;
12
7
  let active_count = 0;
13
8
  let isPaused = false;
14
9
  let isStopped = false;
15
10
  let isAborted = false;
16
- let hasStrategyFailure = false;
17
- let strategyFailure;
11
+ let cnt_started = 0;
12
+ let cnt_succeeded = 0;
13
+ let cnt_failed = 0;
14
+ let cnt_retried = 0;
18
15
  const abortController = new AbortController();
19
16
  const max_concurrency = concurrency ?? Infinity;
17
+ const max_queue_size = maxQueueSize ?? Infinity;
20
18
  const queue = [];
19
+ const delayedRetries = [];
21
20
  let head = 0;
22
- let observationWindow;
23
- let nextObservationWindow = 0;
24
- let collectingSettledWindow = false;
25
- let settledOutstanding = 0;
26
- function halt() {
27
- isRunning = false;
28
- skippedLast = false;
29
- clearTimeout(timeout);
30
- timeout = undefined;
31
- clearTimeout(dynTimeout);
32
- dynTimeout = undefined;
33
- if (head >= queue.length) {
34
- queue.length = 0;
35
- head = 0;
21
+ let reserved_count = 0;
22
+ const idleWaiters = [];
23
+ const adaptiveRate = createAdaptiveRate(adaptiveRateOptions, {
24
+ hasPendingWork: () => queue.length > head,
25
+ resumeStarts() {
26
+ last_called = Date.now();
27
+ clearTimeout(timeout);
28
+ timeout = setTimeout(dequeue, spacing());
29
+ },
30
+ holdStarts(deferBy) {
31
+ clearTimeout(timeout);
32
+ timeout = deferBy === undefined ? undefined : setTimeout(dequeue, spacing() + deferBy);
33
+ },
34
+ idle() {
35
+ clearTimeout(timeout);
36
+ timeout = undefined;
37
+ if (head >= queue.length) {
38
+ queue.length = 0;
39
+ head = 0;
40
+ }
41
+ },
42
+ });
43
+ function spacing() {
44
+ return evenly_spaced ? interval / adaptiveRate.rate : interval;
45
+ }
46
+ function isIdle() {
47
+ return active_count === 0 && queue.length <= head && delayedRetries.length === 0;
48
+ }
49
+ function notifyIdle() {
50
+ if (!isIdle())
51
+ return;
52
+ const waiters = idleWaiters.splice(0);
53
+ for (const resolve of waiters)
54
+ resolve();
55
+ }
56
+ function releaseDelayedRetry(delayedRetry) {
57
+ const index = delayedRetries.indexOf(delayedRetry);
58
+ if (index < 0)
59
+ return;
60
+ delayedRetries.splice(index, 1);
61
+ queue.push(delayedRetry.item);
62
+ start();
63
+ }
64
+ function startDelayedRetry(delayedRetry) {
65
+ delayedRetry.due = Date.now() + delayedRetry.remaining;
66
+ delayedRetry.timeout = setTimeout(() => {
67
+ releaseDelayedRetry(delayedRetry);
68
+ }, delayedRetry.remaining);
69
+ }
70
+ function freezeDelayedRetries() {
71
+ for (const delayedRetry of delayedRetries) {
72
+ if (delayedRetry.timeout === undefined)
73
+ continue;
74
+ if (delayedRetry.due === undefined)
75
+ continue;
76
+ clearTimeout(delayedRetry.timeout);
77
+ delayedRetry.timeout = undefined;
78
+ delayedRetry.remaining = Math.max(0, delayedRetry.due - Date.now());
79
+ }
80
+ }
81
+ function resumeDelayedRetries() {
82
+ for (const delayedRetry of delayedRetries) {
83
+ if (delayedRetry.timeout === undefined)
84
+ startDelayedRetry(delayedRetry);
36
85
  }
37
86
  }
38
- function discardSettledWindow() {
39
- observationWindow = undefined;
40
- collectingSettledWindow = false;
41
- settledOutstanding = 0;
87
+ function scheduleDelayedRetry(item, delay) {
88
+ const delayedRetry = { item, remaining: delay };
89
+ delayedRetries.push(delayedRetry);
90
+ if (!isPaused && !isStopped)
91
+ startDelayedRetry(delayedRetry);
42
92
  }
43
93
  function stop() {
44
94
  isStopped = true;
45
95
  isPaused = false;
46
- halt();
47
- discardSettledWindow();
96
+ freezeDelayedRetries();
97
+ adaptiveRate.stop();
48
98
  }
49
99
  function pause() {
50
100
  if (isAborted || isStopped || isPaused)
51
101
  return;
52
102
  isPaused = true;
53
- rateController.clearObservation();
54
- halt();
55
- discardSettledWindow();
103
+ freezeDelayedRetries();
104
+ adaptiveRate.pause();
56
105
  }
57
106
  function resume() {
58
107
  if (!isPaused)
59
108
  return;
60
109
  isPaused = false;
61
- if (queue.length > head)
62
- start();
110
+ resumeDelayedRetries();
111
+ start();
63
112
  }
64
113
  function abort() {
65
114
  if (isAborted)
66
115
  return;
67
116
  isAborted = true;
68
- halt();
69
- discardSettledWindow();
117
+ adaptiveRate.stop();
118
+ freezeDelayedRetries();
119
+ delayedRetries.length = 0;
70
120
  queue.length = 0;
71
121
  head = 0;
122
+ reserved_count = 0;
72
123
  abortController.abort();
73
124
  }
74
- function isRateReducing(outcome) {
75
- if (!outcome)
125
+ function isRetryable(item, outcome) {
126
+ if (!outcome || item.retries === 0)
76
127
  return false;
77
128
  try {
78
- return rateOutcomeClassifier?.(outcome) ?? true;
129
+ return retryClassifier ? retryClassifier(outcome, retry - item.retries + 1) === true : true;
79
130
  }
80
131
  catch {
81
132
  return true;
82
133
  }
83
134
  }
84
- function handleResult(item, outcome) {
135
+ function handleResult(item, outcome, reportSettlement) {
85
136
  if (isAborted)
86
137
  return;
87
- if (!isPaused && (!usesSettledTiming || item.observationWindow === observationWindow)) {
88
- rateController.recordCompletion(isRateReducing(outcome));
89
- }
90
- if (outcome && item.retries > 0) {
91
- queue.push({ fn: item.fn, retries: item.retries - 1 });
92
- if (!isRunning && !isPaused && !isStopped && queue.length > head)
138
+ if (outcome)
139
+ cnt_failed++;
140
+ else
141
+ cnt_succeeded++;
142
+ if (isRetryable(item, outcome)) {
143
+ cnt_retried++;
144
+ const retryItem = { fn: item.fn, retries: item.retries - 1 };
145
+ if (retryBackoff === undefined) {
146
+ queue.push(retryItem);
93
147
  start();
148
+ }
149
+ else {
150
+ const retryIndex = retry - item.retries + 1;
151
+ scheduleDelayedRetry(retryItem, calculateRetryDelay(retryBackoff, retryIndex));
152
+ }
94
153
  }
154
+ else
155
+ reserved_count--;
156
+ reportSettlement(outcome);
95
157
  }
96
- function handleSettlement(item, outcome, resume = false) {
158
+ function handleSettlement(item, outcome, reportSettlement, resume = false) {
97
159
  active_count--;
98
- handleResult(item, outcome);
99
- if (item.observationWindow === observationWindow) {
100
- settledOutstanding--;
101
- if (!collectingSettledWindow && settledOutstanding === 0)
102
- finishSettledWindow();
103
- }
104
- if (resume && isRunning && !skippedLast && queue.length > head && (!usesSettledTiming || collectingSettledWindow))
160
+ handleResult(item, outcome, reportSettlement);
161
+ if (resume && adaptiveRate.pacing === "open" && queue.length > head)
105
162
  dequeue();
163
+ notifyIdle();
106
164
  }
107
165
  function execute(item) {
108
- if (usesSettledTiming && collectingSettledWindow) {
109
- item.observationWindow = observationWindow;
110
- settledOutstanding++;
111
- }
166
+ const reportSettlement = adaptiveRate.started();
167
+ cnt_started++;
112
168
  active_count++;
113
169
  let result;
114
170
  try {
115
171
  result = item.fn({ signal: abortController.signal });
116
172
  }
117
173
  catch (error) {
118
- handleSettlement(item, { kind: "thrown", error });
174
+ handleSettlement(item, { kind: "thrown", error }, reportSettlement);
119
175
  return;
120
176
  }
121
177
  if (result instanceof Promise) {
122
- void result.then(value => handleSettlement(item, value === false ? { kind: "returned-false" } : undefined, true), (error) => handleSettlement(item, { kind: "rejected", error }, true));
178
+ void result.then(value => handleSettlement(item, value === false ? { kind: "returned-false" } : undefined, reportSettlement, true), (error) => handleSettlement(item, { kind: "rejected", error }, reportSettlement, true));
123
179
  return;
124
180
  }
125
- handleSettlement(item, result === false ? { kind: "returned-false" } : undefined);
181
+ handleSettlement(item, result === false ? { kind: "returned-false" } : undefined, reportSettlement);
126
182
  }
127
183
  function dequeue() {
128
- const threshold = last_called + dyn_interval;
184
+ const threshold = last_called + spacing();
129
185
  const now = Date.now();
130
186
  if (now < threshold) {
131
187
  clearTimeout(timeout);
132
188
  timeout = setTimeout(dequeue, threshold - now);
133
189
  return;
134
190
  }
135
- const end = Math.min(head + dyn_requests_per_interval, queue.length);
191
+ const end = Math.min(head + (evenly_spaced ? 1 : adaptiveRate.rate), queue.length);
136
192
  let started = 0;
137
193
  while (head < end && active_count < max_concurrency) {
138
194
  const item = queue[head++];
@@ -144,130 +200,58 @@ export function createScheduler(options, rateController) {
144
200
  queue.splice(0, head);
145
201
  head = 0;
146
202
  }
147
- if (head >= queue.length && !usesSettledTiming) {
148
- halt();
149
- return;
150
- }
151
- if (active_count >= max_concurrency)
152
- return;
153
- timeout = setTimeout(dequeue, dyn_interval);
154
- }
155
- function applyRate(newRpi) {
156
- if (newRpi === current_rpi)
157
- return;
158
- current_rpi = newRpi;
159
- onRateChange?.(current_rpi);
160
- if (evenly_spaced)
161
- dyn_interval = interval / current_rpi;
162
- else
163
- dyn_requests_per_interval = current_rpi;
164
- }
165
- function adjustRate() {
166
- dynTimeout = undefined;
167
- const wasSkipped = skippedLast;
168
- skippedLast = false;
169
- let decision;
170
- try {
171
- decision = rateController.observe({ hasPendingWork: queue.length > head, wasBackedOff: wasSkipped });
172
- }
173
- catch (error) {
174
- hasStrategyFailure = true;
175
- strategyFailure = error;
176
- halt();
177
- throw error;
178
- }
179
- applyRate(decision.rate);
180
- if (decision.shouldBackOff && back_off) {
181
- clearTimeout(timeout);
182
- skippedLast = true;
183
- timeout = setTimeout(dequeue, dyn_interval + interval);
184
- }
185
- if (isRunning)
186
- dynTimeout = setTimeout(adjustRate, interval);
187
- }
188
- function finishSettledWindow() {
189
- if (observationWindow === undefined || isPaused || isStopped || isAborted)
190
- return;
191
- const wasSkipped = skippedLast;
192
- skippedLast = false;
193
- let decision;
194
- try {
195
- decision = rateController.observe({ hasPendingWork: queue.length > head, wasBackedOff: wasSkipped });
196
- }
197
- catch (error) {
198
- hasStrategyFailure = true;
199
- strategyFailure = error;
200
- halt();
201
- discardSettledWindow();
202
- throw error;
203
- }
204
- observationWindow = undefined;
205
- applyRate(decision.rate);
206
- if (decision.shouldBackOff && back_off) {
207
- skippedLast = true;
208
- timeout = setTimeout(resumeSettledScheduling, interval);
209
- return;
210
- }
211
- if (queue.length > head)
212
- beginSettledWindow();
213
- else
214
- halt();
215
- }
216
- function closeSettledWindow() {
217
- dynTimeout = undefined;
218
- collectingSettledWindow = false;
219
- clearTimeout(timeout);
220
- timeout = undefined;
221
- if (settledOutstanding === 0)
222
- finishSettledWindow();
223
- }
224
- function resumeSettledScheduling() {
225
- skippedLast = false;
226
- beginSettledWindow();
227
- }
228
- function beginSettledWindow() {
229
- if (isAborted || isPaused || isStopped || skippedLast || queue.length <= head)
203
+ if (head >= queue.length)
204
+ adaptiveRate.drained();
205
+ if (adaptiveRate.pacing !== "open" || active_count >= max_concurrency)
230
206
  return;
231
- isRunning = true;
232
- collectingSettledWindow = true;
233
- observationWindow = nextObservationWindow++;
234
- last_called = Date.now();
235
- clearTimeout(timeout);
236
- timeout = setTimeout(dequeue, dyn_interval);
237
- clearTimeout(dynTimeout);
238
- dynTimeout = setTimeout(closeSettledWindow, interval);
207
+ timeout = setTimeout(dequeue, spacing());
239
208
  }
240
209
  function start() {
241
210
  if (isAborted || isPaused || isStopped)
242
211
  return;
243
- if (skippedLast)
244
- return;
245
- if (usesSettledTiming) {
246
- beginSettledWindow();
247
- return;
248
- }
249
- isRunning = true;
250
- last_called = Date.now();
251
- clearTimeout(timeout);
252
- timeout = setTimeout(dequeue, dyn_interval);
253
- if (!dynTimeout)
254
- dynTimeout = setTimeout(adjustRate, interval);
212
+ adaptiveRate.start();
255
213
  }
256
214
  function enqueue(callback) {
257
215
  if (isAborted)
258
216
  throw new Error("Cannot enqueue work after the queue has been aborted");
259
- if (hasStrategyFailure)
260
- throw strategyFailure;
217
+ adaptiveRate.throwIfFailed();
218
+ if (reserved_count >= max_queue_size)
219
+ throw new Error("Cannot enqueue work: maxQueueSize has been reached");
220
+ reserved_count++;
261
221
  queue.push({ fn: callback, retries: retry });
222
+ const wasStopped = isStopped;
262
223
  isStopped = false;
263
- if (!isRunning && !isPaused)
264
- start();
224
+ if (wasStopped)
225
+ resumeDelayedRetries();
226
+ start();
227
+ }
228
+ function getLifecycleState() {
229
+ if (isAborted)
230
+ return "aborted";
231
+ if (isStopped)
232
+ return "stopped";
233
+ if (isPaused)
234
+ return "paused";
235
+ return "running";
265
236
  }
266
237
  enqueue.pause = pause;
267
238
  enqueue.resume = resume;
268
239
  enqueue.stop = stop;
269
240
  enqueue.abort = abort;
270
- Object.defineProperty(enqueue, "pending", { get: () => queue.length - head });
241
+ enqueue.waitForIdle = async () => isIdle() ? Promise.resolve() : new Promise(resolve => { idleWaiters.push(resolve); });
242
+ enqueue.getState = () => Object.freeze({
243
+ rate: adaptiveRate.rate,
244
+ pending: queue.length - head + delayedRetries.length,
245
+ active: active_count,
246
+ state: getLifecycleState(),
247
+ started: cnt_started,
248
+ succeeded: cnt_succeeded,
249
+ failed: cnt_failed,
250
+ retried: cnt_retried,
251
+ rateIncreases: adaptiveRate.rateIncreases,
252
+ rateDecreases: adaptiveRate.rateDecreases,
253
+ });
254
+ Object.defineProperty(enqueue, "pending", { get: () => queue.length - head + delayedRetries.length });
271
255
  return enqueue;
272
256
  }
273
257
  //# sourceMappingURL=scheduler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dynamic-throttled-queue",
3
- "version": "2.2.0-rc.e9be515",
3
+ "version": "2.2.1-rc.b3d1777",
4
4
  "type": "module",
5
5
  "description": "Dynamically throttles arbitrary code to execute between a minimum and maximum number of times per interval. Best for making throttled API requests.",
6
6
  "files": [
@@ -1,22 +0,0 @@
1
- import type { RateStrategy } from "./dynamic-throttled-queue.js";
2
- type RateControllerOptions = {
3
- min_rpi: number;
4
- max_rpi: number;
5
- errors_per_interval: number;
6
- };
7
- type Observation = {
8
- hasPendingWork: boolean;
9
- wasBackedOff: boolean;
10
- };
11
- export type RateDecision = {
12
- rate: number;
13
- shouldBackOff: boolean;
14
- };
15
- export type RateController = {
16
- readonly rate: number;
17
- clearObservation: () => void;
18
- recordCompletion: (isRateReducing: boolean) => void;
19
- observe: (observation: Observation) => RateDecision;
20
- };
21
- export declare function createRateController(options: RateControllerOptions, strategy: RateStrategy): RateController;
22
- export {};
@@ -1,43 +0,0 @@
1
- function validateDecision(decision) {
2
- if (typeof decision !== "object" || decision === null) {
3
- throw new TypeError("rate strategy must return a decision object");
4
- }
5
- const candidate = decision;
6
- if (!Number.isFinite(candidate.nextRate) || !Number.isInteger(candidate.nextRate)) {
7
- throw new TypeError("rate strategy must return a finite integer nextRate");
8
- }
9
- if (typeof candidate.shouldBackOff !== "boolean") {
10
- throw new TypeError("rate strategy must return a boolean shouldBackOff");
11
- }
12
- return candidate;
13
- }
14
- export function createRateController(options, strategy) {
15
- let rate = Math.ceil((options.max_rpi + options.min_rpi) / 2);
16
- let errorCount = 0;
17
- return {
18
- get rate() {
19
- return rate;
20
- },
21
- clearObservation() {
22
- errorCount = 0;
23
- },
24
- recordCompletion(isRateReducing) {
25
- if (isRateReducing)
26
- errorCount++;
27
- },
28
- observe(observation) {
29
- const decision = validateDecision(strategy(Object.freeze({
30
- currentRate: rate,
31
- minRate: options.min_rpi,
32
- maxRate: options.max_rpi,
33
- errorCount,
34
- errorThreshold: options.errors_per_interval,
35
- ...observation,
36
- })));
37
- rate = Math.min(options.max_rpi, Math.max(options.min_rpi, decision.nextRate));
38
- errorCount = 0;
39
- return { rate, shouldBackOff: decision.shouldBackOff };
40
- },
41
- };
42
- }
43
- //# sourceMappingURL=rate-controller.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rate-controller.js","sourceRoot":"","sources":["../src/rate-controller.ts"],"names":[],"mappings":"AAyBA,SAAS,gBAAgB,CAAC,QAAiB;IACzC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtD,MAAM,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,SAAS,GAAG,QAAgC,CAAC;IACnD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClF,MAAM,IAAI,SAAS,CAAC,qDAAqD,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,OAAO,SAAS,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QACjD,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAA8B,EAAE,QAAsB;IACzF,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9D,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,OAAO;QACL,IAAI,IAAI;YACN,OAAO,IAAI,CAAC;QACd,CAAC;QACD,gBAAgB;YACd,UAAU,GAAG,CAAC,CAAC;QACjB,CAAC;QACD,gBAAgB,CAAC,cAAuB;YACtC,IAAI,cAAc;gBAAE,UAAU,EAAE,CAAC;QACnC,CAAC;QACD,OAAO,CAAC,WAAwB;YAC9B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;gBACvD,WAAW,EAAE,IAAI;gBACjB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,UAAU;gBACV,cAAc,EAAE,OAAO,CAAC,mBAAmB;gBAC3C,GAAG,WAAW;aACf,CAAC,CAAC,CAAC,CAAC;YACL,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC/E,UAAU,GAAG,CAAC,CAAC;YACf,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,CAAC,aAAa,EAAE,CAAC;QACzD,CAAC;KACF,CAAC;AACJ,CAAC"}