dynamic-throttled-queue 2.2.0-rc.1849e68 → 2.2.0-rc.3d51b8f

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,10 +26,21 @@ throttle(() => {
26
26
  });
27
27
  ```
28
28
 
29
- Callbacks can return `false` to signal an error (used for dynamic rate adjustment and retry). Async callbacks (returning a Promise) are also supported — rejections and `false` resolutions count as errors.
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
+
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
+
33
+ ```ts
34
+ throttle(async ({ signal }) => {
35
+ const response = await fetch("/api/data", { signal });
36
+ if (!response.ok) return false;
37
+ });
38
+ ```
30
39
 
31
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.
32
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
+
33
44
  ## Options
34
45
 
35
46
  | Param | Type | Default | Description |
@@ -41,12 +52,25 @@ Set `concurrency` to bound callbacks that are still awaiting asynchronous comple
41
52
  | `errors_per_interval` | `number` | `5` | Positive integer error threshold per interval before adjusting rate |
42
53
  | `back_off` | `boolean` | `false` | Back off for 1 full interval when error threshold is hit |
43
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 |
44
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 |
45
58
  | `compact_threshold` | `number` | `512` | Non-negative integer minimum dead slots before internal queue compaction triggers; `0` compacts at the earliest eligible point |
46
59
  | `rateStrategy` | `RateStrategy` | `linear` | Pure policy that requests the next rate and an optional backoff after each observation window |
60
+ | `rateOutcomeClassifier` | `RateOutcomeClassifier` | — | Decides whether a failed callback outcome contributes to adaptive-rate error counting |
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 |
47
63
  | `onRateChange` | `(rate: number) => void` | — | Called when the current rate changes |
48
64
 
49
- `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`.
68
+
69
+ ### Adaptive-rate timing
70
+
71
+ `adjustmentTiming: "interval"` is the compatibility default: each configured interval observes the callback outcomes that have settled so far. A slow callback can therefore settle after its start interval and affect a later rate decision.
72
+
73
+ With `adjustmentTiming: "settled"`, an observation window contains every callback attempt that starts during one full configured interval. When collection closes, no further callbacks start until every attempt in that window settles; the queue then makes exactly one rate decision from the complete window. The next collection interval begins immediately after that decision, unless adaptive-rate `back_off` delays scheduling. Empty settled intervals do not produce a decision. A never-settling callback blocks further settled windows until it settles, or until terminal `abort()`.
50
74
 
51
75
  ## Handle API
52
76
 
@@ -54,8 +78,11 @@ Set `concurrency` to bound callbacks that are still awaiting asynchronous comple
54
78
 
55
79
  | Property | Type | Description |
56
80
  | -------- | ---- | ----------- |
81
+ | `pause()` | `() => void` | Temporarily prevent new callback starts while retaining accepted work |
82
+ | `resume()` | `() => void` | Resume a paused queue with a fresh pacing and observation window |
57
83
  | `stop()` | `() => void` | Stop processing the queue immediately |
58
- | `pending` | `number` (readonly) | Number of callbacks still waiting in the queue |
84
+ | `abort()` | `() => void` | Terminally discard queued work and signal active callbacks |
85
+ | `pending` | `number` (readonly) | Number of callbacks waiting in the queue, including delayed retries |
59
86
 
60
87
  ```ts
61
88
  const throttle = createThrottledQueue({ min_rpi: 5, interval: 1000 });
@@ -66,7 +93,22 @@ console.log(throttle.pending); // number of queued callbacks
66
93
  throttle.stop(); // halt processing
67
94
  ```
68
95
 
69
- `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.
96
+ ## Lifecycle
97
+
98
+ | State | Pending work and enqueue | Active work | Scheduling and lifecycle operations |
99
+ | ----- | ------------------------ | ----------- | ----------------------------------- |
100
+ | 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. |
101
+ | 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. |
102
+ | 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. |
103
+ | 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. |
104
+
105
+ 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()`.
106
+
107
+ 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.
108
+
109
+ `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.
110
+
111
+ `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.
70
112
 
71
113
  ## Examples
72
114
 
@@ -118,9 +160,69 @@ for (let i = 0; i < 100; i++) {
118
160
  }
119
161
  ```
