adaptive-concurrency 0.1.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.
- package/dist/Limit.d.ts +29 -0
- package/dist/Limit.d.ts.map +1 -0
- package/dist/Limit.js +1 -0
- package/dist/LimitAllotment.d.ts +23 -0
- package/dist/LimitAllotment.d.ts.map +1 -0
- package/dist/LimitAllotment.js +1 -0
- package/dist/Limiter.d.ts +175 -0
- package/dist/Limiter.d.ts.map +1 -0
- package/dist/Limiter.js +240 -0
- package/dist/Listener.d.ts +23 -0
- package/dist/Listener.d.ts.map +1 -0
- package/dist/Listener.js +1 -0
- package/dist/ListenerSet.d.ts +12 -0
- package/dist/ListenerSet.d.ts.map +1 -0
- package/dist/ListenerSet.js +35 -0
- package/dist/MetricIds.d.ts +13 -0
- package/dist/MetricIds.d.ts.map +1 -0
- package/dist/MetricIds.js +12 -0
- package/dist/MetricRegistry.d.ts +66 -0
- package/dist/MetricRegistry.d.ts.map +1 -0
- package/dist/MetricRegistry.js +30 -0
- package/dist/RunResult.d.ts +33 -0
- package/dist/RunResult.d.ts.map +1 -0
- package/dist/RunResult.js +35 -0
- package/dist/StreamingLimit.d.ts +26 -0
- package/dist/StreamingLimit.d.ts.map +1 -0
- package/dist/StreamingLimit.js +1 -0
- package/dist/executors/AdaptiveExecutor.d.ts +50 -0
- package/dist/executors/AdaptiveExecutor.d.ts.map +1 -0
- package/dist/executors/AdaptiveExecutor.js +80 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/limit/AIMDLimit.d.ts +37 -0
- package/dist/limit/AIMDLimit.d.ts.map +1 -0
- package/dist/limit/AIMDLimit.js +49 -0
- package/dist/limit/FixedLimit.d.ts +15 -0
- package/dist/limit/FixedLimit.d.ts.map +1 -0
- package/dist/limit/FixedLimit.js +23 -0
- package/dist/limit/Gradient2Limit.d.ts +122 -0
- package/dist/limit/Gradient2Limit.d.ts.map +1 -0
- package/dist/limit/Gradient2Limit.js +107 -0
- package/dist/limit/GradientLimit.d.ts +122 -0
- package/dist/limit/GradientLimit.d.ts.map +1 -0
- package/dist/limit/GradientLimit.js +108 -0
- package/dist/limit/SettableLimit.d.ts +18 -0
- package/dist/limit/SettableLimit.d.ts.map +1 -0
- package/dist/limit/SettableLimit.js +30 -0
- package/dist/limit/StreamingLimit.d.ts +26 -0
- package/dist/limit/StreamingLimit.d.ts.map +1 -0
- package/dist/limit/StreamingLimit.js +1 -0
- package/dist/limit/TracingLimitDecorator.d.ts +16 -0
- package/dist/limit/TracingLimitDecorator.d.ts.map +1 -0
- package/dist/limit/TracingLimitDecorator.js +23 -0
- package/dist/limit/VegasLimit.d.ts +85 -0
- package/dist/limit/VegasLimit.d.ts.map +1 -0
- package/dist/limit/VegasLimit.js +127 -0
- package/dist/limit/WindowedLimit.d.ts +48 -0
- package/dist/limit/WindowedLimit.d.ts.map +1 -0
- package/dist/limit/WindowedLimit.js +67 -0
- package/dist/limit/statistics/ExpMovingAverage.d.ts +21 -0
- package/dist/limit/statistics/ExpMovingAverage.d.ts.map +1 -0
- package/dist/limit/statistics/ExpMovingAverage.js +43 -0
- package/dist/limit/statistics/Minimum.d.ts +12 -0
- package/dist/limit/statistics/Minimum.d.ts.map +1 -0
- package/dist/limit/statistics/Minimum.js +22 -0
- package/dist/limit/statistics/MinimumValue.d.ts +12 -0
- package/dist/limit/statistics/MinimumValue.d.ts.map +1 -0
- package/dist/limit/statistics/MinimumValue.js +22 -0
- package/dist/limit/statistics/SingleMeasurement.d.ts +12 -0
- package/dist/limit/statistics/SingleMeasurement.d.ts.map +1 -0
- package/dist/limit/statistics/SingleMeasurement.js +21 -0
- package/dist/limit/statistics/StreamingStatistic.d.ts +29 -0
- package/dist/limit/statistics/StreamingStatistic.d.ts.map +1 -0
- package/dist/limit/statistics/StreamingStatistic.js +1 -0
- package/dist/limit/utils/index.d.ts +10 -0
- package/dist/limit/utils/index.d.ts.map +1 -0
- package/dist/limit/utils/index.js +19 -0
- package/dist/limit/window/AverageSampleWindow.d.ts +4 -0
- package/dist/limit/window/AverageSampleWindow.d.ts.map +1 -0
- package/dist/limit/window/AverageSampleWindow.js +46 -0
- package/dist/limit/window/PercentileSampleWindow.d.ts +38 -0
- package/dist/limit/window/PercentileSampleWindow.d.ts.map +1 -0
- package/dist/limit/window/PercentileSampleWindow.js +81 -0
- package/dist/limit/window/SampleWindow.d.ts +30 -0
- package/dist/limit/window/SampleWindow.d.ts.map +1 -0
- package/dist/limit/window/SampleWindow.js +1 -0
- package/dist/limiter/AbstractLimiter.d.ts +48 -0
- package/dist/limiter/AbstractLimiter.d.ts.map +1 -0
- package/dist/limiter/AbstractLimiter.js +78 -0
- package/dist/limiter/AbstractPartitionedLimiter.d.ts +66 -0
- package/dist/limiter/AbstractPartitionedLimiter.d.ts.map +1 -0
- package/dist/limiter/AbstractPartitionedLimiter.js +209 -0
- package/dist/limiter/BlockingLimiter.d.ts +55 -0
- package/dist/limiter/BlockingLimiter.d.ts.map +1 -0
- package/dist/limiter/BlockingLimiter.js +111 -0
- package/dist/limiter/DelayedRejectStrategy.d.ts +32 -0
- package/dist/limiter/DelayedRejectStrategy.d.ts.map +1 -0
- package/dist/limiter/DelayedRejectStrategy.js +60 -0
- package/dist/limiter/DelayedThenBlockingRejection.d.ts +19 -0
- package/dist/limiter/DelayedThenBlockingRejection.d.ts.map +1 -0
- package/dist/limiter/DelayedThenBlockingRejection.js +26 -0
- package/dist/limiter/FifoBlockingRejection.d.ts +26 -0
- package/dist/limiter/FifoBlockingRejection.d.ts.map +1 -0
- package/dist/limiter/FifoBlockingRejection.js +77 -0
- package/dist/limiter/LifoBlockingLimiter.d.ts +53 -0
- package/dist/limiter/LifoBlockingLimiter.d.ts.map +1 -0
- package/dist/limiter/LifoBlockingLimiter.js +108 -0
- package/dist/limiter/LifoBlockingRejection.d.ts +31 -0
- package/dist/limiter/LifoBlockingRejection.d.ts.map +1 -0
- package/dist/limiter/LifoBlockingRejection.js +63 -0
- package/dist/limiter/PartitionedStrategy.d.ts +90 -0
- package/dist/limiter/PartitionedStrategy.d.ts.map +1 -0
- package/dist/limiter/PartitionedStrategy.js +183 -0
- package/dist/limiter/SimpleLimiter.d.ts +31 -0
- package/dist/limiter/SimpleLimiter.d.ts.map +1 -0
- package/dist/limiter/SimpleLimiter.js +119 -0
- package/dist/limiter/factories/index.d.ts +7 -0
- package/dist/limiter/factories/index.d.ts.map +1 -0
- package/dist/limiter/factories/index.js +6 -0
- package/dist/limiter/factories/makeBlockingLimiter.d.ts +6 -0
- package/dist/limiter/factories/makeBlockingLimiter.d.ts.map +1 -0
- package/dist/limiter/factories/makeBlockingLimiter.js +8 -0
- package/dist/limiter/factories/makeLifoBlockingLimiter.d.ts +8 -0
- package/dist/limiter/factories/makeLifoBlockingLimiter.d.ts.map +1 -0
- package/dist/limiter/factories/makeLifoBlockingLimiter.js +15 -0
- package/dist/limiter/factories/makePartitionedBlockingLimiter.d.ts +12 -0
- package/dist/limiter/factories/makePartitionedBlockingLimiter.d.ts.map +1 -0
- package/dist/limiter/factories/makePartitionedBlockingLimiter.js +35 -0
- package/dist/limiter/factories/makePartitionedLifoBlockingLimiter.d.ts +14 -0
- package/dist/limiter/factories/makePartitionedLifoBlockingLimiter.d.ts.map +1 -0
- package/dist/limiter/factories/makePartitionedLifoBlockingLimiter.js +38 -0
- package/dist/limiter/factories/makePartitionedLimiter.d.ts +11 -0
- package/dist/limiter/factories/makePartitionedLimiter.d.ts.map +1 -0
- package/dist/limiter/factories/makePartitionedLimiter.js +30 -0
- package/dist/limiter/factories/makeSimpleLimiter.d.ts +3 -0
- package/dist/limiter/factories/makeSimpleLimiter.d.ts.map +1 -0
- package/dist/limiter/factories/makeSimpleLimiter.js +9 -0
- package/dist/limiter/factories.d.ts +31 -0
- package/dist/limiter/factories.d.ts.map +1 -0
- package/dist/limiter/factories.js +74 -0
- package/dist/statistics/ExpMovingAverage.d.ts +21 -0
- package/dist/statistics/ExpMovingAverage.d.ts.map +1 -0
- package/dist/statistics/ExpMovingAverage.js +43 -0
- package/dist/statistics/MinimumValue.d.ts +12 -0
- package/dist/statistics/MinimumValue.d.ts.map +1 -0
- package/dist/statistics/MinimumValue.js +22 -0
- package/dist/statistics/MostRecentValue.d.ts +12 -0
- package/dist/statistics/MostRecentValue.d.ts.map +1 -0
- package/dist/statistics/MostRecentValue.js +21 -0
- package/dist/statistics/StreamingStatistic.d.ts +29 -0
- package/dist/statistics/StreamingStatistic.d.ts.map +1 -0
- package/dist/statistics/StreamingStatistic.js +1 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +19 -0
- package/package.json +31 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Limiter, } from "../../Limiter.js";
|
|
2
|
+
import { PartitionedStrategy, } from "../PartitionedStrategy.js";
|
|
3
|
+
import { DelayedRejectStrategy } from "../DelayedRejectStrategy.js";
|
|
4
|
+
export function makePartitionedLimiter(options) {
|
|
5
|
+
const limit = options.limiter?.limit ?? Limiter.makeDefaultLimit();
|
|
6
|
+
const delayByPartition = new Map(Object.entries(options.partitions).map(([name, cfg]) => [name, cfg.delayMs ?? 0]));
|
|
7
|
+
const partitionsWithoutDelay = Object.fromEntries(Object.entries(options.partitions).map(([name, cfg]) => [name, { percent: cfg.percent }]));
|
|
8
|
+
return new Limiter({
|
|
9
|
+
...options.limiter,
|
|
10
|
+
limit,
|
|
11
|
+
acquireStrategy: new PartitionedStrategy({
|
|
12
|
+
partitionResolver: options.partitionResolver,
|
|
13
|
+
partitions: partitionsWithoutDelay,
|
|
14
|
+
initialLimit: limit.currentLimit,
|
|
15
|
+
metricRegistry: options.limiter?.metricRegistry,
|
|
16
|
+
}),
|
|
17
|
+
allotmentUnavailableStrategy: new DelayedRejectStrategy({
|
|
18
|
+
delayMsForContext: (context) => {
|
|
19
|
+
const partition = options.partitionResolver(context);
|
|
20
|
+
if (partition === undefined) {
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
return delayByPartition.get(partition) ?? 0;
|
|
24
|
+
},
|
|
25
|
+
...(options.maxConcurrentDelays === undefined
|
|
26
|
+
? {}
|
|
27
|
+
: { maxConcurrentDelays: options.maxConcurrentDelays }),
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Limiter, type LimiterOptions, type SyncAcquireResult } from "../../Limiter.js";
|
|
2
|
+
export declare function makeSimpleLimiter<ContextT = void>(options?: Omit<LimiterOptions<ContextT, SyncAcquireResult>, "acquireStrategy">): Limiter<ContextT, SyncAcquireResult>;
|
|
3
|
+
//# sourceMappingURL=makeSimpleLimiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"makeSimpleLimiter.d.ts","sourceRoot":"","sources":["../../../src/limiter/factories/makeSimpleLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EAEP,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAC;AAE1B,wBAAgB,iBAAiB,CAAC,QAAQ,GAAG,IAAI,EAC/C,OAAO,GAAE,IAAI,CACX,cAAc,CAAC,QAAQ,EAAE,iBAAiB,CAAC,EAC3C,iBAAiB,CACb,GACL,OAAO,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAOtC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Limiter, SemaphoreStrategy, } from "../../Limiter.js";
|
|
2
|
+
export function makeSimpleLimiter(options = {}) {
|
|
3
|
+
const limit = options.limit ?? Limiter.makeDefaultLimit();
|
|
4
|
+
return new Limiter({
|
|
5
|
+
...options,
|
|
6
|
+
limit,
|
|
7
|
+
acquireStrategy: new SemaphoreStrategy(limit.currentLimit),
|
|
8
|
+
});
|
|
9
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Limiter, type AsyncAcquireResult, type LimiterOptions, type SyncAcquireResult } from "../Limiter.js";
|
|
2
|
+
import { type LifoBlockingRejectionOptions } from "./LifoBlockingRejection.js";
|
|
3
|
+
import { type PartitionConfig } from "./PartitionedStrategy.js";
|
|
4
|
+
export declare function makeSimpleLimiter<ContextT = void>(options?: LimiterOptions<ContextT, SyncAcquireResult>): Limiter<ContextT, SyncAcquireResult>;
|
|
5
|
+
export interface BlockingLimiterFactoryOptions<ContextT> {
|
|
6
|
+
timeout?: number;
|
|
7
|
+
limiter?: Omit<LimiterOptions<ContextT, AsyncAcquireResult>, "rejectionStrategy">;
|
|
8
|
+
}
|
|
9
|
+
export declare function makeBlockingLimiter<ContextT = void>(options?: BlockingLimiterFactoryOptions<ContextT>): Limiter<ContextT, AsyncAcquireResult>;
|
|
10
|
+
export interface LifoBlockingLimiterFactoryOptions<ContextT> {
|
|
11
|
+
backlogSize?: number;
|
|
12
|
+
backlogTimeout?: LifoBlockingRejectionOptions<ContextT>["backlogTimeout"];
|
|
13
|
+
limiter?: Omit<LimiterOptions<ContextT, AsyncAcquireResult>, "rejectionStrategy">;
|
|
14
|
+
}
|
|
15
|
+
export declare function makeLifoBlockingLimiter<ContextT = void>(options?: LifoBlockingLimiterFactoryOptions<ContextT>): Limiter<ContextT, AsyncAcquireResult>;
|
|
16
|
+
export interface PartitionedLimiterFactoryOptions<ContextT, PartitionName extends string = string> {
|
|
17
|
+
partitionResolver: (context: ContextT) => PartitionName | undefined;
|
|
18
|
+
partitions: Record<PartitionName, PartitionConfig>;
|
|
19
|
+
limiter?: Omit<LimiterOptions<ContextT, SyncAcquireResult>, "acquireStrategy">;
|
|
20
|
+
}
|
|
21
|
+
export declare function makePartitionedLimiter<ContextT, PartitionName extends string = string>(options: PartitionedLimiterFactoryOptions<ContextT, PartitionName>): Limiter<ContextT, SyncAcquireResult>;
|
|
22
|
+
export interface PartitionedBlockingLimiterFactoryOptions<ContextT, PartitionName extends string = string> extends PartitionedLimiterFactoryOptions<ContextT, PartitionName> {
|
|
23
|
+
timeout?: number;
|
|
24
|
+
}
|
|
25
|
+
export declare function makePartitionedBlockingLimiter<ContextT, PartitionName extends string = string>(options: PartitionedBlockingLimiterFactoryOptions<ContextT, PartitionName>): Limiter<ContextT, AsyncAcquireResult>;
|
|
26
|
+
export interface PartitionedLifoBlockingLimiterFactoryOptions<ContextT, PartitionName extends string = string> extends PartitionedLimiterFactoryOptions<ContextT, PartitionName> {
|
|
27
|
+
backlogSize?: number;
|
|
28
|
+
backlogTimeout?: LifoBlockingRejectionOptions<ContextT>["backlogTimeout"];
|
|
29
|
+
}
|
|
30
|
+
export declare function makePartitionedLifoBlockingLimiter<ContextT, PartitionName extends string = string>(options: PartitionedLifoBlockingLimiterFactoryOptions<ContextT, PartitionName>): Limiter<ContextT, AsyncAcquireResult>;
|
|
31
|
+
//# sourceMappingURL=factories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factories.d.ts","sourceRoot":"","sources":["../../src/limiter/factories.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,0BAA0B,CAAC;AAUlC,wBAAgB,iBAAiB,CAAC,QAAQ,GAAG,IAAI,EAC/C,OAAO,GAAE,cAAc,CAAC,QAAQ,EAAE,iBAAiB,CAAM,GACxD,OAAO,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAEtC;AAED,MAAM,WAAW,6BAA6B,CAAC,QAAQ;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,IAAI,CACZ,cAAc,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAC5C,mBAAmB,CACpB,CAAC;CACH;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,GAAG,IAAI,EACjD,OAAO,GAAE,6BAA6B,CAAC,QAAQ,CAAM,GACpD,OAAO,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAOvC;AAED,MAAM,WAAW,iCAAiC,CAAC,QAAQ;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,4BAA4B,CAAC,QAAQ,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAC1E,OAAO,CAAC,EAAE,IAAI,CACZ,cAAc,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAC5C,mBAAmB,CACpB,CAAC;CACH;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,GAAG,IAAI,EACrD,OAAO,GAAE,iCAAiC,CAAC,QAAQ,CAAM,GACxD,OAAO,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAQvC;AAED,MAAM,WAAW,gCAAgC,CAC/C,QAAQ,EACR,aAAa,SAAS,MAAM,GAAG,MAAM;IAErC,iBAAiB,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,aAAa,GAAG,SAAS,CAAC;IACpE,UAAU,EAAE,MAAM,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;IACnD,OAAO,CAAC,EAAE,IAAI,CACZ,cAAc,CAAC,QAAQ,EAAE,iBAAiB,CAAC,EAC3C,iBAAiB,CAClB,CAAC;CACH;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EACR,aAAa,SAAS,MAAM,GAAG,MAAM,EAErC,OAAO,EAAE,gCAAgC,CAAC,QAAQ,EAAE,aAAa,CAAC,GACjE,OAAO,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAYtC;AAED,MAAM,WAAW,wCAAwC,CACvD,QAAQ,EACR,aAAa,SAAS,MAAM,GAAG,MAAM,CACrC,SAAQ,gCAAgC,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,8BAA8B,CAC5C,QAAQ,EACR,aAAa,SAAS,MAAM,GAAG,MAAM,EAErC,OAAO,EAAE,wCAAwC,CAAC,QAAQ,EAAE,aAAa,CAAC,GACzE,OAAO,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAevC;AAED,MAAM,WAAW,4CAA4C,CAC3D,QAAQ,EACR,aAAa,SAAS,MAAM,GAAG,MAAM,CACrC,SAAQ,gCAAgC,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,4BAA4B,CAAC,QAAQ,CAAC,CAAC,gBAAgB,CAAC,CAAC;CAC3E;AAED,wBAAgB,kCAAkC,CAChD,QAAQ,EACR,aAAa,SAAS,MAAM,GAAG,MAAM,EAErC,OAAO,EAAE,4CAA4C,CAAC,QAAQ,EAAE,aAAa,CAAC,GAC7E,OAAO,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAgBvC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Limiter, } from "../Limiter.js";
|
|
2
|
+
import { FifoBlockingRejection } from "./FifoBlockingRejection.js";
|
|
3
|
+
import { LifoBlockingRejection, } from "./LifoBlockingRejection.js";
|
|
4
|
+
import { PartitionedStrategy, } from "./PartitionedStrategy.js";
|
|
5
|
+
import { VegasLimit } from "../limit/VegasLimit.js";
|
|
6
|
+
function makeLimit(provided) {
|
|
7
|
+
return provided ?? new VegasLimit();
|
|
8
|
+
}
|
|
9
|
+
export function makeSimpleLimiter(options = {}) {
|
|
10
|
+
return new Limiter(options);
|
|
11
|
+
}
|
|
12
|
+
export function makeBlockingLimiter(options = {}) {
|
|
13
|
+
return new Limiter({
|
|
14
|
+
...options.limiter,
|
|
15
|
+
rejectionStrategy: new FifoBlockingRejection({
|
|
16
|
+
timeout: options.timeout,
|
|
17
|
+
}),
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export function makeLifoBlockingLimiter(options = {}) {
|
|
21
|
+
return new Limiter({
|
|
22
|
+
...options.limiter,
|
|
23
|
+
rejectionStrategy: new LifoBlockingRejection({
|
|
24
|
+
backlogSize: options.backlogSize,
|
|
25
|
+
backlogTimeout: options.backlogTimeout,
|
|
26
|
+
}),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export function makePartitionedLimiter(options) {
|
|
30
|
+
const limit = makeLimit(options.limiter?.limit);
|
|
31
|
+
return new Limiter({
|
|
32
|
+
...options.limiter,
|
|
33
|
+
limit,
|
|
34
|
+
acquireStrategy: new PartitionedStrategy({
|
|
35
|
+
partitionResolver: options.partitionResolver,
|
|
36
|
+
partitions: options.partitions,
|
|
37
|
+
initialLimit: limit.currentLimit,
|
|
38
|
+
metricRegistry: options.limiter?.metricRegistry,
|
|
39
|
+
}),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
export function makePartitionedBlockingLimiter(options) {
|
|
43
|
+
const limit = makeLimit(options.limiter?.limit);
|
|
44
|
+
return new Limiter({
|
|
45
|
+
...options.limiter,
|
|
46
|
+
limit,
|
|
47
|
+
acquireStrategy: new PartitionedStrategy({
|
|
48
|
+
partitionResolver: options.partitionResolver,
|
|
49
|
+
partitions: options.partitions,
|
|
50
|
+
initialLimit: limit.currentLimit,
|
|
51
|
+
metricRegistry: options.limiter?.metricRegistry,
|
|
52
|
+
}),
|
|
53
|
+
rejectionStrategy: new FifoBlockingRejection({
|
|
54
|
+
timeout: options.timeout,
|
|
55
|
+
}),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
export function makePartitionedLifoBlockingLimiter(options) {
|
|
59
|
+
const limit = makeLimit(options.limiter?.limit);
|
|
60
|
+
return new Limiter({
|
|
61
|
+
...options.limiter,
|
|
62
|
+
limit,
|
|
63
|
+
acquireStrategy: new PartitionedStrategy({
|
|
64
|
+
partitionResolver: options.partitionResolver,
|
|
65
|
+
partitions: options.partitions,
|
|
66
|
+
initialLimit: limit.currentLimit,
|
|
67
|
+
metricRegistry: options.limiter?.metricRegistry,
|
|
68
|
+
}),
|
|
69
|
+
rejectionStrategy: new LifoBlockingRejection({
|
|
70
|
+
backlogSize: options.backlogSize,
|
|
71
|
+
backlogTimeout: options.backlogTimeout,
|
|
72
|
+
}),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { StreamingStatistic } from "./StreamingStatistic.js";
|
|
2
|
+
/**
|
|
3
|
+
* Exponential moving average over a sample stream. During the warmup
|
|
4
|
+
* phase (the first {@link warmupWindow} samples) a simple arithmetic mean is
|
|
5
|
+
* used. After warmup, samples are blended using an exponential decay factor
|
|
6
|
+
* derived from the configured window size.
|
|
7
|
+
*/
|
|
8
|
+
export declare class ExpMovingAverage implements StreamingStatistic {
|
|
9
|
+
private value;
|
|
10
|
+
private sum;
|
|
11
|
+
private count;
|
|
12
|
+
private readonly window;
|
|
13
|
+
private readonly warmupWindow;
|
|
14
|
+
constructor(window: number, warmupWindow: number);
|
|
15
|
+
addSample(sample: number): number;
|
|
16
|
+
private static factor;
|
|
17
|
+
get currentValue(): number;
|
|
18
|
+
reset(): void;
|
|
19
|
+
update(operation: (current: number) => number): void;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=ExpMovingAverage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpMovingAverage.d.ts","sourceRoot":"","sources":["../../src/statistics/ExpMovingAverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE;;;;;GAKG;AACH,qBAAa,gBAAiB,YAAW,kBAAkB;IACzD,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IAKhD,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAYjC,OAAO,CAAC,MAAM,CAAC,MAAM;IAIrB,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,KAAK,IAAI,IAAI;IAMb,MAAM,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI;CAGrD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exponential moving average over a sample stream. During the warmup
|
|
3
|
+
* phase (the first {@link warmupWindow} samples) a simple arithmetic mean is
|
|
4
|
+
* used. After warmup, samples are blended using an exponential decay factor
|
|
5
|
+
* derived from the configured window size.
|
|
6
|
+
*/
|
|
7
|
+
export class ExpMovingAverage {
|
|
8
|
+
value = 0;
|
|
9
|
+
sum = 0;
|
|
10
|
+
count = 0;
|
|
11
|
+
window;
|
|
12
|
+
warmupWindow;
|
|
13
|
+
constructor(window, warmupWindow) {
|
|
14
|
+
this.window = window;
|
|
15
|
+
this.warmupWindow = warmupWindow;
|
|
16
|
+
}
|
|
17
|
+
addSample(sample) {
|
|
18
|
+
if (this.count < this.warmupWindow) {
|
|
19
|
+
this.count++;
|
|
20
|
+
this.sum += sample;
|
|
21
|
+
this.value = this.sum / this.count;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
const factor = ExpMovingAverage.factor(this.window);
|
|
25
|
+
this.value = this.value * (1 - factor) + sample * factor;
|
|
26
|
+
}
|
|
27
|
+
return this.value;
|
|
28
|
+
}
|
|
29
|
+
static factor(n) {
|
|
30
|
+
return 2.0 / (n + 1);
|
|
31
|
+
}
|
|
32
|
+
get currentValue() {
|
|
33
|
+
return this.value;
|
|
34
|
+
}
|
|
35
|
+
reset() {
|
|
36
|
+
this.value = 0;
|
|
37
|
+
this.count = 0;
|
|
38
|
+
this.sum = 0;
|
|
39
|
+
}
|
|
40
|
+
update(operation) {
|
|
41
|
+
this.value = operation(this.value);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { StreamingStatistic } from "./StreamingStatistic.js";
|
|
2
|
+
/**
|
|
3
|
+
* Tracks the minimum value seen across all samples.
|
|
4
|
+
*/
|
|
5
|
+
export declare class MinimumValue implements StreamingStatistic {
|
|
6
|
+
private value;
|
|
7
|
+
addSample(sample: number): number;
|
|
8
|
+
get currentValue(): number;
|
|
9
|
+
reset(): void;
|
|
10
|
+
update(operation: (current: number) => number): void;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=MinimumValue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MinimumValue.d.ts","sourceRoot":"","sources":["../../src/statistics/MinimumValue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE;;GAEG;AACH,qBAAa,YAAa,YAAW,kBAAkB;IACrD,OAAO,CAAC,KAAK,CAAY;IAEzB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAOjC,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,KAAK,IAAI,IAAI;IAIb,MAAM,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI;CAIrD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tracks the minimum value seen across all samples.
|
|
3
|
+
*/
|
|
4
|
+
export class MinimumValue {
|
|
5
|
+
value = Infinity;
|
|
6
|
+
addSample(sample) {
|
|
7
|
+
if (sample < this.value) {
|
|
8
|
+
this.value = sample;
|
|
9
|
+
}
|
|
10
|
+
return this.value;
|
|
11
|
+
}
|
|
12
|
+
get currentValue() {
|
|
13
|
+
return this.value;
|
|
14
|
+
}
|
|
15
|
+
reset() {
|
|
16
|
+
this.value = Infinity;
|
|
17
|
+
}
|
|
18
|
+
update(operation) {
|
|
19
|
+
const current = this.value;
|
|
20
|
+
this.value = Math.min(current, operation(current));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { StreamingStatistic } from "./StreamingStatistic.js";
|
|
2
|
+
/**
|
|
3
|
+
* Holds only the most recent sample value.
|
|
4
|
+
*/
|
|
5
|
+
export declare class MostRecentValue implements StreamingStatistic {
|
|
6
|
+
private value;
|
|
7
|
+
addSample(sample: number): number;
|
|
8
|
+
get currentValue(): number;
|
|
9
|
+
reset(): void;
|
|
10
|
+
update(operation: (current: number) => number): void;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=MostRecentValue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MostRecentValue.d.ts","sourceRoot":"","sources":["../../src/statistics/MostRecentValue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE;;GAEG;AACH,qBAAa,eAAgB,YAAW,kBAAkB;IACxD,OAAO,CAAC,KAAK,CAAuB;IAEpC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAKjC,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,KAAK,IAAI,IAAI;IAIb,MAAM,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI;CAKrD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Holds only the most recent sample value.
|
|
3
|
+
*/
|
|
4
|
+
export class MostRecentValue {
|
|
5
|
+
value = null;
|
|
6
|
+
addSample(sample) {
|
|
7
|
+
this.value = sample;
|
|
8
|
+
return sample;
|
|
9
|
+
}
|
|
10
|
+
get currentValue() {
|
|
11
|
+
return this.value ?? 0;
|
|
12
|
+
}
|
|
13
|
+
reset() {
|
|
14
|
+
this.value = null;
|
|
15
|
+
}
|
|
16
|
+
update(operation) {
|
|
17
|
+
if (this.value !== null) {
|
|
18
|
+
this.value = operation(this.value);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stateful summary of a numeric sample stream (e.g. minimum, last value, EMA).
|
|
3
|
+
*/
|
|
4
|
+
export interface StreamingStatistic {
|
|
5
|
+
/**
|
|
6
|
+
* Add a single sample and update the internal state.
|
|
7
|
+
* @param sample The sample value to add
|
|
8
|
+
* @returns The updated statistic value
|
|
9
|
+
*/
|
|
10
|
+
addSample(sample: number): number;
|
|
11
|
+
/** Current statistic value. */
|
|
12
|
+
get currentValue(): number;
|
|
13
|
+
/**
|
|
14
|
+
* Reset the internal state as if no samples were ever added.
|
|
15
|
+
*/
|
|
16
|
+
reset(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Apply a transformation to the current value.
|
|
19
|
+
*
|
|
20
|
+
* The callback's return value may not be always be used as-is, specifically
|
|
21
|
+
* if doing so would violate the semantics of the statistic. (E.g., if the
|
|
22
|
+
* statistic is a minimum, and the callback returns a value greater than the
|
|
23
|
+
* current minimum, the statistic will not be updated.) For example, if the
|
|
24
|
+
* statistic is a minimum, and the callback returns a value greater than the
|
|
25
|
+
* current minimum, the statistic will not be updated.
|
|
26
|
+
*/
|
|
27
|
+
update(operation: (current: number) => number): void;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=StreamingStatistic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamingStatistic.d.ts","sourceRoot":"","sources":["../../src/statistics/StreamingStatistic.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAElC,+BAA+B;IAC/B,IAAI,YAAY,IAAI,MAAM,CAAC;IAE3B;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;IAEd;;;;;;;;;OASG;IACH,MAAM,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACtD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Only expects integer inputs. Always floors the result to an int.
|
|
3
|
+
* Always returns >= 1. So, squareRoot(0) = 1.
|
|
4
|
+
*/
|
|
5
|
+
export declare function squareRoot(n: number): number;
|
|
6
|
+
/**
|
|
7
|
+
* Create a function that returns: max(baseline, squareRoot(n))
|
|
8
|
+
*/
|
|
9
|
+
export declare function squareRootWithBaseline(baseline: number): (n: number) => number;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility function used by limiters to calculate thresholds using the square
|
|
3
|
+
* root of the current limit. Values up to 1000 are pre-computed because the
|
|
4
|
+
* square root operation can be slow.
|
|
5
|
+
*/
|
|
6
|
+
const sqrtLookup = Array.from({ length: 1000 }, (_, i) => Math.max(1, Math.floor(Math.sqrt(i))));
|
|
7
|
+
/**
|
|
8
|
+
* Only expects integer inputs. Always floors the result to an int.
|
|
9
|
+
* Always returns >= 1. So, squareRoot(0) = 1.
|
|
10
|
+
*/
|
|
11
|
+
export function squareRoot(n) {
|
|
12
|
+
return n < 1000 ? sqrtLookup[n] : Math.floor(Math.sqrt(n));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Create a function that returns: max(baseline, squareRoot(n))
|
|
16
|
+
*/
|
|
17
|
+
export function squareRootWithBaseline(baseline) {
|
|
18
|
+
return (n) => Math.max(baseline, squareRoot(n));
|
|
19
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "adaptive-concurrency",
|
|
3
|
+
"description": "A TypeScript adaptation of Netflix's concurrency-limits library.",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"concurrency",
|
|
6
|
+
"adaptive concurrency",
|
|
7
|
+
"limits",
|
|
8
|
+
"rate limiting",
|
|
9
|
+
"dynamic rate limiting"
|
|
10
|
+
],
|
|
11
|
+
"author": "Ethan Resnick <ethan.resnick@gmail.com>",
|
|
12
|
+
"version": "0.1.0",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsc",
|
|
25
|
+
"test": "node --import tsx --test \"src/**/*.test.ts\""
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"tsx": "^4.19.0",
|
|
29
|
+
"typescript": "next"
|
|
30
|
+
}
|
|
31
|
+
}
|