adaptive-concurrency 0.4.0 → 0.6.0

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.
@@ -1,18 +1,20 @@
1
1
  import type { LimitAllotment } from "../../LimitAllotment.js";
2
2
  import type { AcquireResult, AllotmentUnavailableStrategy } from "../../Limiter.js";
3
+ import type { EnqueueOptions } from "../../utils/LinkedWaiterQueue.js";
3
4
  export type Waiter<ContextT> = {
4
5
  context: ContextT;
5
6
  retry: (context: ContextT) => AcquireResult;
6
7
  resolve: (allotment: LimitAllotment | undefined) => void;
7
8
  };
8
9
  export declare const MAX_TIMEOUT: number;
9
- export type BlockingBacklogRejectionOptions<ContextT, Handle> = {
10
+ export type BlockingBacklogRejectionOptions<ContextT, Handle, EnqueueOptionsT = EnqueueOptions> = {
10
11
  backlogSize: number;
11
12
  backlogTimeout: number | ((context: ContextT) => number);
12
- queue: WaiterQueue<ContextT, Handle>;
13
+ queue: WaiterQueue<ContextT, Handle, EnqueueOptionsT>;
14
+ enqueueOptions: EnqueueOptionsT | ((context: ContextT) => EnqueueOptionsT);
13
15
  };
14
- export type WaiterQueue<ContextT, Handle> = {
15
- enqueue: (waiter: Waiter<ContextT>) => {
16
+ export type WaiterQueue<ContextT, Handle, EnqueueOptionsT = EnqueueOptions> = {
17
+ enqueue: (waiter: Waiter<ContextT>, options: EnqueueOptionsT) => {
16
18
  value: Waiter<ContextT>;
17
19
  handle: Handle;
18
20
  };
@@ -23,13 +25,14 @@ export type WaiterQueue<ContextT, Handle> = {
23
25
  removeByHandle: (handle: Handle) => boolean;
24
26
  size: () => number;
25
27
  };
26
- export declare class BlockingBacklogRejection<ContextT, Handle> implements AllotmentUnavailableStrategy<ContextT> {
28
+ export declare class BlockingBacklogRejection<ContextT, Handle, EnqueueOptionsT = EnqueueOptions> implements AllotmentUnavailableStrategy<ContextT> {
27
29
  private readonly backlogSize;
28
30
  private readonly getBacklogTimeout;
31
+ private readonly getEnqueueOptions;
29
32
  private readonly queue;
30
33
  private drainInProgress;
31
34
  private releaseDuringDrain;
32
- constructor(options: BlockingBacklogRejectionOptions<ContextT, Handle>);
35
+ constructor(options: BlockingBacklogRejectionOptions<ContextT, Handle, EnqueueOptionsT>);
33
36
  onAllotmentUnavailable(context: ContextT, retry: (context: ContextT) => AcquireResult, signal?: AbortSignal): Promise<LimitAllotment | undefined>;
34
37
  onAllotmentReleased(): Promise<void>;
35
38
  onLimitChanged(oldLimit: number, newLimit: number): void;
@@ -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,MAAM,MAAM,MAAM,CAAC,QAAQ,IAAI;IAC7B,OAAO,EAAE,QAAQ,CAAC;IAClB,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,CAAC;IAC5C,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,EAAE,MAAM,IAAI;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC;IACzD,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,QAAQ,EAAE,MAAM,IAAI;IAC1C,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK;QACrC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,QAAQ,EAAE,MAAM;QAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACxE,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,IAAI,EAAE,MAAM,MAAM,CAAC;CACpB,CAAC;AAEF,qBAAa,wBAAwB,CACnC,QAAQ,EACR,MAAM,CACN,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,EAAE,MAAM,CAAC;IA6BtE,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;IA6C1C,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQxD,OAAO,CAAC,aAAa;IAkCrB,OAAO,CAAC,yBAAyB;CAUlC"}
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,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAEvE,MAAM,MAAM,MAAM,CAAC,QAAQ,IAAI;IAC7B,OAAO,EAAE,QAAQ,CAAC;IAClB,KAAK,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,CAAC;IAC5C,OAAO,EAAE,CAAC,SAAS,EAAE,cAAc,GAAG,SAAS,KAAK,IAAI,CAAC;CAC1D,CAAC;AAEF,eAAO,MAAM,WAAW,QAAiB,CAAC;AAE1C,MAAM,MAAM,+BAA+B,CACzC,QAAQ,EACR,MAAM,EACN,eAAe,GAAG,cAAc,IAC9B;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC;IACzD,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;IACtD,cAAc,EAAE,eAAe,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,eAAe,CAAC,CAAC;CAC5E,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,GAAG,cAAc,IAAI;IAC5E,OAAO,EAAE,CACP,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,EACxB,OAAO,EAAE,eAAe,KACrB;QAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,QAAQ,EAAE,MAAM;QAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACxE,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,IAAI,EAAE,MAAM,MAAM,CAAC;CACpB,CAAC;AAEF,qBAAa,wBAAwB,CACnC,QAAQ,EACR,MAAM,EACN,eAAe,GAAG,cAAc,CAChC,YAAW,4BAA4B,CAAC,QAAQ,CAAC;IACjD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgC;IAClE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAyC;IAC3E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiD;IACvE,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,kBAAkB,CAAS;gBAGjC,OAAO,EAAE,+BAA+B,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC;IAiC7E,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;IA6C1C,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQxD,OAAO,CAAC,aAAa;IAoCrB,OAAO,CAAC,yBAAyB;CAUlC"}
@@ -2,28 +2,36 @@ export const MAX_TIMEOUT = 60 * 60 * 1000; // 1 hour
2
2
  export class BlockingBacklogRejection {
3
3
  backlogSize;
4
4
  getBacklogTimeout;
5
+ getEnqueueOptions;
5
6
  queue;
6
7
  drainInProgress = false;
7
8
  releaseDuringDrain = false;
8
9
  constructor(options) {
9
10
  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");
11
+ if (Number.isNaN(backlogSize) || backlogSize < 0) {
12
+ throw new RangeError("backlogSize must be greater than or equal to 0");
13
13
  }
14
14
  this.backlogSize = backlogSize;
15
15
  this.queue = options.queue;
16
16
  const backlogTimeout = options.backlogTimeout;
17
- if (typeof backlogTimeout === "number") {
18
- this.assertTimeoutWithinBounds(backlogTimeout);
19
- this.getBacklogTimeout = () => backlogTimeout;
20
- return;
17
+ const enqueueOptions = options.enqueueOptions;
18
+ this.getBacklogTimeout = (() => {
19
+ if (typeof backlogTimeout === "number") {
20
+ this.assertTimeoutWithinBounds(backlogTimeout);
21
+ return () => backlogTimeout;
22
+ }
23
+ return (context) => {
24
+ const contextTimeout = backlogTimeout(context);
25
+ this.assertTimeoutWithinBounds(contextTimeout);
26
+ return contextTimeout;
27
+ };
28
+ })();
29
+ if (typeof enqueueOptions === "function") {
30
+ this.getEnqueueOptions = enqueueOptions;
31
+ }
32
+ else {
33
+ this.getEnqueueOptions = () => enqueueOptions;
21
34
  }
22
- this.getBacklogTimeout = (context) => {
23
- const contextTimeout = backlogTimeout(context);
24
- this.assertTimeoutWithinBounds(contextTimeout);
25
- return contextTimeout;
26
- };
27
35
  }
28
36
  onAllotmentUnavailable(context, retry, signal) {
29
37
  if (signal?.aborted) {
@@ -97,7 +105,8 @@ export class BlockingBacklogRejection {
97
105
  retry,
98
106
  resolve: (allotment) => settle(allotment),
99
107
  };
100
- const { handle } = this.queue.enqueue(waiter);
108
+ const enqueueOptions = this.getEnqueueOptions(context);
109
+ const { handle } = this.queue.enqueue(waiter, enqueueOptions);
101
110
  const timer = setTimeout(() => settle(undefined), timeout);
102
111
  const onAbort = () => settle(undefined);
103
112
  const cleanup = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"makeBlockingLimiter.d.ts","sourceRoot":"","sources":["../../../src/limiter/factories/makeBlockingLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAQhE,wBAAgB,mBAAmB,CAAC,QAAQ,GAAG,IAAI,EACjD,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC;IAC1D,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,8BAA8B,CAAC,CAAC;CACrE,GACL,OAAO,CAAC,QAAQ,CAAC,CASnB"}
1
+ {"version":3,"file":"makeBlockingLimiter.d.ts","sourceRoot":"","sources":["../../../src/limiter/factories/makeBlockingLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAQhE,wBAAgB,mBAAmB,CAAC,QAAQ,GAAG,IAAI,EACjD,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC;IAC1D,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,8BAA8B,CAAC,CAAC;CACrE,GACL,OAAO,CAAC,QAAQ,CAAC,CAUnB"}
@@ -7,7 +7,8 @@ export function makeBlockingLimiter(options = {}) {
7
7
  allotmentUnavailableStrategy: new BlockingBacklogRejection({
8
8
  backlogSize: options.backlogSize ?? Number.POSITIVE_INFINITY,
9
9
  backlogTimeout: options.backlogTimeout ?? MAX_TIMEOUT,
10
- queue: new LinkedWaiterQueue("back"),
10
+ enqueueOptions: { direction: "back" },
11
+ queue: new LinkedWaiterQueue(),
11
12
  }),
12
13
  });
13
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"makeLifoBlockingLimiter.d.ts","sourceRoot":"","sources":["../../../src/limiter/factories/makeLifoBlockingLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOhE,wBAAgB,uBAAuB,CAAC,QAAQ,GAAG,IAAI,EACrD,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC;IAC1D,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,8BAA8B,CAAC,CAAC;CACrE,GACL,OAAO,CAAC,QAAQ,CAAC,CASnB"}
1
+ {"version":3,"file":"makeLifoBlockingLimiter.d.ts","sourceRoot":"","sources":["../../../src/limiter/factories/makeLifoBlockingLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOhE,wBAAgB,uBAAuB,CAAC,QAAQ,GAAG,IAAI,EACrD,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC;IAC1D,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,8BAA8B,CAAC,CAAC;CACrE,GACL,OAAO,CAAC,QAAQ,CAAC,CAUnB"}
@@ -7,7 +7,8 @@ export function makeLifoBlockingLimiter(options = {}) {
7
7
  allotmentUnavailableStrategy: new BlockingBacklogRejection({
8
8
  backlogSize: options.backlogSize ?? 100,
9
9
  backlogTimeout: options.backlogTimeout ?? 1_000,
10
- queue: new LinkedWaiterQueue("front"),
10
+ enqueueOptions: { direction: "front" },
11
+ queue: new LinkedWaiterQueue(),
11
12
  }),
12
13
  });
13
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"makePartitionedBlockingLimiter.d.ts","sourceRoot":"","sources":["../../../src/limiter/factories/makePartitionedBlockingLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEhE,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,8CAA8C,CAAC;AAStD,wBAAgB,8BAA8B,CAC5C,QAAQ,EACR,aAAa,SAAS,MAAM,GAAG,MAAM,EACrC,OAAO,EAAE;IACT,iBAAiB,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,GAAG,SAAS,CAAC;IACpE,UAAU,EAAE,MAAM,CAAC,aAAa,EAAE,eAAe,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1E,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAC5D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC;CAC3D,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkCpB"}
1
+ {"version":3,"file":"makePartitionedBlockingLimiter.d.ts","sourceRoot":"","sources":["../../../src/limiter/factories/makePartitionedBlockingLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEhE,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,8CAA8C,CAAC;AAStD,wBAAgB,8BAA8B,CAC5C,QAAQ,EACR,aAAa,SAAS,MAAM,GAAG,MAAM,EACrC,OAAO,EAAE;IACT,iBAAiB,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,GAAG,SAAS,CAAC;IACpE,UAAU,EAAE,MAAM,CAAC,aAAa,EAAE,eAAe,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1E,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAC5D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC;CAC3D,GAAG,OAAO,CAAC,QAAQ,CAAC,CAmCpB"}
@@ -32,7 +32,8 @@ export function makePartitionedBlockingLimiter(options) {
32
32
  blockingStrategy: new BlockingBacklogRejection({
33
33
  backlogSize: options.backlogSize ?? Number.POSITIVE_INFINITY,
34
34
  backlogTimeout: options.backlogTimeout ?? MAX_TIMEOUT,
35
- queue: new LinkedWaiterQueue("back"),
35
+ enqueueOptions: { direction: "back" },
36
+ queue: new LinkedWaiterQueue(),
36
37
  }),
37
38
  }),
38
39
  });
@@ -1 +1 @@
1
- {"version":3,"file":"makePartitionedLifoBlockingLimiter.d.ts","sourceRoot":"","sources":["../../../src/limiter/factories/makePartitionedLifoBlockingLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEhE,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,8CAA8C,CAAC;AAQtD,wBAAgB,kCAAkC,CAChD,QAAQ,EACR,aAAa,SAAS,MAAM,GAAG,MAAM,EACrC,OAAO,EAAE;IACT,iBAAiB,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,GAAG,SAAS,CAAC;IACpE,UAAU,EAAE,MAAM,CAAC,aAAa,EAAE,eAAe,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1E,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAC5D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC;CAC3D,GAAG,OAAO,CAAC,QAAQ,CAAC,CAmCpB"}
1
+ {"version":3,"file":"makePartitionedLifoBlockingLimiter.d.ts","sourceRoot":"","sources":["../../../src/limiter/factories/makePartitionedLifoBlockingLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEhE,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,8CAA8C,CAAC;AAQtD,wBAAgB,kCAAkC,CAChD,QAAQ,EACR,aAAa,SAAS,MAAM,GAAG,MAAM,EACrC,OAAO,EAAE;IACT,iBAAiB,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,GAAG,SAAS,CAAC;IACpE,UAAU,EAAE,MAAM,CAAC,aAAa,EAAE,eAAe,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1E,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAC5D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC;CAC3D,GAAG,OAAO,CAAC,QAAQ,CAAC,CAoCpB"}
@@ -32,7 +32,8 @@ export function makePartitionedLifoBlockingLimiter(options) {
32
32
  blockingStrategy: new BlockingBacklogRejection({
33
33
  backlogSize: options.backlogSize ?? 100,
34
34
  backlogTimeout: options.backlogTimeout ?? 1_000,
35
- queue: new LinkedWaiterQueue("front"),
35
+ enqueueOptions: { direction: "front" },
36
+ queue: new LinkedWaiterQueue(),
36
37
  }),
37
38
  }),
38
39
  });
@@ -1,14 +1,16 @@
1
1
  declare class ItemHandle {
2
2
  }
3
3
  export type EnqueueDirection = "front" | "back";
4
+ export type EnqueueOptions = {
5
+ direction: EnqueueDirection;
6
+ priority?: number | undefined;
7
+ };
4
8
  export declare class LinkedWaiterQueue<T extends object> {
5
- private head;
6
- private tail;
9
+ private readonly buckets;
7
10
  private readonly nodes;
8
- private readonly enqueueDirection;
11
+ private maxPriority;
9
12
  private length;
10
- constructor(enqueueDirection: EnqueueDirection);
11
- enqueue(value: T, enqueueDirection?: EnqueueDirection): {
13
+ enqueue(value: T, options: EnqueueOptions): {
12
14
  value: T;
13
15
  handle: ItemHandle;
14
16
  };
@@ -18,8 +20,9 @@ export declare class LinkedWaiterQueue<T extends object> {
18
20
  } | undefined;
19
21
  removeByHandle(handle: ItemHandle): boolean;
20
22
  size(): number;
21
- private pushFront;
22
- private pushBack;
23
+ private getOrCreateBucket;
24
+ private insertInBucket;
25
+ private unlinkFromBucket;
23
26
  }
24
27
  export {};
25
28
  //# sourceMappingURL=LinkedWaiterQueue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LinkedWaiterQueue.d.ts","sourceRoot":"","sources":["../../src/utils/LinkedWaiterQueue.ts"],"names":[],"mappings":"AAAA,cAAM,UAAU;CAAG;AAEnB,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,CAAC;AAShD,qBAAa,iBAAiB,CAAC,CAAC,SAAS,MAAM;IAC7C,OAAO,CAAC,IAAI,CAA4B;IACxC,OAAO,CAAC,IAAI,CAA4B;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwC;IAC9D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD,OAAO,CAAC,MAAM,CAAK;gBAEP,gBAAgB,EAAE,gBAAgB;IAI9C,OAAO,CACL,KAAK,EAAE,CAAC,EACR,gBAAgB,CAAC,EAAE,gBAAgB,GAClC;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE;IAqBnC,QAAQ,IAAI;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,GAAG,SAAS;IAUxD,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO;IAuB3C,IAAI,IAAI,MAAM;IAId,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,QAAQ;CAWjB"}
1
+ {"version":3,"file":"LinkedWaiterQueue.d.ts","sourceRoot":"","sources":["../../src/utils/LinkedWaiterQueue.ts"],"names":[],"mappings":"AAAA,cAAM,UAAU;CAAG;AAEnB,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,CAAC;AAChD,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B,CAAC;AAkBF,qBAAa,iBAAiB,CAAC,CAAC,SAAS,MAAM;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwC;IAChE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwC;IAC9D,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,MAAM,CAAK;IAEnB,OAAO,CACL,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,cAAc,GACtB;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE;IA0BnC,QAAQ,IAAI;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,GAAG,SAAS;IAcxD,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO;IAa3C,IAAI,IAAI,MAAM;IAId,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,cAAc;IAwBtB,OAAO,CAAC,gBAAgB;CA+BzB"}
@@ -1,40 +1,44 @@
1
1
  class ItemHandle {
2
2
  }
3
3
  export class LinkedWaiterQueue {
4
- head;
5
- tail;
4
+ buckets = new Map();
6
5
  nodes = new Map();
7
- enqueueDirection;
6
+ maxPriority;
8
7
  length = 0;
9
- constructor(enqueueDirection) {
10
- this.enqueueDirection = enqueueDirection;
11
- }
12
- enqueue(value, enqueueDirection) {
8
+ enqueue(value, options) {
13
9
  const handle = new ItemHandle();
10
+ const priority = options.priority ?? 0;
11
+ if (!Number.isFinite(priority)) {
12
+ throw new RangeError("priority must be a finite number");
13
+ }
14
+ const bucket = this.getOrCreateBucket(priority);
14
15
  const node = {
15
16
  handle,
16
17
  value: value,
18
+ priority,
17
19
  prev: undefined,
18
20
  next: undefined,
21
+ bucket,
19
22
  };
20
- const direction = enqueueDirection ?? this.enqueueDirection;
21
23
  this.nodes.set(handle, node);
22
- if (direction === "front") {
23
- this.pushFront(node);
24
- }
25
- else {
26
- this.pushBack(node);
24
+ this.insertInBucket(node, options.direction);
25
+ if (this.maxPriority === undefined || priority > this.maxPriority) {
26
+ this.maxPriority = priority;
27
27
  }
28
28
  this.length += 1;
29
29
  return { value, handle };
30
30
  }
31
31
  peekHead() {
32
- if (!this.head) {
32
+ if (this.maxPriority === undefined) {
33
+ return undefined;
34
+ }
35
+ const bucket = this.buckets.get(this.maxPriority);
36
+ if (!bucket || !bucket.head) {
33
37
  return undefined;
34
38
  }
35
39
  return {
36
- value: this.head.value,
37
- handle: this.head.handle,
40
+ value: bucket.head.value,
41
+ handle: bucket.head.handle,
38
42
  };
39
43
  }
40
44
  removeByHandle(handle) {
@@ -42,44 +46,83 @@ export class LinkedWaiterQueue {
42
46
  if (!node)
43
47
  return false;
44
48
  this.nodes.delete(handle);
49
+ this.unlinkFromBucket(node);
50
+ node.prev = undefined;
51
+ node.next = undefined;
52
+ this.length -= 1;
53
+ return true;
54
+ }
55
+ size() {
56
+ return this.length;
57
+ }
58
+ getOrCreateBucket(priority) {
59
+ const existing = this.buckets.get(priority);
60
+ if (existing) {
61
+ return existing;
62
+ }
63
+ const created = {
64
+ priority,
65
+ head: undefined,
66
+ tail: undefined,
67
+ size: 0,
68
+ };
69
+ this.buckets.set(priority, created);
70
+ return created;
71
+ }
72
+ insertInBucket(node, direction) {
73
+ const bucket = node.bucket;
74
+ if (direction === "front") {
75
+ if (!bucket.head) {
76
+ bucket.head = node;
77
+ bucket.tail = node;
78
+ }
79
+ else {
80
+ node.next = bucket.head;
81
+ bucket.head.prev = node;
82
+ bucket.head = node;
83
+ }
84
+ }
85
+ else {
86
+ if (!bucket.tail) {
87
+ bucket.head = node;
88
+ bucket.tail = node;
89
+ }
90
+ else {
91
+ node.prev = bucket.tail;
92
+ bucket.tail.next = node;
93
+ bucket.tail = node;
94
+ }
95
+ }
96
+ bucket.size += 1;
97
+ }
98
+ unlinkFromBucket(node) {
99
+ const bucket = node.bucket;
45
100
  if (node.prev) {
46
101
  node.prev.next = node.next;
47
102
  }
48
103
  else {
49
- this.head = node.next;
104
+ bucket.head = node.next;
50
105
  }
51
106
  if (node.next) {
52
107
  node.next.prev = node.prev;
53
108
  }
54
109
  else {
55
- this.tail = node.prev;
110
+ bucket.tail = node.prev;
56
111
  }
57
- node.prev = undefined;
58
- node.next = undefined;
59
- this.length -= 1;
60
- return true;
61
- }
62
- size() {
63
- return this.length;
64
- }
65
- pushFront(node) {
66
- if (!this.head) {
67
- this.head = node;
68
- this.tail = node;
112
+ bucket.size -= 1;
113
+ if (bucket.size > 0) {
69
114
  return;
70
115
  }
71
- node.next = this.head;
72
- this.head.prev = node;
73
- this.head = node;
74
- }
75
- pushBack(node) {
76
- if (!this.tail) {
77
- this.head = node;
78
- this.tail = node;
116
+ this.buckets.delete(bucket.priority);
117
+ if (this.maxPriority !== bucket.priority) {
79
118
  return;
80
119
  }
81
- node.prev = this.tail;
82
- this.tail.next = node;
83
- this.tail = node;
120
+ let newMax;
121
+ for (const priority of this.buckets.keys()) {
122
+ if (newMax === undefined || priority > newMax) {
123
+ newMax = priority;
124
+ }
125
+ }
126
+ this.maxPriority = newMax;
84
127
  }
85
128
  }
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.4.0",
12
+ "version": "0.6.0",
13
13
  "type": "module",
14
14
  "exports": {
15
15
  ".": {
@@ -20,15 +20,14 @@
20
20
  "files": [
21
21
  "dist"
22
22
  ],
23
- "scripts": {
24
- "build": "tsc",
25
- "test": "node --import tsx --test \"src/**/*.test.ts\"",
26
- "prepublishOnly": "pnpm build"
27
- },
28
23
  "devDependencies": {
29
24
  "tsx": "^4.19.0",
30
25
  "type-fest": "^5.5.0",
31
26
  "type-party": "^0.7.3",
32
27
  "typescript": "^6.0.2"
28
+ },
29
+ "scripts": {
30
+ "build": "tsc",
31
+ "test": "node --import tsx --test \"src/**/*.test.ts\""
33
32
  }
34
- }
33
+ }