@mrjacket/ahko 0.3.0 → 0.5.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/CHANGELOG.md +28 -0
- package/README.md +59 -3
- package/dist/ahko.d.ts +23 -7
- package/dist/errors/timeout.error.d.ts +15 -2
- package/dist/index.cjs +651 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +649 -54
- package/dist/index.js.map +1 -1
- package/dist/models/options.model.d.ts +24 -0
- package/dist/models/strategy.model.d.ts +6 -2
- package/dist/scheduler/debounce-coordinator.d.ts +41 -0
- package/dist/scheduler/signal.d.ts +20 -0
- package/dist/scheduler/task-queue.d.ts +16 -3
- package/dist/scheduler/task-runner.d.ts +17 -8
- package/dist/scheduler/throttle-coordinator.d.ts +43 -0
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,34 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.5.0] - 2026-09-22 — Throttle, Debounce & Rate Limiting
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Debounce scheduling strategy (`EScheduleStrategy.DEBOUNCE`) with quiet window timer resets.
|
|
12
|
+
- Throttle scheduling strategy (`EScheduleStrategy.THROTTLE`) with immediate leading execution and coalesced trailing run.
|
|
13
|
+
- Promise coalescing by explicit identity key (`key: string | symbol`): all concurrent callers awaiting the same key receive the exact same Promise resolution without artificial cancellation rejections.
|
|
14
|
+
- Task start interval rate limiting via `minIntervalMs` on scheduler constructor (`IAhkoOptions`).
|
|
15
|
+
- Automatic key cleanup and timer detachment upon settlement guaranteeing zero memory leaks.
|
|
16
|
+
- Convenience API methods `ahko.debounce()` and `ahko.throttle()`.
|
|
17
|
+
- Validation for keys, quiet windows, throttle periods, and rate limit intervals.
|
|
18
|
+
- Comprehensive unit test suites for debounce coalescing, throttle leading/trailing runs, and interval rate limiting.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## [0.4.0] - 2026-09-22 — Timeout & Robust Cancellation
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- Execution timeout control via `timeoutMs` in `IScheduleOptions`.
|
|
26
|
+
- Rejection with `AhkoTimeoutError` containing exceeded `timeoutMs` threshold and descriptive message.
|
|
27
|
+
- Immediate rejection and slot recovery for hanging, uncooperative tasks via `Promise.race`.
|
|
28
|
+
- Active execution timeout isolation (queued waiting time and backoff delays do not consume execution timeout).
|
|
29
|
+
- Fresh `timeoutMs` window allocation on retry attempts.
|
|
30
|
+
- Unified signal coordination via `combineSignals` utility with deterministic listener detachment.
|
|
31
|
+
- Strict configuration validation for `timeoutMs` (positive finite numbers).
|
|
32
|
+
- Comprehensive unit test suite covering execution timeouts, cancellation precedence, uncooperative tasks, retries, and signal combination.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
8
36
|
## [0.3.0] - 2026-09-22 — Retry & Backoff
|
|
9
37
|
|
|
10
38
|
### Added
|
package/README.md
CHANGED
|
@@ -160,7 +160,51 @@ const taskPromise = ahko.schedule(
|
|
|
160
160
|
controller.abort();
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
-
### 6.
|
|
163
|
+
### 6. Execution Deadlines & Timeouts (`timeoutMs`)
|
|
164
|
+
|
|
165
|
+
Enforce deadlines per attempt. If a task exceeds `timeoutMs`, its context signal is aborted and the task rejects with `AhkoTimeoutError`:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
try {
|
|
169
|
+
await ahko.schedule(
|
|
170
|
+
async ({ signal }) => {
|
|
171
|
+
return callLongRunningApi({ signal });
|
|
172
|
+
},
|
|
173
|
+
{ timeoutMs: 3000 } // aborts and rejects if running longer than 3 seconds
|
|
174
|
+
);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
if (error instanceof AhkoTimeoutError) {
|
|
177
|
+
console.error(`Timed out after ${error.timeoutMs}ms`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### 7. Debounce & Throttle with Promise Coalescing
|
|
183
|
+
|
|
184
|
+
Coalesce repeated invocations into shared executions by explicit `key`. Callers share the exact same returned Promise:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
// Debounce: waits for 300ms of quiet before running
|
|
188
|
+
const results = await ahko.debounce("search_box", async () => {
|
|
189
|
+
return queryApi(text);
|
|
190
|
+
}, 300);
|
|
191
|
+
|
|
192
|
+
// Throttle: runs leading edge immediately, coalesces trailing calls
|
|
193
|
+
await ahko.throttle("window_resize", async () => {
|
|
194
|
+
recalculateLayout();
|
|
195
|
+
}, 100);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### 8. Paced Execution (`minIntervalMs`)
|
|
199
|
+
|
|
200
|
+
Prevent burst spikes by ensuring a minimum interval elapses between consecutive task starts:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
// At most 2 concurrent tasks, paced at least 50ms apart
|
|
204
|
+
const ahko = new Ahko({ concurrency: 2, minIntervalMs: 50 });
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### 9. Telemetry (`stats`)
|
|
164
208
|
|
|
165
209
|
Inspect real-time scheduler state without synthetic metrics:
|
|
166
210
|
|
|
@@ -174,7 +218,7 @@ console.log(stats);
|
|
|
174
218
|
// completedTasks: 42,
|
|
175
219
|
// failedTasks: 1,
|
|
176
220
|
// cancelledTasks: 2,
|
|
177
|
-
// timedOutTasks:
|
|
221
|
+
// timedOutTasks: 1,
|
|
178
222
|
// capacity: 3
|
|
179
223
|
// }
|
|
180
224
|
```
|
|
@@ -203,6 +247,7 @@ Creates an AHKO scheduler instance.
|
|
|
203
247
|
| Option | Type | Default | Description |
|
|
204
248
|
|---|---|---|---|
|
|
205
249
|
| `concurrency` | `number` | `Infinity` | Maximum concurrent tasks allowed to run simultaneously. Must be $\ge 1$. |
|
|
250
|
+
| `minIntervalMs` | `number` | `0` | Minimum interval in milliseconds between consecutive task starts. Must be $\ge 0$. |
|
|
206
251
|
|
|
207
252
|
### `ahko.schedule<T>(task: ITask<T>, options?: IScheduleOptions): Promise<T>`
|
|
208
253
|
|
|
@@ -210,12 +255,23 @@ Schedules an asynchronous task with full return type inference.
|
|
|
210
255
|
|
|
211
256
|
| Option | Type | Default | Description |
|
|
212
257
|
|---|---|---|---|
|
|
213
|
-
| `strategy` | `"immediate" \| "delay" \| "idle"` | `"immediate"` | Scheduling execution strategy. |
|
|
258
|
+
| `strategy` | `"immediate" \| "delay" \| "idle" \| "throttle" \| "debounce"` | `"immediate"` | Scheduling execution strategy. |
|
|
214
259
|
| `delay` | `number` | `0` | Delay in milliseconds when strategy is `"delay"`. |
|
|
260
|
+
| `key` | `string \| symbol` | `undefined` | Explicit identity key for `"debounce"` and `"throttle"`. |
|
|
261
|
+
| `waitMs` | `number` | `undefined` | Window duration in ms for debounce quiet period or throttle interval. |
|
|
215
262
|
| `idleTimeout` | `number` | `undefined` | Maximum time to wait for idle window before forcing queue entry. |
|
|
216
263
|
| `retry` | `IRetryOptions` | `undefined` | Automatic retry policy (attempts, backoff, jitter, predicate). |
|
|
264
|
+
| `timeoutMs` | `number` | `undefined` | Maximum execution duration in milliseconds per attempt before aborting with `AhkoTimeoutError`. |
|
|
217
265
|
| `signal` | `AbortSignal` | `undefined` | Optional external `AbortSignal` for cooperative cancellation. |
|
|
218
266
|
|
|
267
|
+
### `ahko.debounce<T>(key: string | symbol, task: ITask<T>, waitMs: number, options?: IScheduleOptions): Promise<T>`
|
|
268
|
+
|
|
269
|
+
Convenience method scheduling a debounced task with key-based Promise coalescing.
|
|
270
|
+
|
|
271
|
+
### `ahko.throttle<T>(key: string | symbol, task: ITask<T>, waitMs: number, options?: IScheduleOptions): Promise<T>`
|
|
272
|
+
|
|
273
|
+
Convenience method scheduling a throttled task with leading execution and coalesced trailing run.
|
|
274
|
+
|
|
219
275
|
### `ahko.idle<T>(task: ITask<T>, options?: Omit<IScheduleOptions, "strategy">): Promise<T>`
|
|
220
276
|
|
|
221
277
|
Convenience method scheduling a task under `strategy: "idle"`.
|
package/dist/ahko.d.ts
CHANGED
|
@@ -44,6 +44,7 @@ export declare class Ahko {
|
|
|
44
44
|
*
|
|
45
45
|
* @throws {AhkoConfigurationError} If the task is not a function or options are invalid.
|
|
46
46
|
* @throws {AhkoCancellationError} If the task is cancelled prior to or during execution.
|
|
47
|
+
* @throws {AhkoTimeoutError} If task execution exceeds timeoutMs.
|
|
47
48
|
*
|
|
48
49
|
* @example
|
|
49
50
|
* ```typescript
|
|
@@ -73,15 +74,30 @@ export declare class Ahko {
|
|
|
73
74
|
*
|
|
74
75
|
* @throws {AhkoConfigurationError} If the task is not a function or options are invalid.
|
|
75
76
|
* @throws {AhkoCancellationError} If the task is cancelled prior to or during execution.
|
|
76
|
-
*
|
|
77
|
-
* @example
|
|
78
|
-
* ```typescript
|
|
79
|
-
* const result = await ahko.idle(async ({ signal }) => {
|
|
80
|
-
* return computeAnalytics();
|
|
81
|
-
* });
|
|
82
|
-
* ```
|
|
83
77
|
*/
|
|
84
78
|
idle<T>(task: ITask<T>, options?: Omit<IScheduleOptions, "strategy">): Promise<T>;
|
|
79
|
+
/**
|
|
80
|
+
* Convenience method to schedule a debounced task with key-based Promise coalescing.
|
|
81
|
+
*
|
|
82
|
+
* @template T - Inferred return type of the task.
|
|
83
|
+
* @param key - Explicit identity key.
|
|
84
|
+
* @param task - Work to execute once calls stop arriving.
|
|
85
|
+
* @param waitMs - Quiet window duration in milliseconds.
|
|
86
|
+
* @param options - Additional schedule options.
|
|
87
|
+
* @returns Shared promise resolving with the final execution outcome.
|
|
88
|
+
*/
|
|
89
|
+
debounce<T>(key: string | symbol, task: ITask<T>, waitMs: number, options?: Omit<IScheduleOptions, "strategy" | "key" | "waitMs">): Promise<T>;
|
|
90
|
+
/**
|
|
91
|
+
* Convenience method to schedule a throttled task with leading execution and coalesced trailing run.
|
|
92
|
+
*
|
|
93
|
+
* @template T - Inferred return type of the task.
|
|
94
|
+
* @param key - Explicit identity key.
|
|
95
|
+
* @param task - Work to execute.
|
|
96
|
+
* @param waitMs - Throttle interval duration in milliseconds.
|
|
97
|
+
* @param options - Additional schedule options.
|
|
98
|
+
* @returns Promise resolving with the leading or coalesced trailing result.
|
|
99
|
+
*/
|
|
100
|
+
throttle<T>(key: string | symbol, task: ITask<T>, waitMs: number, options?: Omit<IScheduleOptions, "strategy" | "key" | "waitMs">): Promise<T>;
|
|
85
101
|
/**
|
|
86
102
|
* Retrieves real-time telemetry metrics from the scheduler.
|
|
87
103
|
*
|
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
import { AhkoError } from "./ahko.error.js";
|
|
2
|
+
/**
|
|
3
|
+
* Options for constructing an AhkoTimeoutError.
|
|
4
|
+
*/
|
|
5
|
+
export interface IAhkoTimeoutErrorOptions extends ErrorOptions {
|
|
6
|
+
/**
|
|
7
|
+
* The timeout threshold in milliseconds that was exceeded.
|
|
8
|
+
*/
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
}
|
|
2
11
|
/**
|
|
3
12
|
* Thrown when a task exceeds its allotted timeout duration.
|
|
4
13
|
*/
|
|
5
14
|
export declare class AhkoTimeoutError extends AhkoError {
|
|
15
|
+
/**
|
|
16
|
+
* The timeout threshold in milliseconds that was exceeded, if configured.
|
|
17
|
+
*/
|
|
18
|
+
readonly timeoutMs?: number;
|
|
6
19
|
/**
|
|
7
20
|
* Creates a new AhkoTimeoutError.
|
|
8
21
|
*
|
|
9
22
|
* @param message - Explanation of timeout expiry.
|
|
10
|
-
* @param options - Standard Error options including cause.
|
|
23
|
+
* @param options - Standard Error options including optional timeoutMs and cause.
|
|
11
24
|
*/
|
|
12
|
-
constructor(message?: string, options?:
|
|
25
|
+
constructor(message?: string, options?: IAhkoTimeoutErrorOptions);
|
|
13
26
|
}
|