adaptive-concurrency 0.3.3 → 0.3.4

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/dist/Limiter.d.ts CHANGED
@@ -67,8 +67,9 @@ export interface AllotmentUnavailableStrategy<ContextT> {
67
67
  */
68
68
  onAllotmentReleased(): MaybePromise<void>;
69
69
  /**
70
- * Called when the adaptive limit changes. Blocking strategies can use this to
71
- * proactively drain queued waiters when capacity increases.
70
+ * Called when the adaptive limit changes. Blocking/rejection strategies can
71
+ * use this to proactively react to newly available capacity (e.g. drain
72
+ * backlog).
72
73
  */
73
74
  onLimitChanged?(oldLimit: number, newLimit: number): MaybePromise<void>;
74
75
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Limiter.d.ts","sourceRoot":"","sources":["../src/Limiter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Limiter.d.ts","sourceRoot":"","sources":["../src/Limiter.ts"],"names":[],"mappings":"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"}
package/dist/Limiter.js CHANGED
@@ -85,15 +85,27 @@ export class Limiter {
85
85
  };
86
86
  if (!(await this.acquireStrategy.tryAcquireAllotment(ctx, state))) {
87
87
  this.rejectedCounter.increment();
88
- if (this.rejectionStrategy) {
88
+ if (!this.rejectionStrategy) {
89
+ return undefined;
90
+ }
91
+ // if signal aborted here, nothing to cleanup, as we didn't acquire anything.
92
+ if (options?.signal?.aborted) {
93
+ return undefined;
94
+ }
95
+ return this.rejectionStrategy.onAllotmentUnavailable(ctx, async (retryCtx) => {
89
96
  if (options?.signal?.aborted) {
90
97
  return undefined;
91
98
  }
92
- return this.rejectionStrategy.onAllotmentUnavailable(ctx, (retryCtx) => this.tryAcquireCore(retryCtx), options?.signal);
93
- }
99
+ return this.tryAcquireCore(retryCtx);
100
+ }, options?.signal);
101
+ }
102
+ const allotment = this.createAllotment(ctx);
103
+ if (options?.signal?.aborted) {
104
+ // here, we did acquire, so we need to try to cleanup.
105
+ await allotment.releaseAndIgnore();
94
106
  return undefined;
95
107
  }
96
- return this.createAllotment(ctx);
108
+ return allotment;
97
109
  }