120
162
 
163
+ ### Rate outcome classification
164
+
165
+ `rateOutcomeClassifier` receives only failed callback outcomes and returns whether each one should reduce the adaptive rate. It does not change retry eligibility: `false`, thrown errors, and rejected promises still retry under the existing `retry` option.
166
+
167
+ ```ts
168
+ import {
169
+ createThrottledQueue,
170
+ type RateFailureOutcome,
171
+ } from "dynamic-throttled-queue";
172
+
173
+ function affectsCapacity(outcome: RateFailureOutcome) {
174
+ if (outcome.kind === "returned-false") return false;
175
+
176
+ // Treat HTTP 429 and 5xx as capacity signals, while ignoring other failures.
177
+ const status = (outcome.error as { status?: number }).status;
178
+ return status === 429 || (status !== undefined && status >= 500 && status < 600);
179
+ }
180
+
181
+ const throttle = createThrottledQueue({
182
+ min_rpi: 1,
183
+ max_rpi: 10,
184
+ interval: 1000,
185
+ rateOutcomeClassifier: affectsCapacity,
186
+ });
187
+ ```
188
+
189
+ 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.
190
+
191
+ ### Retry classification
192
+
193
+ `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.
194
+
195
+ Retry eligibility is independent from adaptive-rate accounting. A failure can be retryable, rate-reducing, both, or neither:
196
+
197
+ ```ts
198
+ const throttle = createThrottledQueue({
199
+ min_rpi: 1,
200
+ interval: 1000,
201
+ retry: 2,
202
+ retryClassifier: (outcome, attempt) =>
203
+ outcome.kind === "rejected" && attempt < 3,
204
+ rateOutcomeClassifier: outcome => outcome.kind === "rejected",
205
+ });
206
+ ```
207
+
121
208
  ### Rate strategies
122
209
 
123
- The default `linear` strategy preserves the adaptive behavior above. You can import and pass it explicitly, or provide a custom pure strategy:
210
+ 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.
211
+
212
+ ```ts
213
+ import { aimd, createThrottledQueue } from "dynamic-throttled-queue";
214
+
215
+ const throttle = createThrottledQueue({
216
+ min_rpi: 1,
217
+ max_rpi: 100,
218
+ interval: 1000,
219
+ rateStrategy: aimd({ increaseBy: 2, decreaseFactor: 0.5 }),
220
+ });
221
+ ```
222
+
223
+ `aimd()` defaults to `{ increaseBy: 1, decreaseFactor: 0.5 }`. `increaseBy` must be a positive integer; `decreaseFactor` must be greater than `0` and less than `1`. AIMD uses `Math.floor(currentRate * decreaseFactor)` when reducing the rate, then the queue applies its configured `min_rpi` and `max_rpi` bounds. Like `linear`, it holds steady for partial-error, empty, and immediately-post-backoff observation windows.
224
+
225
+ You can also import and pass `linear` explicitly, or provide a custom pure strategy:
124
226
 
125
227
  ```ts
