rate-budget 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hikuroshi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,238 @@
1
+ # rate-budget
2
+
3
+ `rate-budget` is a small, dependency-free toolkit for calculating request rate
4
+ limits, quota thresholds, token or cost budgets, cooldowns, and retries.
5
+
6
+ It is provider-agnostic and storage-agnostic. The package does not manage your
7
+ database, Redis keys, queues, locks, or HTTP clients. Your application owns the
8
+ state; `rate-budget` only calculates deterministic decisions from the counters
9
+ and events you pass in.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install rate-budget
15
+ pnpm add rate-budget
16
+ yarn add rate-budget
17
+ ```
18
+
19
+ ## Features
20
+
21
+ - Request spacing for limits such as RPM, RPH, or any count-per-window limit.
22
+ - Sliding-window cost checks for tokens, bytes, credits, points, or custom units.
23
+ - Daily quota thresholds such as RPD with configurable safety percentages.
24
+ - Per-request token or cost budget planning.
25
+ - Flexible budget splitting for context, input, output, metadata, and similar allocations.
26
+ - Lightweight in-memory actor cooldowns for single-process use cases.
27
+ - Async retry helper with configurable status codes, message fragments, and delays.
28
+ - ESM and CommonJS exports.
29
+ - TypeScript declarations.
30
+ - Zero runtime dependencies.
31
+
32
+ ## Imports
33
+
34
+ ESM:
35
+
36
+ ```ts
37
+ import {
38
+ buildRequestLimitProfile,
39
+ calculateWindowUsageWaitMs,
40
+ } from "rate-budget";
41
+ ```
42
+
43
+ CommonJS:
44
+
45
+ ```js
46
+ const {
47
+ buildRequestLimitProfile,
48
+ calculateWindowUsageWaitMs,
49
+ } = require("rate-budget");
50
+ ```
51
+
52
+ ## Core Model
53
+
54
+ `rate-budget` is designed around pure calculations:
55
+
56
+ 1. Read current usage and recent events from your own storage.
57
+ 2. Pass those values into `rate-budget`.
58
+ 3. If the decision requires waiting, delay or enqueue in your application.
59
+ 4. If the request is allowed, reserve or log the request atomically.
60
+ 5. After the request finishes, update usage in your storage.
61
+
62
+ This keeps the package lightweight while still fitting distributed systems,
63
+ serverless applications, workers, bots, and API gateways.
64
+
65
+ ## RPM, TPM, and RPD Example
66
+
67
+ ```ts
68
+ import {
69
+ buildRequestLimitProfile,
70
+ calculateCooldownWaitMs,
71
+ calculateWindowUsageWaitMs,
72
+ evaluateCountLimit,
73
+ } from "rate-budget";
74
+
75
+ const profile = buildRequestLimitProfile({
76
+ rpmLimit: 15,
77
+ tpmLimit: 250_000,
78
+ rpdLimit: 500,
79
+ dailyThresholdPercent: 90,
80
+ });
81
+
82
+ const dailyDecision = evaluateCountLimit({
83
+ usedCount: usageToday.requestCount,
84
+ limit: profile.rpdLimit,
85
+ thresholdPercent: profile.dailyThresholdPercent,
86
+ });
87
+
88
+ if (!dailyDecision.allowed) {
89
+ throw new Error("Daily quota threshold reached.");
90
+ }
91
+
92
+ const cooldownWaitMs = calculateCooldownWaitMs({
93
+ lastAcceptedAt: lastApiRequest?.createdAt,
94
+ cooldownMs: profile.cooldownMs,
95
+ });
96
+
97
+ const tokenWaitMs = calculateWindowUsageWaitMs({
98
+ incomingCost: estimatedRequestTokens,
99
+ limit: profile.tpmLimit,
100
+ entries: recentApiRequests.map((request) => ({
101
+ occurredAt: request.createdAt,
102
+ cost: request.totalTokens,
103
+ })),
104
+ });
105
+
106
+ const waitMs = Math.max(cooldownWaitMs, tokenWaitMs);
107
+
108
+ if (waitMs > 0) {
109
+ await waitOrQueue(waitMs);
110
+ }
111
+ ```
112
+
113
+ ## Sliding-Window Cost Limit
114
+
115
+ Use `evaluateWindowUsage` when you need the full decision, or
116
+ `calculateWindowUsageWaitMs` when you only need the wait time.
117
+
118
+ ```ts
119
+ import { evaluateWindowUsage } from "rate-budget";
120
+
121
+ const decision = evaluateWindowUsage({
122
+ incomingCost: 500,
123
+ limit: 10_000,
124
+ windowMs: 60_000,
125
+ safetyBufferMs: 1_000,
126
+ entries: [
127
+ { occurredAt: "2026-05-21 14:00:10", cost: 4_000 },
128
+ { occurredAt: "2026-05-21 14:00:30", cost: 6_200 },
129
+ ],
130
+ });
131
+
132
+ if (!decision.allowed && decision.retryAfterMs !== null) {
133
+ await delay(decision.retryAfterMs);
134
+ }
135
+ ```
136
+
137
+ `cost` can represent tokens, weighted requests, bytes, credits, or any other
138
+ unit that should be limited over time.
139
+
140
+ ## Token Budget Planning
141
+
142
+ ```ts
143
+ import {
144
+ calculatePerRequestTokenBudget,
145
+ calculateTokenBudgetPortion,
146
+ distributeFlexibleTokenBudget,
147
+ } from "rate-budget";
148
+
149
+ const totalBudget = calculatePerRequestTokenBudget({
150
+ tokensPerWindow: 250_000,
151
+ requestSpacingMs: 5_000,
152
+ minimumTokens: 96,
153
+ });
154
+
155
+ const inputBudget = calculateTokenBudgetPortion(totalBudget, 0.5);
156
+
157
+ const flexible = distributeFlexibleTokenBudget({
158
+ parentBudget: inputBudget,
159
+ availableTokens: inputBudget - systemPromptTokens - userPromptTokens,
160
+ partitions: [
161
+ { name: "context", targetRatio: 0.55, maxRatio: 0.6 },
162
+ { name: "metadata", targetRatio: 0.15, maxRatio: 0.2 },
163
+ ],
164
+ });
165
+
166
+ console.log(flexible.context, flexible.metadata);
167
+ ```
168
+
169
+ ## In-Memory Actor Cooldowns
170
+
171
+ Use `InMemoryActorCooldownLimiter` for local process cooldowns, such as UX
172
+ cooldowns in a bot or simple API server. For multi-instance systems, store the
173
+ cooldown state in Redis or a database and use the pure helpers instead.
174
+
175
+ ```ts
176
+ import { InMemoryActorCooldownLimiter } from "rate-budget";
177
+
178
+ const limiter = new InMemoryActorCooldownLimiter({
179
+ sameActorCooldownMs: 3_000,
180
+ differentActorCooldownMs: 1_000,
181
+ stateTtlMs: 5 * 60_000,
182
+ });
183
+
184
+ const decision = limiter.consume("guild:123", "user:456");
185
+
186
+ if (!decision.allowed) {
187
+ console.log(`Retry after ${decision.retryAfterMs}ms`);
188
+ }
189
+ ```
190
+
191
+ ## Retry
192
+
193
+ ```ts
194
+ import { retryAsync, isRetryableError } from "rate-budget";
195
+
196
+ const response = await retryAsync({
197
+ retryAttempts: 2,
198
+ delayMs: ({ attemptIndex }) => 1_000 * (attemptIndex + 1),
199
+ shouldRetry: (error) =>
200
+ isRetryableError(error, {
201
+ statusCodes: [429, 500, 502, 503, 504],
202
+ messageIncludes: ["rate limit", "temporarily unavailable"],
203
+ }),
204
+ task: () => fetchProvider(),
205
+ });
206
+ ```
207
+
208
+ ## API Overview
209
+
210
+ - `buildRequestLimitProfile(input)`: creates a normalized RPM, TPM, RPD, threshold, cooldown, and inactive cooldown profile.
211
+ - `calculateLimitSpacingMs(limitPerWindow, options)`: calculates safe request spacing inside a time window.
212
+ - `calculateInactiveLimitSpacingMs(limitPerWindow, options)`: calculates inactive cooldown spacing with a multiplier.
213
+ - `calculateThresholdCount(limit, thresholdPercent)`: calculates a safe quota threshold.
214
+ - `evaluateCountLimit(input)`: evaluates count-based quota usage.
215
+ - `calculateCooldownWaitMs(input)`: calculates remaining cooldown from the last accepted timestamp.
216
+ - `evaluateWindowUsage(input)`: evaluates sliding-window cost usage and returns a detailed decision.
217
+ - `calculateWindowUsageWaitMs(input)`: returns only the wait time for sliding-window cost usage.
218
+ - `calculatePerRequestTokenBudget(input)`: calculates cost or token budget per request.
219
+ - `calculateTokenBudgetPortion(totalBudget, ratio)`: returns a ratio-based budget portion.
220
+ - `distributeFlexibleTokenBudget(input)`: allocates flexible budget across named partitions.
221
+ - `InMemoryActorCooldownLimiter`: local in-memory cooldown per scope and actor.
222
+ - `retryAsync(input)`: retries an async task.
223
+ - `isRetryableError(error, options)`: checks status codes and message fragments.
224
+ - `delay(ms)`: small promise-based delay helper.
225
+
226
+ ## Build and Test
227
+
228
+ ```bash
229
+ pnpm --filter rate-budget build
230
+ pnpm --filter rate-budget test
231
+ ```
232
+
233
+ From the package directory:
234
+
235
+ ```bash
236
+ npm run build
237
+ npm test
238
+ ```
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./limits.js"), exports);
18
+ __exportStar(require("./memory-cooldown.js"), exports);
19
+ __exportStar(require("./retry.js"), exports);
20
+ __exportStar(require("./token-budget.js"), exports);
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,uDAAqC;AACrC,6CAA2B;AAC3B,oDAAkC"}
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_INACTIVE_COOLDOWN_MULTIPLIER = exports.DEFAULT_LIMIT_SAFETY_BUFFER_MS = exports.DEFAULT_LIMIT_WINDOW_MS = void 0;
4
+ exports.toPositiveInteger = toPositiveInteger;
5
+ exports.toNonNegativeInteger = toNonNegativeInteger;
6
+ exports.clampPercent = clampPercent;
7
+ exports.toTimestampMs = toTimestampMs;
8
+ exports.calculateLimitSpacingMs = calculateLimitSpacingMs;
9
+ exports.calculateInactiveLimitSpacingMs = calculateInactiveLimitSpacingMs;
10
+ exports.calculateThresholdCount = calculateThresholdCount;
11
+ exports.evaluateCountLimit = evaluateCountLimit;
12
+ exports.calculateCooldownWaitMs = calculateCooldownWaitMs;
13
+ exports.evaluateWindowUsage = evaluateWindowUsage;
14
+ exports.calculateWindowUsageWaitMs = calculateWindowUsageWaitMs;
15
+ exports.buildRequestLimitProfile = buildRequestLimitProfile;
16
+ exports.DEFAULT_LIMIT_WINDOW_MS = 60000;
17
+ exports.DEFAULT_LIMIT_SAFETY_BUFFER_MS = 1000;
18
+ exports.DEFAULT_INACTIVE_COOLDOWN_MULTIPLIER = 2;
19
+ function normalizeFiniteNumber(value, fallback) {
20
+ return Number.isFinite(value) ? value : fallback;
21
+ }
22
+ function toPositiveInteger(value, fallback = 1) {
23
+ return Math.max(1, Math.floor(normalizeFiniteNumber(value, fallback)));
24
+ }
25
+ function toNonNegativeInteger(value, fallback = 0) {
26
+ return Math.max(0, Math.floor(normalizeFiniteNumber(value, fallback)));
27
+ }
28
+ function clampPercent(value, fallback = 100) {
29
+ const safeValue = normalizeFiniteNumber(value, fallback);
30
+ return Math.min(100, Math.max(0, safeValue));
31
+ }
32
+ function toTimestampMs(value) {
33
+ if (value === null || value === undefined) {
34
+ return null;
35
+ }
36
+ if (typeof value === "number") {
37
+ return Number.isFinite(value) ? value : null;
38
+ }
39
+ const timestamp = value instanceof Date ? value.getTime() : Date.parse(value);
40
+ return Number.isFinite(timestamp) ? timestamp : null;
41
+ }
42
+ function calculateLimitSpacingMs(limitPerWindow, options = {}) {
43
+ const limit = toPositiveInteger(limitPerWindow);
44
+ const windowMs = toPositiveInteger(options.windowMs ?? exports.DEFAULT_LIMIT_WINDOW_MS, exports.DEFAULT_LIMIT_WINDOW_MS);
45
+ const safetyBufferMs = toNonNegativeInteger(options.safetyBufferMs ?? exports.DEFAULT_LIMIT_SAFETY_BUFFER_MS, exports.DEFAULT_LIMIT_SAFETY_BUFFER_MS);
46
+ return Math.ceil(windowMs / limit + safetyBufferMs);
47
+ }
48
+ function calculateInactiveLimitSpacingMs(limitPerWindow, options = {}) {
49
+ const multiplier = Math.max(1, normalizeFiniteNumber(options.multiplier ?? exports.DEFAULT_INACTIVE_COOLDOWN_MULTIPLIER, exports.DEFAULT_INACTIVE_COOLDOWN_MULTIPLIER));
50
+ return Math.ceil(calculateLimitSpacingMs(limitPerWindow, options) * multiplier);
51
+ }
52
+ function calculateThresholdCount(limit, thresholdPercent = 100) {
53
+ const safeLimit = toPositiveInteger(limit);
54
+ const safeThresholdPercent = clampPercent(thresholdPercent);
55
+ return Math.max(1, Math.ceil(safeLimit * (safeThresholdPercent / 100)));
56
+ }
57
+ function evaluateCountLimit(input) {
58
+ const usedCount = toNonNegativeInteger(input.usedCount);
59
+ const thresholdCount = calculateThresholdCount(input.limit, input.thresholdPercent);
60
+ const remainingCount = Math.max(0, thresholdCount - usedCount);
61
+ if (remainingCount <= 0) {
62
+ return {
63
+ allowed: false,
64
+ usedCount,
65
+ thresholdCount,
66
+ remainingCount: 0,
67
+ };
68
+ }
69
+ return {
70
+ allowed: true,
71
+ usedCount,
72
+ thresholdCount,
73
+ remainingCount,
74
+ };
75
+ }
76
+ function calculateCooldownWaitMs(input) {
77
+ const lastAcceptedAt = toTimestampMs(input.lastAcceptedAt);
78
+ if (lastAcceptedAt === null) {
79
+ return 0;
80
+ }
81
+ const now = normalizeFiniteNumber(input.now ?? Date.now(), Date.now());
82
+ const cooldownMs = toNonNegativeInteger(input.cooldownMs);
83
+ return Math.max(0, cooldownMs - (now - lastAcceptedAt));
84
+ }
85
+ function normalizeWindowEntries(entries, entriesSortedOldestFirst, input) {
86
+ const normalized = entries.flatMap((entry) => {
87
+ const occurredAtMs = toTimestampMs(entry.occurredAt);
88
+ if (occurredAtMs === null ||
89
+ occurredAtMs < input.now - input.windowMs ||
90
+ occurredAtMs > input.now) {
91
+ return [];
92
+ }
93
+ return [
94
+ {
95
+ occurredAtMs,
96
+ cost: toNonNegativeInteger(entry.cost),
97
+ },
98
+ ];
99
+ });
100
+ if (entriesSortedOldestFirst) {
101
+ return normalized;
102
+ }
103
+ return normalized.sort((left, right) => left.occurredAtMs - right.occurredAtMs);
104
+ }
105
+ function evaluateWindowUsage(input) {
106
+ const limit = toPositiveInteger(input.limit);
107
+ const incomingCost = toNonNegativeInteger(input.incomingCost);
108
+ const now = normalizeFiniteNumber(input.now ?? Date.now(), Date.now());
109
+ const windowMs = toPositiveInteger(input.windowMs ?? exports.DEFAULT_LIMIT_WINDOW_MS, exports.DEFAULT_LIMIT_WINDOW_MS);
110
+ const entries = normalizeWindowEntries(input.entries, input.entriesSortedOldestFirst ?? true, { now, windowMs });
111
+ const currentCost = input.currentCost === undefined
112
+ ? entries.reduce((sum, entry) => sum + entry.cost, 0)
113
+ : toNonNegativeInteger(input.currentCost);
114
+ const projectedCost = currentCost + incomingCost;
115
+ if (incomingCost > limit) {
116
+ return {
117
+ allowed: false,
118
+ reason: "single_request_exceeds_limit",
119
+ projectedCost,
120
+ limit,
121
+ retryAfterMs: null,
122
+ };
123
+ }
124
+ if (projectedCost <= limit) {
125
+ return {
126
+ allowed: true,
127
+ reason: "within_limit",
128
+ projectedCost,
129
+ limit,
130
+ retryAfterMs: 0,
131
+ };
132
+ }
133
+ const safetyBufferMs = toNonNegativeInteger(input.safetyBufferMs ?? exports.DEFAULT_LIMIT_SAFETY_BUFFER_MS, exports.DEFAULT_LIMIT_SAFETY_BUFFER_MS);
134
+ let remainingCost = projectedCost;
135
+ for (const entry of entries) {
136
+ remainingCost -= entry.cost;
137
+ if (remainingCost <= limit) {
138
+ return {
139
+ allowed: false,
140
+ reason: "window_exhausted",
141
+ projectedCost,
142
+ limit,
143
+ retryAfterMs: Math.max(0, windowMs - (now - entry.occurredAtMs) + safetyBufferMs),
144
+ };
145
+ }
146
+ }
147
+ return {
148
+ allowed: false,
149
+ reason: "window_exhausted",
150
+ projectedCost,
151
+ limit,
152
+ retryAfterMs: windowMs,
153
+ };
154
+ }
155
+ function calculateWindowUsageWaitMs(input) {
156
+ const decision = evaluateWindowUsage(input);
157
+ if (decision.allowed) {
158
+ return 0;
159
+ }
160
+ return (decision.retryAfterMs ??
161
+ toPositiveInteger(input.windowMs ?? exports.DEFAULT_LIMIT_WINDOW_MS, exports.DEFAULT_LIMIT_WINDOW_MS));
162
+ }
163
+ function buildRequestLimitProfile(input) {
164
+ const rpmLimit = toPositiveInteger(input.rpmLimit);
165
+ const tpmLimit = toPositiveInteger(input.tpmLimit);
166
+ const rpdLimit = toPositiveInteger(input.rpdLimit);
167
+ const dailyThresholdPercent = clampPercent(input.dailyThresholdPercent ?? 100);
168
+ const cooldownOptions = {
169
+ windowMs: input.windowMs,
170
+ safetyBufferMs: input.safetyBufferMs,
171
+ };
172
+ return {
173
+ rpmLimit,
174
+ tpmLimit,
175
+ rpdLimit,
176
+ dailyThresholdPercent,
177
+ dailyThresholdRequests: calculateThresholdCount(rpdLimit, dailyThresholdPercent),
178
+ cooldownMs: calculateLimitSpacingMs(rpmLimit, cooldownOptions),
179
+ inactiveCooldownMs: calculateInactiveLimitSpacingMs(rpmLimit, {
180
+ ...cooldownOptions,
181
+ multiplier: input.inactiveCooldownMultiplier,
182
+ }),
183
+ };
184
+ }
185
+ //# sourceMappingURL=limits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.js","sourceRoot":"","sources":["../../src/limits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InMemoryActorCooldownLimiter = void 0;
4
+ exports.consumeActorCooldown = consumeActorCooldown;
5
+ const limits_js_1 = require("./limits.js");
6
+ function consumeActorCooldown(currentState, input) {
7
+ const now = Number.isFinite(input.now) ? input.now ?? Date.now() : Date.now();
8
+ if (!currentState) {
9
+ return {
10
+ allowed: true,
11
+ state: {
12
+ lastAcceptedAt: now,
13
+ lastActorId: input.actorId,
14
+ },
15
+ };
16
+ }
17
+ const requiredCooldownMs = currentState.lastActorId === input.actorId
18
+ ? (0, limits_js_1.toNonNegativeInteger)(input.sameActorCooldownMs)
19
+ : (0, limits_js_1.toNonNegativeInteger)(input.differentActorCooldownMs);
20
+ const elapsedMs = now - currentState.lastAcceptedAt;
21
+ if (elapsedMs < requiredCooldownMs) {
22
+ return {
23
+ allowed: false,
24
+ retryAfterMs: requiredCooldownMs - elapsedMs,
25
+ state: currentState,
26
+ };
27
+ }
28
+ return {
29
+ allowed: true,
30
+ state: {
31
+ lastAcceptedAt: now,
32
+ lastActorId: input.actorId,
33
+ },
34
+ };
35
+ }
36
+ class InMemoryActorCooldownLimiter {
37
+ constructor(options) {
38
+ this.states = new Map();
39
+ this.touches = 0;
40
+ this.sameActorCooldownMs = (0, limits_js_1.toNonNegativeInteger)(options.sameActorCooldownMs);
41
+ this.differentActorCooldownMs = (0, limits_js_1.toNonNegativeInteger)(options.differentActorCooldownMs);
42
+ this.stateTtlMs = (0, limits_js_1.toNonNegativeInteger)(options.stateTtlMs ?? 5 * 60000);
43
+ this.cleanupInterval = Math.max(1, (0, limits_js_1.toNonNegativeInteger)(options.cleanupInterval ?? 256, 256));
44
+ }
45
+ consume(scopeId, actorId, now = Date.now()) {
46
+ this.cleanup(now);
47
+ const decision = consumeActorCooldown(this.states.get(scopeId), {
48
+ actorId,
49
+ now,
50
+ sameActorCooldownMs: this.sameActorCooldownMs,
51
+ differentActorCooldownMs: this.differentActorCooldownMs,
52
+ });
53
+ if (decision.allowed) {
54
+ this.states.set(scopeId, decision.state);
55
+ }
56
+ return decision;
57
+ }
58
+ reset(scopeId) {
59
+ if (scopeId) {
60
+ this.states.delete(scopeId);
61
+ return;
62
+ }
63
+ this.states.clear();
64
+ }
65
+ size() {
66
+ return this.states.size;
67
+ }
68
+ cleanup(now) {
69
+ this.touches += 1;
70
+ if (this.touches % this.cleanupInterval !== 0) {
71
+ return;
72
+ }
73
+ for (const [scopeId, state] of this.states.entries()) {
74
+ if (now - state.lastAcceptedAt > this.stateTtlMs) {
75
+ this.states.delete(scopeId);
76
+ }
77
+ }
78
+ }
79
+ }
80
+ exports.InMemoryActorCooldownLimiter = InMemoryActorCooldownLimiter;
81
+ //# sourceMappingURL=memory-cooldown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-cooldown.js","sourceRoot":"","sources":["../../src/memory-cooldown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.delay = delay;
4
+ exports.getErrorStatus = getErrorStatus;
5
+ exports.getErrorMessage = getErrorMessage;
6
+ exports.isRetryableError = isRetryableError;
7
+ exports.retryAsync = retryAsync;
8
+ const limits_js_1 = require("./limits.js");
9
+ function delay(ms) {
10
+ const safeMs = (0, limits_js_1.toNonNegativeInteger)(ms);
11
+ if (safeMs <= 0) {
12
+ return Promise.resolve();
13
+ }
14
+ return new Promise((resolve) => {
15
+ setTimeout(resolve, safeMs);
16
+ });
17
+ }
18
+ function getErrorStatus(error) {
19
+ if (!error || typeof error !== "object" || !("status" in error)) {
20
+ return null;
21
+ }
22
+ const status = error.status;
23
+ return typeof status === "number" && Number.isFinite(status) ? status : null;
24
+ }
25
+ function getErrorMessage(error) {
26
+ if (error instanceof Error) {
27
+ return error.message;
28
+ }
29
+ if (typeof error === "string") {
30
+ return error;
31
+ }
32
+ return "";
33
+ }
34
+ function isRetryableError(error, options = {}) {
35
+ const statusCodes = options.statusCodes ?? [429, 500, 503];
36
+ const status = getErrorStatus(error);
37
+ if (status !== null && statusCodes.includes(status)) {
38
+ return true;
39
+ }
40
+ const message = getErrorMessage(error).toLowerCase();
41
+ return (options.messageIncludes ?? []).some((fragment) => message.includes(fragment.toLowerCase()));
42
+ }
43
+ function resolveRetryDelay(delayMs, input) {
44
+ if (typeof delayMs === "function") {
45
+ return (0, limits_js_1.toNonNegativeInteger)(delayMs(input));
46
+ }
47
+ return (0, limits_js_1.toNonNegativeInteger)(delayMs ?? 0);
48
+ }
49
+ async function retryAsync(input) {
50
+ const retryAttempts = (0, limits_js_1.toNonNegativeInteger)(input.retryAttempts);
51
+ const maxAttempts = retryAttempts + 1;
52
+ let lastError = null;
53
+ for (let attemptIndex = 0; attemptIndex < maxAttempts; attemptIndex += 1) {
54
+ try {
55
+ return await input.task({ attemptIndex });
56
+ }
57
+ catch (error) {
58
+ lastError = error;
59
+ if (attemptIndex >= maxAttempts - 1) {
60
+ break;
61
+ }
62
+ const shouldRetry = input.shouldRetry
63
+ ? input.shouldRetry(error, { attemptIndex })
64
+ : isRetryableError(error);
65
+ if (!shouldRetry) {
66
+ break;
67
+ }
68
+ const nextDelayMs = resolveRetryDelay(input.delayMs, {
69
+ attemptIndex,
70
+ error,
71
+ });
72
+ await input.onRetry?.({
73
+ attemptIndex,
74
+ nextDelayMs,
75
+ error,
76
+ });
77
+ await delay(nextDelayMs);
78
+ }
79
+ }
80
+ throw lastError;
81
+ }
82
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/retry.ts"],"names":[],"mappings":"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"}