98
110
  async tryAcquireCore(ctx) {
99
111
  const state = {
@@ -108,30 +120,77 @@ export class Limiter {
108
120
  createAllotment(ctx) {
109
121
  const startTime = this.clock();
110
122
  const currentInflight = ++this._inflight;
123
+ // Make sure an allotment can only be released once; future calls become a
124
+ // no-op. This simplifies a lot of cleanup handling etc that'd otherwise be
125
+ // much racier/more complicated. It could hide subtle correctness issue, but
126
+ // should be more valuable as defense-in-depth.
127
+ let releaseStarted = false;
111
128
  return {
112
129
  releaseAndRecordSuccess: async () => {
130
+ if (releaseStarted)
131
+ return;
132
+ releaseStarted = true;
113
133
  const endTime = this.clock();
114
134
  const rtt = endTime - startTime;
115
135
  this._inflight--;
116
- await this.acquireStrategy.onAllotmentReleased(ctx);
117
136
  this.successCounter.increment();
118
- this.limitAlgorithm.addSample(startTime, rtt, currentInflight, false);
119
- await this.rejectionStrategy?.onAllotmentReleased();
137
+ // If one onAllotmentReleased call fails, hard to know what to do here.
138
+ // We're in some kind of inconsistent state, but we probably have to
139
+ // soldier on.
140
+ try {
141
+ await this.acquireStrategy.onAllotmentReleased(ctx);
142
+ }
143
+ catch { }
144
+ try {
145
+ this.limitAlgorithm.addSample(startTime, rtt, currentInflight, false);
146
+ }
147
+ catch { }
148
+ try {
149
+ await this.rejectionStrategy?.onAllotmentReleased();
150
+ }
151
+ catch { }
120
152
  },
121
153
  releaseAndIgnore: async () => {
154
+ if (releaseStarted)
155
+ return;
156
+ releaseStarted = true;
122
157
  this._inflight--;
123
- await this.acquireStrategy.onAllotmentReleased(ctx);
124
158
  this.ignoredCounter.increment();
125
- await this.rejectionStrategy?.onAllotmentReleased();
159
+ // If one onAllotmentReleased call fails, hard to know what to do here.
160
+ // We're in some kind of inconsistent state, but we probably have to
161
+ // soldier on.
162
+ try {
163
+ await this.acquireStrategy.onAllotmentReleased(ctx);
164
+ }
165
+ catch { }
166
+ try {
167
+ await this.rejectionStrategy?.onAllotmentReleased();
168
+ }
169
+ catch { }
126
170
  },
127
171
  releaseAndRecordDropped: async () => {
172
+ if (releaseStarted)
173
+ return;
174
+ releaseStarted = true;
128
175
  const endTime = this.clock();
129
176
  const rtt = endTime - startTime;
130
177
  this._inflight--;
131
- await this.acquireStrategy.onAllotmentReleased(ctx);
132
178
  this.droppedCounter.increment();
133
- this.limitAlgorithm.addSample(startTime, rtt, currentInflight, true);
134
- await this.rejectionStrategy?.onAllotmentReleased();
179
+ // If one onAllotmentReleased call fails, hard to know what to do here.
180
+ // We're in some kind of inconsistent state, but we probably have to
181
+ // soldier on.
182
+ try {
183
+ await this.acquireStrategy.onAllotmentReleased(ctx);
184
+ }
185
+ catch { }
186
+ try {
187
+ this.limitAlgorithm.addSample(startTime, rtt, currentInflight, true);
188
+ }
189
+ catch { }
190
+ try {
191
+ await this.rejectionStrategy?.onAllotmentReleased();
192
+ }
193
+ catch { }
135
194
  },
136
195
  };
137
196
  }
@@ -1,5 +1,6 @@
1
1
  import type { LimitAllotment } from "../../LimitAllotment.js";
2
2
  import type { AcquireResult, AllotmentUnavailableStrategy } from "../../Limiter.js";
3
+ import type { WaiterHandle } from "../../utils/LinkedWaiterQueue.js";
3
4
  type Waiter<ContextT> = {
4
5
  context: ContextT;
5
6
  retry: (context: ContextT) => AcquireResult;
@@ -18,14 +19,12 @@ export type WaiterQueue<WaiterT extends Waiter<any>> = {
18
19
  removeByHandle: (handle: WaiterHandle) => boolean;
19
20
  size: () => number;
20
21
  };
21
- export type WaiterHandle = {
22
- key: symbol;
23
- };
24
22
  export declare class BlockingBacklogRejection<ContextT> implements AllotmentUnavailableStrategy<ContextT> {
25
23
  private readonly backlogSize;
26
24
  private readonly getBacklogTimeout;
27
25
  private readonly queue;
28
26
  private drainInProgress;
27
+ private releaseDuringDrain;
29
28
  constructor(options: BlockingBacklogRejectionOptions<ContextT>);
30
29
  onAllotmentUnavailable(context: ContextT, retry: (context: ContextT) => AcquireResult, signal?: AbortSignal): Promise<LimitAllotment | undefined>;
31
30
  onAllotmentReleased(): Promise<void>;
@@ -33,19 +32,5 @@ export declare class BlockingBacklogRejection<ContextT> implements AllotmentUnav
33
32
  private waitInBacklog;
34
33
  private assertTimeoutWithinBounds;
35
34
  }
36
- export declare class ArrayWaiterQueue<WaiterT extends Waiter<any>> implements WaiterQueue<WaiterT> {
37
- private head;
38
- private tail;
39
- private readonly nodes;
40
- private readonly enqueueDirection;
41
- private length;
42
- constructor(enqueueDirection: "front" | "back");
43
- enqueue(waiterWithoutHandle: Omit<WaiterT, "handle">): WaiterT;
44
- peekHead(): WaiterT | undefined;
45
- removeByHandle(handle: WaiterHandle): boolean;
46
- size(): number;
47
- private pushFront;
48
- private pushBack;
49
- }
50
35
  export {};
51
36
  //# sourceMappingURL=BlockingBacklogRejection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"BlockingBacklogRejection.d.ts","sourceRoot":"","sources":["../../../src/limiter/allocation-unavailable-strategies/BlockingBacklogRejection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EACV,aAAa,EACb,4BAA4B,EAC7B,MAAM,kBAAkB,CAAC;AAE1B,KAAK,MAAM,CAAC,QAAQ,IAAI;IACtB,OAAO,EAAE,QAAQ,CAAC;IAClB,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,CAAC;IAC5C,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,CAAC,SAAS,EAAE,cAAc,GAAG,SAAS,KAAK,IAAI,CAAC;CAC1D,CAAC;AAEF,eAAO,MAAM,WAAW,QAAiB,CAAC;AAE1C,MAAM,MAAM,+BAA+B,CAAC,QAAQ,IAAI;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC;IACzD,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,OAAO,SAAS,MAAM,CAAC,GAAG,CAAC,IAAI;IACrD,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,OAAO,CAAC;IACtD,QAAQ,EAAE,MAAM,OAAO,GAAG,SAAS,CAAC;IACpC,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,OAAO,CAAC;IAClD,IAAI,EAAE,MAAM,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,qBAAa,wBAAwB,CACnC,QAAQ,CACR,YAAW,4BAA4B,CAAC,QAAQ,CAAC;IACjD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgC;IAClE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD,OAAO,CAAC,eAAe,CAAS;gBAEpB,OAAO,EAAE,+BAA+B,CAAC,QAAQ,CAAC;IAmB9D,sBAAsB,CACpB,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,EAC3C,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IAYhC,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAgC1C,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQxD,OAAO,CAAC,aAAa;IAmCrB,OAAO,CAAC,yBAAyB;CAKlC;AAED,qBAAa,gBAAgB,CAC3B,OAAO,SAAS,MAAM,CAAC,GAAG,CAAC,CAC3B,YAAW,WAAW,CAAC,OAAO,CAAC;IAC/B,OAAO,CAAC,IAAI,CAAkC;IAC9C,OAAO,CAAC,IAAI,CAAkC;IAC9C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0C;IAChE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD,OAAO,CAAC,MAAM,CAAK;gBAEP,gBAAgB,EAAE,OAAO,GAAG,MAAM;IAI9C,OAAO,CAAC,mBAAmB,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,GAAG,OAAO;IAuB9D,QAAQ,IAAI,OAAO,GAAG,SAAS;IAI/B,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO;IAuB7C,IAAI,IAAI,MAAM;IAId,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,QAAQ;CAWjB"}
1
+ {"version":3,"file":"BlockingBacklogRejection.d.ts","sourceRoot":"","sources":["../../../src/limiter/allocation-unavailable-strategies/BlockingBacklogRejection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EACV,aAAa,EACb,4BAA4B,EAC7B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAErE,KAAK,MAAM,CAAC,QAAQ,IAAI;IACtB,OAAO,EAAE,QAAQ,CAAC;IAClB,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,CAAC;IAC5C,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,CAAC,SAAS,EAAE,cAAc,GAAG,SAAS,KAAK,IAAI,CAAC;CAC1D,CAAC;AAEF,eAAO,MAAM,WAAW,QAAiB,CAAC;AAE1C,MAAM,MAAM,+BAA+B,CAAC,QAAQ,IAAI;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC;IACzD,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,OAAO,SAAS,MAAM,CAAC,GAAG,CAAC,IAAI;IACrD,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,OAAO,CAAC;IACtD,QAAQ,EAAE,MAAM,OAAO,GAAG,SAAS,CAAC;IACpC,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,OAAO,CAAC;IAClD,IAAI,EAAE,MAAM,MAAM,CAAC;CACpB,CAAC;AAEF,qBAAa,wBAAwB,CACnC,QAAQ,CACR,YAAW,4BAA4B,CAAC,QAAQ,CAAC;IACjD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgC;IAClE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,kBAAkB,CAAS;gBAEvB,OAAO,EAAE,+BAA+B,CAAC,QAAQ,CAAC;IA6B9D,sBAAsB,CACpB,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,EAC3C,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IAYhC,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IA4C1C,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQxD,OAAO,CAAC,aAAa;IAiCrB,OAAO,CAAC,yBAAyB;CAUlC"}
@@ -4,8 +4,14 @@ export class BlockingBacklogRejection {
4
4
  getBacklogTimeout;
5
5
  queue;
6
6
  drainInProgress = false;
7
+ releaseDuringDrain = false;
7
8
  constructor(options) {
8
- this.backlogSize = options.backlogSize;
9
+ const backlogSize = options.backlogSize;
10
+ if (backlogSize !== Number.POSITIVE_INFINITY &&
11
+ (!Number.isFinite(backlogSize) || backlogSize < 0)) {
12
+ throw new RangeError("BlockingBacklogRejection: backlogSize must be a finite number greater than or equal to 0, or Infinity");
13
+ }
14
+ this.backlogSize = backlogSize;
9
15
  this.queue = options.queue;
10
16
  const backlogTimeout = options.backlogTimeout;
11
17
  if (typeof backlogTimeout === "number") {
@@ -29,7 +35,11 @@ export class BlockingBacklogRejection {
29
35
  return this.waitInBacklog(context, retry, signal);
30
36
  }
31
37
  async onAllotmentReleased() {
32
- if (this.drainInProgress || this.queue.size() === 0) {
38
+ if (this.drainInProgress) {
39
+ this.releaseDuringDrain = true;
40
+ return;
41
+ }
42
+ if (this.queue.size() === 0) {
33
43
  return;
34
44
  }
35
45
  this.drainInProgress = true;
@@ -39,8 +49,15 @@ export class BlockingBacklogRejection {
39
49
  if (!waiter) {
40
50
  return;
41
51
  }
52
+ this.releaseDuringDrain = false;
42
53
  const allotment = await waiter.retry(waiter.context);
43
54
  if (!allotment) {
55
+ if (this.releaseDuringDrain) {
56
+ // A slot was released while retry was in-flight but the
57
+ // notification was suppressed by drainInProgress. Retry the
58
+ // loop so the freed capacity isn't lost.
59
+ continue;
60
+ }
44
61
  return;
45
62
  }
46
63
  if (!this.queue.removeByHandle(waiter.handle)) {
@@ -64,6 +81,7 @@ export class BlockingBacklogRejection {
64
81
  }
65
82
  }
66
83
  waitInBacklog(context, retry, signal) {
84
+ const timeout = this.getBacklogTimeout(context);
67
85
  return new Promise((resolve) => {
68
86
  let settled = false;
69
87
  const settle = (allotment) => {
@@ -78,7 +96,7 @@ export class BlockingBacklogRejection {
78
96
  retry,
79
97
  resolve: (allotment) => settle(allotment),
80
98
  });
81
- const timer = setTimeout(() => settle(undefined), this.getBacklogTimeout(context));
99
+ const timer = setTimeout(() => settle(undefined), timeout);
82
100
  const onAbort = () => settle(undefined);
83
101
  const cleanup = () => {
84
102
  clearTimeout(timer);
@@ -89,88 +107,11 @@ export class BlockingBacklogRejection {
89
107
  });
90
108
  }
91
109
  assertTimeoutWithinBounds(timeout) {
92
- if (timeout > MAX_TIMEOUT) {
93
- throw new Error(`Timeout cannot be greater than ${MAX_TIMEOUT} ms`);
94
- }
95
- }
96
- }
97
- export class ArrayWaiterQueue {
98
- head;
99
- tail;
100
- nodes = new Map();
101
- enqueueDirection;
102
- length = 0;
103
- constructor(enqueueDirection) {
104
- this.enqueueDirection = enqueueDirection;
105
- }
106
- enqueue(waiterWithoutHandle) {
107
- const handle = { key: Symbol("waiter-node") };
108
- const waiter = {
109
- ...waiterWithoutHandle,
110
- handle,
111
- };
112
- const node = {
113
- handle,
114
- value: waiter,
115
- prev: undefined,
116
- next: undefined,
117
- };
118
- this.nodes.set(handle.key, node);
119
- if (this.enqueueDirection === "front") {
120
- this.pushFront(node);
121
- }
122
- else {
123
- this.pushBack(node);
124
- }
125
- this.length += 1;
126
- return waiter;
127
- }
128
- peekHead() {
129
- return this.head?.value;
130
- }
131
- removeByHandle(handle) {
132
- const node = this.nodes.get(handle.key);
133
- if (!node)
134
- return false;
135
- this.nodes.delete(handle.key);
136
- if (node.prev) {
137
- node.prev.next = node.next;
138
- }
139
- else {
140
- this.head = node.next;
141
- }
142
- if (node.next) {
143
- node.next.prev = node.prev;
144
- }
145
- else {
146
- this.tail = node.prev;
147
- }
148
- node.prev = undefined;
149
- node.next = undefined;
150
- this.length -= 1;
151
- return true;
152
- }
153
- size() {
154
- return this.length;
155
- }
156
- pushFront(node) {
157
- if (!this.head) {
158
- this.head = node;
159
- this.tail = node;
160
- return;
110
+ if (!Number.isFinite(timeout) || timeout < 0) {
111
+ throw new RangeError("Timeout must be a finite number greater than or equal to 0");
161
112
  }
162
- node.next = this.head;
163
- this.head.prev = node;
164
- this.head = node;
165
- }
166
- pushBack(node) {
167
- if (!this.tail) {
168
- this.head = node;
169
- this.tail = node;
170
- return;
113
+ if (timeout > MAX_TIMEOUT) {
114
+ throw new RangeError(`Timeout cannot be greater than ${MAX_TIMEOUT} ms`);
171
115
  }
172
- node.prev = this.tail;
173
- this.tail.next = node;
174
- this.tail = node;
175
116
  }
176
117
  }
@@ -15,5 +15,6 @@ export declare class DelayedThenBlockingRejection<ContextT> implements Allotment
15
15
  });
16
16
  onAllotmentUnavailable(context: ContextT, retry: (context: ContextT) => AcquireResult, signal?: AbortSignal): Promise<LimitAllotment | undefined>;
17
17
  onAllotmentReleased(): Promise<void>;
18
+ onLimitChanged(oldLimit: number, newLimit: number): void;
18
19
  }
19
20
  //# sourceMappingURL=DelayedThenBlockingRejection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DelayedThenBlockingRejection.d.ts","sourceRoot":"","sources":["../../../src/limiter/allocation-unavailable-strategies/DelayedThenBlockingRejection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EACV,aAAa,EACb,4BAA4B,EAC7B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAExE;;;;GAIG;AACH,qBAAa,4BAA4B,CACvC,QAAQ,CACR,YAAW,4BAA4B,CAAC,QAAQ,CAAC;IACjD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkC;IAChE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAyC;gBAE9D,OAAO,EAAE;QACnB,aAAa,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAC/C,gBAAgB,EAAE,4BAA4B,CAAC,QAAQ,CAAC,CAAC;KAC1D;IAKK,sBAAsB,CAC1B,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,EAC3C,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IAqBhC,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;CAI3C"}
1
+ {"version":3,"file":"DelayedThenBlockingRejection.d.ts","sourceRoot":"","sources":["../../../src/limiter/allocation-unavailable-strategies/DelayedThenBlockingRejection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EACV,aAAa,EACb,4BAA4B,EAC7B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAExE;;;;GAIG;AACH,qBAAa,4BAA4B,CACvC,QAAQ,CACR,YAAW,4BAA4B,CAAC,QAAQ,CAAC;IACjD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkC;IAChE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAyC;gBAE9D,OAAO,EAAE;QACnB,aAAa,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAC/C,gBAAgB,EAAE,4BAA4B,CAAC,QAAQ,CAAC,CAAC;KAC1D;IAKK,sBAAsB,CAC1B,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,EAC3C,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IAkBhC,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAK1C,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;CAGzD"}
@@ -22,11 +22,13 @@ export class DelayedThenBlockingRejection {
22
22
  if (signal?.aborted) {
23
23
  return undefined;
24
24
  }
25
- return (allotment ??
26
- this.blockingStrategy.onAllotmentUnavailable(context, retry, signal));
25
+ return this.blockingStrategy.onAllotmentUnavailable(context, retry, signal);
27
26
  }
28
27
  async onAllotmentReleased() {
29
28
  await this.delayStrategy.onAllotmentReleased();
30
29
  await this.blockingStrategy.onAllotmentReleased();
31
30
  }
31
+ onLimitChanged(oldLimit, newLimit) {
32
+ this.blockingStrategy.onLimitChanged?.(oldLimit, newLimit);
33
+ }
32
34
  }
@@ -1,4 +1,5 @@
1
- import { ArrayWaiterQueue, BlockingBacklogRejection, MAX_TIMEOUT, } from "./BlockingBacklogRejection.js";
1
+ import { LinkedWaiterQueue } from "../../utils/LinkedWaiterQueue.js";
2
+ import { BlockingBacklogRejection, MAX_TIMEOUT, } from "./BlockingBacklogRejection.js";
2
3
  /**
3
4
  * Rejection strategy that blocks the caller in a FIFO queue when the limit
4
5
  * has been reached, waiting for a slot to open up. This strategy favors
@@ -13,7 +14,7 @@ export class FifoBlockingRejection {
13
14
  this.delegate = new BlockingBacklogRejection({
14
15
  backlogSize: options.backlogSize ?? Number.POSITIVE_INFINITY,
15
16
  backlogTimeout: options.backlogTimeout ?? MAX_TIMEOUT,
16
- queue: new ArrayWaiterQueue("back"),
17
+ queue: new LinkedWaiterQueue("back"),
17
18
  });
18
19
  }
19
20
  onAllotmentUnavailable(context, retry, signal) {
@@ -1,4 +1,5 @@
1
- import { ArrayWaiterQueue, BlockingBacklogRejection, } from "./BlockingBacklogRejection.js";
1
+ import { LinkedWaiterQueue } from "../../utils/LinkedWaiterQueue.js";
2
+ import { BlockingBacklogRejection, } from "./BlockingBacklogRejection.js";
2
3
  /**
3
4
  * Rejection strategy that blocks the caller in a LIFO queue when the limit
4
5
  * has been reached. This strategy favors availability over latency by
@@ -11,7 +12,7 @@ export class LifoBlockingRejection {
11
12
  this.delegate = new BlockingBacklogRejection({
12
13
  backlogSize: options.backlogSize ?? 100,
13
14
  backlogTimeout: options.backlogTimeout ?? 1_000,
14
- queue: new ArrayWaiterQueue("front"),
15
+ queue: new LinkedWaiterQueue("front"),
15
16
  });
16
17
  }
17
18
  onAllotmentUnavailable(context, retry, signal) {
@@ -0,0 +1,21 @@
1
+ export type WaiterHandle = {
2
+ key: symbol;
3
+ };
4
+ export type EnqueueDirection = "front" | "back";
5
+ export declare class LinkedWaiterQueue<WaiterT extends {
6
+ handle: WaiterHandle;
7
+ }> {
8
+ private head;
9
+ private tail;
10
+ private readonly nodes;
11
+ private readonly enqueueDirection;
12
+ private length;
13
+ constructor(enqueueDirection: EnqueueDirection);
14
+ enqueue(waiterWithoutHandle: Omit<WaiterT, "handle">, enqueueDirection?: EnqueueDirection): WaiterT;
15
+ peekHead(): WaiterT | undefined;
16
+ removeByHandle(handle: WaiterHandle): boolean;
17
+ size(): number;
18
+ private pushFront;
19
+ private pushBack;
20
+ }
21
+ //# sourceMappingURL=LinkedWaiterQueue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkedWaiterQueue.d.ts","sourceRoot":"","sources":["../../src/utils/LinkedWaiterQueue.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,CAAC;AAShD,qBAAa,iBAAiB,CAAC,OAAO,SAAS;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE;IACrE,OAAO,CAAC,IAAI,CAAkC;IAC9C,OAAO,CAAC,IAAI,CAAkC;IAC9C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0C;IAChE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD,OAAO,CAAC,MAAM,CAAK;gBAEP,gBAAgB,EAAE,gBAAgB;IAI9C,OAAO,CACL,mBAAmB,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC5C,gBAAgB,CAAC,EAAE,gBAAgB,GAClC,OAAO;IAwBV,QAAQ,IAAI,OAAO,GAAG,SAAS;IAI/B,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO;IAuB7C,IAAI,IAAI,MAAM;IAId,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,QAAQ;CAWjB"}
@@ -0,0 +1,81 @@
1
+ export class LinkedWaiterQueue {
2
+ head;
3
+ tail;
4
+ nodes = new Map();
5
+ enqueueDirection;
6
+ length = 0;
7
+ constructor(enqueueDirection) {
8
+ this.enqueueDirection = enqueueDirection;
9
+ }
10
+ enqueue(waiterWithoutHandle, enqueueDirection) {
11
+ const handle = { key: Symbol("waiter-node") };
12
+ const waiter = {
13
+ ...waiterWithoutHandle,
14
+ handle,
15
+ };
16
+ const node = {
17
+ handle,
18
+ value: waiter,
19
+ prev: undefined,
20
+ next: undefined,
21
+ };
22
+ const direction = enqueueDirection ?? this.enqueueDirection;
23
+ this.nodes.set(handle.key, node);
24
+ if (direction === "front") {
25
+ this.pushFront(node);
26
+ }
27
+ else {
28
+ this.pushBack(node);
29
+ }
30
+ this.length += 1;
31
+ return waiter;
32
+ }
33
+ peekHead() {
34
+ return this.head?.value;
35
+ }
36
+ removeByHandle(handle) {
37
+ const node = this.nodes.get(handle.key);
38
+ if (!node)
39
+ return false;
40
+ this.nodes.delete(handle.key);
41
+ if (node.prev) {
42
+ node.prev.next = node.next;
43
+ }
44
+ else {
45
+ this.head = node.next;
46
+ }
47
+ if (node.next) {
48
+ node.next.prev = node.prev;
49
+ }
50
+ else {
51
+ this.tail = node.prev;
52
+ }
53
+ node.prev = undefined;
54
+ node.next = undefined;
55
+ this.length -= 1;
56
+ return true;
57
+ }
58
+ size() {
59
+ return this.length;
60
+ }
61
+ pushFront(node) {
62
+ if (!this.head) {
63
+ this.head = node;
64
+ this.tail = node;
65
+ return;
66
+ }
67
+ node.next = this.head;
68
+ this.head.prev = node;
69
+ this.head = node;
70
+ }
71
+ pushBack(node) {
72
+ if (!this.tail) {
73
+ this.head = node;
74
+ this.tail = node;
75
+ return;
76
+ }
77
+ node.prev = this.tail;
78
+ this.tail.next = node;
79
+ this.tail = node;
80
+ }
81
+ }
@@ -7,4 +7,5 @@ export declare function squareRoot(n: number): number;
7
7
  * Create a function that returns: max(baseline, squareRoot(n))
8
8
  */
9
9
  export declare function squareRootWithBaseline(baseline: number): (n: number) => number;
10
+ export { LinkedWaiterQueue, type EnqueueDirection, type WaiterHandle, } from "./LinkedWaiterQueue.js";
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAE9E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAE9E;AAED,OAAO,EACL,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,YAAY,GAClB,MAAM,wBAAwB,CAAC"}
@@ -17,3 +17,4 @@ export function squareRoot(n) {
17
17
  export function squareRootWithBaseline(baseline) {
18
18
  return (n) => Math.max(baseline, squareRoot(n));
19
19
  }
20
+ export { LinkedWaiterQueue, } from "./LinkedWaiterQueue.js";
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "dynamic rate limiting"
10
10
  ],
11
11
  "author": "Ethan Resnick <ethan.resnick@gmail.com>",
12
- "version": "0.3.3",
12
+ "version": "0.3.4",
13
13
  "type": "module",
14
14
  "exports": {
15
15
  ".": {
@@ -29,6 +29,6 @@
29
29
  "tsx": "^4.19.0",
30
30
  "type-fest": "^5.5.0",
31
31
  "type-party": "^0.7.3",
32
- "typescript": "next"
32
+ "typescript": "^6.0.2"
33
33
  }
34
34
  }