126
228
  import {
@@ -180,6 +282,24 @@ throttle(async () => {
180
282
  });
181
283
  ```
182
284
 
285
+ ### Retry backoff
286
+
287
+ ```ts
288
+ const throttle = createThrottledQueue({
289
+ min_rpi: 5,
290
+ interval: 1000,
291
+ retry: 3,
292
+ retryBackoff: {
293
+ strategy: "exponential",
294
+ baseDelay: 250,
295
+ maxDelay: 10_000,
296
+ jitter: 0.2,
297
+ },
298
+ });
299
+ ```
300
+
301
+ 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.
302
+
183
303
  ## Migration from v1
184
304
 
185
305
  - `errors_per_second` removed — use `errors_per_interval` (counts errors per full interval window, not per second).
@@ -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;
@@ -12,9 +19,29 @@ export type RateStrategyDecision = Readonly<{
12
19
  shouldBackOff: boolean;
13
20
  }>;
14
21
  export type RateStrategy = (observation: RateStrategyObservation) => RateStrategyDecision;
22
+ export type AimdOptions = {
23
+ increaseBy?: number;
24
+ decreaseFactor?: number;
25
+ };
26
+ export type RateFailureOutcome = Readonly<{
27
+ kind: "returned-false";
28
+ }> | Readonly<{
29
+ kind: "thrown";
30
+ error: unknown;
31
+ }> | Readonly<{
32
+ kind: "rejected";
33
+ error: unknown;
34
+ }>;
35
+ export type RateOutcomeClassifier = (outcome: RateFailureOutcome) => boolean;
36
+ export type RetryClassifier = (outcome: RateFailureOutcome, attempt: number) => boolean;
37
+ export type AdjustmentTiming = "interval" | "settled";
15
38
  export declare const linear: RateStrategy;
39
+ export declare function aimd({ increaseBy, decreaseFactor }?: AimdOptions): RateStrategy;
40
+ export type ExecutionContext = Readonly<{
41
+ signal: AbortSignal;
42
+ }>;
16
43
  /** Return `false` to signal failure (increments error count, triggers retry if configured). */
17
- export type ThrottleCallback = () => boolean | void | Promise<boolean | void>;
44
+ export type ThrottleCallback = (context: ExecutionContext) => boolean | void | Promise<boolean | void>;
18
45
  export type ThrottleOptions = {
19
46
  min_rpi: number;
20
47
  interval: number;
@@ -25,17 +52,30 @@ export type ThrottleOptions = {
25
52
  back_off?: boolean;
26
53
  /** Non-negative integer retries for each failed callback. Default 0. */
27
54
  retry?: number;
55
+ /** Per-retry delay policy. Omit to preserve immediate retries. */
56
+ retryBackoff?: RetryBackoff;
28
57
  /** Maximum number of callbacks awaiting asynchronous settlement. Omit for no limit. */
29
58
  concurrency?: number;
59
+ /** Maximum accepted callbacks that have not reached a terminal outcome. Omit for no limit. */
60
+ maxQueueSize?: number;
30
61
  /** Non-negative integer dead slots before queue compaction triggers. Default 512. */
31
62
  compact_threshold?: number;
32
63
  /** Policy used to request the next rate and any backoff after each observation window. */
33
64
  rateStrategy?: RateStrategy;
65
+ /** Decides whether a failed callback outcome contributes to adaptive-rate error counting. */
66
+ rateOutcomeClassifier?: RateOutcomeClassifier;
67
+ /** Decides whether a failed callback outcome is eligible for another attempt. */
68
+ retryClassifier?: RetryClassifier;
69
+ /** When adaptive-rate observations are adjusted. Defaults to interval compatibility behavior. */
70
+ adjustmentTiming?: AdjustmentTiming;
34
71
  onRateChange?: (rate: number) => void;
35
72
  };
36
73
  export type ThrottleFn = (callback: ThrottleCallback) => void;
37
74
  export type ThrottleHandle = ThrottleFn & {
75
+ pause: () => void;
76
+ resume: () => void;
38
77
  stop: () => void;
78
+ abort: () => void;
39
79
  readonly pending: number;
40
80
  };
41
81
  export declare function createThrottledQueue(options: ThrottleOptions): ThrottleHandle;
@@ -1,5 +1,6 @@
1
1
  import { createRateController } from "./rate-controller.js";
2
2
  import { createScheduler } from "./scheduler.js";
3
+ const adjustmentTimings = new Set(["interval", "settled"]);
3
4
  export const linear = ({ minRate, maxRate, currentRate, errorCount, errorThreshold, hasPendingWork, wasBackedOff, }) => {
4
5
  if (errorCount >= errorThreshold) {
5
6
  return { nextRate: Math.max(minRate, currentRate - 1), shouldBackOff: true };
@@ -9,8 +10,38 @@ export const linear = ({ minRate, maxRate, currentRate, errorCount, errorThresho
9
10
  }
10
11
  return { nextRate: currentRate, shouldBackOff: false };
11
12
  };
13
+ export function aimd({ increaseBy = 1, decreaseFactor = 0.5 } = {}) {
14
+ if (!Number.isInteger(increaseBy) || increaseBy < 1) {
15
+ throw new Error("increaseBy must be a positive integer");
16
+ }
17
+ if (!Number.isFinite(decreaseFactor) || decreaseFactor <= 0 || decreaseFactor >= 1) {
18
+ throw new Error("decreaseFactor must be a number greater than 0 and less than 1");
19
+ }
20
+ return ({ currentRate, errorCount, errorThreshold, hasPendingWork, wasBackedOff }) => {
21
+ if (errorCount >= errorThreshold) {
22
+ return { nextRate: Math.floor(currentRate * decreaseFactor), shouldBackOff: true };
23
+ }
24
+ if (!wasBackedOff && errorCount === 0 && hasPendingWork) {
25
+ return { nextRate: currentRate + increaseBy, shouldBackOff: false };
26
+ }
27
+ return { nextRate: currentRate, shouldBackOff: false };
28
+ };
29
+ }
30
+ function validateRetryBackoff(retryBackoff) {
31
+ if (retryBackoff === undefined)
32
+ return;
33
+ if (!Number.isFinite(retryBackoff.baseDelay) || retryBackoff.baseDelay < 0) {
34
+ throw new Error("retryBackoff.baseDelay must be a finite non-negative number");
35
+ }
36
+ if (retryBackoff.maxDelay !== undefined && (!Number.isFinite(retryBackoff.maxDelay) || retryBackoff.maxDelay < 0)) {
37
+ throw new Error("retryBackoff.maxDelay must be a finite non-negative number");
38
+ }
39
+ if (retryBackoff.jitter !== undefined && (!Number.isFinite(retryBackoff.jitter) || retryBackoff.jitter < 0 || retryBackoff.jitter > 1)) {
40
+ throw new Error("retryBackoff.jitter must be a finite number from 0 through 1");
41
+ }
42
+ }
12
43
  export function createThrottledQueue(options) {
13
- const { min_rpi, interval, max_rpi = min_rpi, concurrency, retry = 0, compact_threshold = 512 } = options;
44
+ const { min_rpi, interval, max_rpi = min_rpi, concurrency, maxQueueSize, retry = 0, compact_threshold = 512 } = options;
14
45
  const errors_per_interval = options.errors_per_interval ?? 5;
15
46
  if (!Number.isInteger(min_rpi) || min_rpi < 1) {
16
47
  throw new Error("min_rpi must be a positive integer");
@@ -24,6 +55,9 @@ export function createThrottledQueue(options) {
24
55
  if (concurrency !== undefined && (!Number.isInteger(concurrency) || concurrency < 1)) {
25
56
  throw new Error("concurrency must be a positive integer");
26
57
  }
58
+ if (maxQueueSize !== undefined && (!Number.isSafeInteger(maxQueueSize) || maxQueueSize < 0)) {
59
+ throw new Error("maxQueueSize must be a non-negative safe integer");
60
+ }
27
61
  if (!Number.isInteger(errors_per_interval) || errors_per_interval < 1) {
28
62
  throw new Error("errors_per_interval must be a positive integer");
29
63
  }
@@ -33,6 +67,10 @@ export function createThrottledQueue(options) {
33
67
  if (!Number.isInteger(compact_threshold) || compact_threshold < 0) {
34
68
  throw new Error("compact_threshold must be a non-negative integer");
35
69
  }
70
+ if (options.adjustmentTiming !== undefined && !adjustmentTimings.has(options.adjustmentTiming)) {
71
+ throw new Error("adjustmentTiming must be either interval or settled");
72
+ }
73
+ validateRetryBackoff(options.retryBackoff);
36
74
  return createScheduler(options, createRateController({
37
75
  min_rpi,
38
76
  max_rpi,
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-throttled-queue.js","sourceRoot":"","sources":["../src/dynamic-throttled-queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,6BAA6B;AAC5D,OAAO,EAAE,eAAe,EAAE,uBAAuB;AAmBjD,MAAM,CAAC,MAAM,MAAM,GAAiB,CAAC,EACnC,OAAO,EACP,OAAO,EACP,WAAW,EACX,UAAU,EACV,cAAc,EACd,cAAc,EACd,YAAY,GACb,EAAE,EAAE;IACH,IAAI,UAAU,IAAI,cAAc,EAAE,CAAC;QACjC,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,GAAG,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;IAC/E,CAAC;IACD,IAAI,CAAC,YAAY,IAAI,UAAU,KAAK,CAAC,IAAI,cAAc,EAAE,CAAC;QACxD,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,GAAG,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;IAChF,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;AACzD,CAAC,CAAC;AA+BF,MAAM,UAAU,oBAAoB,CAAC,OAAwB;IAC3D,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,EAAE,WAAW,EAAE,KAAK,GAAG,CAAC,EAAE,iBAAiB,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC;IAE1G,MAAM,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,IAAI,CAAC,CAAC;IAE7D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,OAAO,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,WAAW,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,CAAC,EAAE,CAAC;QACrF,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,mBAAmB,CAAC,IAAI,mBAAmB,GAAG,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,iBAAiB,GAAG,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,eAAe,CAAC,OAAO,EAAE,oBAAoB,CAAC;QACnD,OAAO;QACP,OAAO;QACP,mBAAmB;KACpB,EAAE,OAAO,CAAC,YAAY,IAAI,MAAM,CAAC,CAAC,CAAC;AACtC,CAAC"}
1
+ {"version":3,"file":"dynamic-throttled-queue.js","sourceRoot":"","sources":["../src/dynamic-throttled-queue.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,8 @@ export type RateDecision = {
14
14
  };
15
15
  export type RateController = {
16
16
  readonly rate: number;
17
- recordCompletion: (result: boolean | void) => void;
17
+ clearObservation: () => void;
18
+ recordCompletion: (isRateReducing: boolean) => void;
18
19
  observe: (observation: Observation) => RateDecision;
19
20
  };
20
21
  export declare function createRateController(options: RateControllerOptions, strategy: RateStrategy): RateController;
@@ -18,8 +18,11 @@ export function createRateController(options, strategy) {
18
18
  get rate() {
19
19
  return rate;
20
20
  },
21
- recordCompletion(result) {
22
- if (result === false)
21
+ clearObservation() {
22
+ errorCount = 0;
23
+ },
24
+ recordCompletion(isRateReducing) {
25
+ if (isRateReducing)
23
26
  errorCount++;
24
27
  },
25
28
  observe(observation) {
@@ -1 +1 @@
1
- {"version":3,"file":"rate-controller.js","sourceRoot":"","sources":["../src/rate-controller.ts"],"names":[],"mappings":"AAwBA,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,CAAC,MAAsB;YACrC,IAAI,MAAM,KAAK,KAAK;gBAAE,UAAU,EAAE,CAAC;QACrC,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"}
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"}
@@ -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"}
package/dist/scheduler.js CHANGED
@@ -1,5 +1,7 @@
1
+ import { calculateRetryDelay } from "./retry-backoff.js";
1
2
  export function createScheduler(options, rateController) {
2
- const { interval, evenly_spaced = true, retry = 0, concurrency, compact_threshold = 512, back_off = false, onRateChange, } = options;
3
+ const { interval, evenly_spaced = true, retry = 0, retryBackoff, concurrency, maxQueueSize, compact_threshold = 512, back_off = false, rateOutcomeClassifier, retryClassifier, onRateChange, adjustmentTiming = "interval", } = options;
4
+ const usesSettledTiming = adjustmentTiming === "settled";
3
5
  let current_rpi = rateController.rate;
4
6
  let dyn_interval = evenly_spaced ? interval / current_rpi : interval;
5
7
  let dyn_requests_per_interval = evenly_spaced ? 1 : current_rpi;
@@ -9,12 +11,60 @@ export function createScheduler(options, rateController) {
9
11
  let timeout;
10
12
  let dynTimeout;
11
13
  let active_count = 0;
14
+ let isPaused = false;
12
15
  let isStopped = false;
16
+ let isAborted = false;
13
17
  let hasStrategyFailure = false;
14
18
  let strategyFailure;
19
+ const abortController = new AbortController();
15
20
  const max_concurrency = concurrency ?? Infinity;
21
+ const max_queue_size = maxQueueSize ?? Infinity;
16
22
  const queue = [];
23
+ const delayedRetries = [];
17
24
  let head = 0;
25
+ let reserved_count = 0;
26
+ let observationWindow;
27
+ let nextObservationWindow = 0;
28
+ let collectingSettledWindow = false;
29
+ let settledOutstanding = 0;
30
+ function releaseDelayedRetry(delayedRetry) {
31
+ const index = delayedRetries.indexOf(delayedRetry);
32
+ if (index < 0)
33
+ return;
34
+ delayedRetries.splice(index, 1);
35
+ queue.push(delayedRetry.item);
36
+ if (!isRunning && !isPaused && !isStopped && queue.length > head)
37
+ start();
38
+ }
39
+ function startDelayedRetry(delayedRetry) {
40
+ delayedRetry.due = Date.now() + delayedRetry.remaining;
41
+ delayedRetry.timeout = setTimeout(() => {
42
+ releaseDelayedRetry(delayedRetry);
43
+ }, delayedRetry.remaining);
44
+ }
45
+ function freezeDelayedRetries() {
46
+ for (const delayedRetry of delayedRetries) {
47
+ if (delayedRetry.timeout === undefined)
48
+ continue;
49
+ if (delayedRetry.due === undefined)
50
+ continue;
51
+ clearTimeout(delayedRetry.timeout);
52
+ delayedRetry.timeout = undefined;
53
+ delayedRetry.remaining = Math.max(0, delayedRetry.due - Date.now());
54
+ }
55
+ }
56
+ function resumeDelayedRetries() {
57
+ for (const delayedRetry of delayedRetries) {
58
+ if (delayedRetry.timeout === undefined)
59
+ startDelayedRetry(delayedRetry);
60
+ }
61
+ }
62
+ function scheduleDelayedRetry(item, delay) {
63
+ const delayedRetry = { item, remaining: delay };
64
+ delayedRetries.push(delayedRetry);
65
+ if (!isPaused && !isStopped)
66
+ startDelayedRetry(delayedRetry);
67
+ }
18
68
  function halt() {
19
69
  isRunning = false;
20
70
  skippedLast = false;
@@ -27,24 +77,120 @@ export function createScheduler(options, rateController) {
27
77
  head = 0;
28
78
  }
29
79
  }
80
+ function discardSettledWindow() {
81
+ observationWindow = undefined;
82
+ collectingSettledWindow = false;
83
+ settledOutstanding = 0;
84
+ }
30
85
  function stop() {
31
86
  isStopped = true;
87
+ isPaused = false;
88
+ freezeDelayedRetries();
32
89
  halt();
90
+ discardSettledWindow();
33
91
  }
34
- function handleResult(item, result) {
35
- rateController.recordCompletion(result);
36
- if (result === false && item.retries > 0) {
37
- queue.push({ fn: item.fn, retries: item.retries - 1 });
38
- if (!isRunning && !isStopped && queue.length > head)
39
- start();
92
+ function pause() {
93
+ if (isAborted || isStopped || isPaused)
94
+ return;
95
+ isPaused = true;
96
+ rateController.clearObservation();
97
+ freezeDelayedRetries();
98
+ halt();
99
+ discardSettledWindow();
100
+ }
101
+ function resume() {
102
+ if (!isPaused)
103
+ return;
104
+ isPaused = false;
105
+ resumeDelayedRetries();
106
+ if (queue.length > head)
107
+ start();
108
+ }
109
+ function abort() {
110
+ if (isAborted)
111
+ return;
112
+ isAborted = true;
113
+ halt();
114
+ discardSettledWindow();
115
+ freezeDelayedRetries();
116
+ delayedRetries.length = 0;
117
+ queue.length = 0;
118
+ head = 0;
119
+ reserved_count = 0;
120
+ abortController.abort();
121
+ }
122
+ function isRateReducing(outcome) {
123
+ if (!outcome)
124
+ return false;
125
+ try {
126
+ return rateOutcomeClassifier?.(outcome) ?? true;
127
+ }
128
+ catch {
129
+ return true;
40
130
  }
41
131
  }
42
- function handleSettlement(item, result, resume = false) {
132
+ function isRetryable(item, outcome) {
133
+ if (!outcome || item.retries === 0)
134
+ return false;
135
+ try {
136
+ return retryClassifier ? retryClassifier(outcome, retry - item.retries + 1) === true : true;
137
+ }
138
+ catch {
139
+ return true;
140
+ }
141
+ }
142
+ function handleResult(item, outcome) {
143
+ if (isAborted)
144
+ return;
145
+ if (!isPaused && (!usesSettledTiming || item.observationWindow === observationWindow)) {
146
+ rateController.recordCompletion(isRateReducing(outcome));
147
+ }
148
+ if (isRetryable(item, outcome)) {
149
+ const retryItem = { fn: item.fn, retries: item.retries - 1 };
150
+ if (retryBackoff === undefined) {
151
+ queue.push(retryItem);
152
+ if (!isRunning && !isPaused && !isStopped && queue.length > head)
153
+ start();
154
+ }
155
+ else {
156
+ const retryIndex = retry - item.retries + 1;
157
+ scheduleDelayedRetry(retryItem, calculateRetryDelay(retryBackoff, retryIndex));
158
+ }
159
+ }
160
+ else
161
+ reserved_count--;
162
+ }
163
+ function handleSettlement(item, outcome, resume = false) {
43
164
  active_count--;
44
- handleResult(item, result);
45
- if (resume && isRunning && !skippedLast && queue.length > head)
165
+ handleResult(item, outcome);
166
+ if (item.observationWindow === observationWindow) {
167
+ settledOutstanding--;
168
+ if (!collectingSettledWindow && settledOutstanding === 0)
169
+ finishSettledWindow();
170
+ }
171
+ if (resume && isRunning && !skippedLast && queue.length > head && (!usesSettledTiming || collectingSettledWindow))
46
172
  dequeue();
47
173
  }
174
+ function execute(item) {
175
+ if (usesSettledTiming && collectingSettledWindow) {
176
+ item.observationWindow = observationWindow;
177
+ settledOutstanding++;
178
+ }
179
+ active_count++;
180
+ let result;
181
+ try {
182
+ result = item.fn({ signal: abortController.signal });
183
+ }
184
+ catch (error) {
185
+ handleSettlement(item, { kind: "thrown", error });
186
+ return;
187
+ }
188
+ if (result instanceof Promise) {
189
+ void result.then(value => handleSettlement(item, value === false ? { kind: "returned-false" } : undefined, true), (error) => handleSettlement(item, { kind: "rejected", error }, true));
190
+ return;
191
+ }
192
+ handleSettlement(item, result === false ? { kind: "returned-false" } : undefined);
193
+ }
48
194
  function dequeue() {
49
195
  const threshold = last_called + dyn_interval;
50
196
  const now = Date.now();
@@ -57,29 +203,15 @@ export function createScheduler(options, rateController) {
57
203
  let started = 0;
58
204
  while (head < end && active_count < max_concurrency) {
59
205
  const item = queue[head++];
60
- active_count++;
61
206
  if (started++ === 0)
62
207
  last_called = Date.now();
63
- let result;
64
- try {
65
- result = item.fn();
66
- }
67
- catch {
68
- handleSettlement(item, false);
69
- continue;
70
- }
71
- if (result instanceof Promise) {
72
- void result.then(value => handleSettlement(item, value, true), () => handleSettlement(item, false, true));
73
- }
74
- else {
75
- handleSettlement(item, result);
76
- }
208
+ execute(item);
77
209
  }
78
210
  if (head > compact_threshold && head > queue.length / 2) {
79
211
  queue.splice(0, head);
80
212
  head = 0;
81
213
  }
82
- if (head >= queue.length) {
214
+ if (head >= queue.length && !usesSettledTiming) {
83
215
  halt();
84
216
  return;
85
217
  }
@@ -120,9 +252,67 @@ export function createScheduler(options, rateController) {
120
252
  if (isRunning)
121
253
  dynTimeout = setTimeout(adjustRate, interval);
122
254
  }
255
+ function finishSettledWindow() {
256
+ if (observationWindow === undefined || isPaused || isStopped || isAborted)
257
+ return;
258
+ const wasSkipped = skippedLast;
259
+ skippedLast = false;
260
+ let decision;
261
+ try {
262
+ decision = rateController.observe({ hasPendingWork: queue.length > head, wasBackedOff: wasSkipped });
263
+ }
264
+ catch (error) {
265
+ hasStrategyFailure = true;
266
+ strategyFailure = error;
267
+ halt();
268
+ discardSettledWindow();
269
+ throw error;
270
+ }
271
+ observationWindow = undefined;
272
+ applyRate(decision.rate);
273
+ if (decision.shouldBackOff && back_off) {
274
+ skippedLast = true;
275
+ timeout = setTimeout(resumeSettledScheduling, interval);
276
+ return;
277
+ }
278
+ if (queue.length > head)
279
+ beginSettledWindow();
280
+ else
281
+ halt();
282
+ }
283
+ function closeSettledWindow() {
284
+ dynTimeout = undefined;
285
+ collectingSettledWindow = false;
286
+ clearTimeout(timeout);
287
+ timeout = undefined;
288
+ if (settledOutstanding === 0)
289
+ finishSettledWindow();
290
+ }
291
+ function resumeSettledScheduling() {
292
+ skippedLast = false;
293
+ beginSettledWindow();
294
+ }
295
+ function beginSettledWindow() {
296
+ if (isAborted || isPaused || isStopped || skippedLast || queue.length <= head)
297
+ return;
298
+ isRunning = true;
299
+ collectingSettledWindow = true;
300
+ observationWindow = nextObservationWindow++;
301
+ last_called = Date.now();
302
+ clearTimeout(timeout);
303
+ timeout = setTimeout(dequeue, dyn_interval);
304
+ clearTimeout(dynTimeout);
305
+ dynTimeout = setTimeout(closeSettledWindow, interval);
306
+ }
123
307
  function start() {
308
+ if (isAborted || isPaused || isStopped)
309
+ return;
124
310
  if (skippedLast)
125
311
  return;
312
+ if (usesSettledTiming) {
313
+ beginSettledWindow();
314
+ return;
315
+ }
126
316
  isRunning = true;
127
317
  last_called = Date.now();
128
318
  clearTimeout(timeout);
@@ -131,15 +321,26 @@ export function createScheduler(options, rateController) {
131
321
  dynTimeout = setTimeout(adjustRate, interval);
132
322
  }
133
323
  function enqueue(callback) {
324
+ if (isAborted)
325
+ throw new Error("Cannot enqueue work after the queue has been aborted");
134
326
  if (hasStrategyFailure)
135
327
  throw strategyFailure;
328
+ if (reserved_count >= max_queue_size)
329
+ throw new Error("Cannot enqueue work: maxQueueSize has been reached");
330
+ reserved_count++;
136
331
  queue.push({ fn: callback, retries: retry });
332
+ const wasStopped = isStopped;
137
333
  isStopped = false;
138
- if (!isRunning)
334
+ if (wasStopped)
335
+ resumeDelayedRetries();
336
+ if (!isRunning && !isPaused)
139
337
  start();
140
338
  }
339
+ enqueue.pause = pause;
340
+ enqueue.resume = resume;
141
341
  enqueue.stop = stop;
142
- Object.defineProperty(enqueue, "pending", { get: () => queue.length - head });
342
+ enqueue.abort = abort;
343
+ Object.defineProperty(enqueue, "pending", { get: () => queue.length - head + delayedRetries.length });
143
344
  return enqueue;
144
345
  }
145
346
  //# 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.1849e68",
3
+ "version": "2.2.0-rc.3d51b8f",
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": [