@mrjacket/ahko 1.0.0 → 1.1.5

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 CHANGED
@@ -5,6 +5,69 @@ 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
+ ## [1.1.5] - 2026-09-24 — Batch Collections, Dynamic & Adaptive Concurrency, Task Tags
9
+
10
+ ### Added
11
+ - **Batch Collections API (`ahko.map` & `ahko.each`)**:
12
+ - `ahko.map<TItem, TResult>(items, fn, options?)`: Concurrently transforms any iterable sequence while strictly preserving original element order.
13
+ - `ahko.each<TItem>(items, fn, options?)`: Concurrently iterates over any sequence returning `Promise<void>`.
14
+ - Supports localized concurrency caps per-batch (`options.concurrency`), falling back to scheduler concurrency when omitted.
15
+ - Fail-fast flow control via `stopOnError: true` (aborts remaining tasks immediately and rejects) or settled error propagation via `stopOnError: false` (default).
16
+ - Native integration with `signal`, `retry`, `tags`, and priority options.
17
+ - **Dynamic & Adaptive Concurrency (AIMD Auto-Chill Mode)**:
18
+ - Runtime dynamic concurrency reconfiguration via `ahko.setConcurrency(n)` and getter `ahko.concurrency`.
19
+ - Additive Increase / Multiplicative Decrease (AIMD) algorithm (`AdaptiveCoordinator`) adjusting scheduler capacity based on real-time task latency (`options.adaptive`).
20
+ - Seamlessly handles network latency spikes by scaling down concurrency on congestion and recovering when latency drops.
21
+ - Lifecycle event `"concurrency:change"` emitting `previousConcurrency`, `currentConcurrency`, and human-readable `reason`.
22
+ - Telemetry metrics in `ahko.stats().adaptive`: `currentConcurrency`, `averageLatencyMs`, `samplesRecorded`.
23
+ - **Task Tags & Selective Cancellation**:
24
+ - Categorize tasks via `tags: string[]` in `schedule()`, `map()`, or declarative profiles.
25
+ - Selectively cancel related tasks via `ahko.cancelByTag(tag, reason?)` without interrupting other pending or active workloads.
26
+ - Inspect workload density per category via `ahko.statsByTag(tag)` (`activeTasks` and `pendingTasks`).
27
+ - Memory-safe automatic tag indexing and instant cleanup upon task runner settlement.
28
+ - **Declarative Configuration Schema Expansion**:
29
+ - Added `adaptive` policy and `tags` classification to `schema.json` and `config.ahko.example.json`.
30
+ - **New Runnable Examples**:
31
+ - `examples/09-batch-collections.mjs`: Concurrent mapping over iterables with strict index ordering.
32
+ - `examples/10-adaptive-concurrency.mjs`: AIMD Auto-Chill mode reacting to upstream latency.
33
+ - `examples/11-tag-cancellation.mjs`: Tagged workload telemetry and selective cancellation.
34
+
35
+ ---
36
+
37
+ ## [1.1.0] - 2026-09-23 — Declarative Config, Circuit Breaker & Priority Queue
38
+
39
+ ### Added
40
+ - Declarative configuration file support via `config.ahko.json` with multi-profile support (e.g. `default`, `crawler`, `critical-gateway`).
41
+ - Static configuration loaders: `Ahko.loadConfig(config)` for universal programmatic profile loading (Node.js & browser), `Ahko.loadConfigFile(path?)` for asynchronous filesystem loading, and `Ahko.fromProfile(name, overrides?)`.
42
+ - Martin Fowler Circuit Breaker pattern with `ECircuitState` (`CLOSED`, `OPEN`, `HALF_OPEN`), `CircuitBreakerCoordinator`, and `AhkoCircuitBreakerOpenError`:
43
+ - Protects downstream services by tracking consecutive failures against a `failureThreshold`.
44
+ - Fast-fails pending and incoming tasks without execution when OPEN.
45
+ - Automatically transitions to HALF_OPEN after `resetTimeoutMs` cooldown to allow a recovery trial.
46
+ - Heals to CLOSED on trial success or immediately re-trips to OPEN on trial failure.
47
+ - Priority queue scheduling with stable FIFO ordering:
48
+ - Supports named priorities (`"high"`, `"normal"`, `"low"`) and arbitrary numerical weights (e.g. `100`, `-5`).
49
+ - Tasks with higher priority preempt lower priority tasks in the queue; tasks with identical priority preserve strict FIFO ordering.
50
+ - Queue flow control via `ahko.pause()`, `ahko.resume()`, and `ahko.isPaused()`:
51
+ - Halts dispatching pending tasks without interrupting currently executing tasks.
52
+ - Immediately dispatches accumulated tasks upon resume up to concurrency limits.
53
+ - Total Timeout Budget (`totalTimeoutMs`):
54
+ - Sets an overarching execution deadline spanning queue wait time, execution, and retry delays.
55
+ - Cancels task runners cleanly with `AhkoTimeoutError` when the budget expires.
56
+ - Ergonomic function wrapping via `ahko.wrap(fn, options)`:
57
+ - Wraps any sync or async function returning a decorated function routed through the scheduler with pre-configured priorities and options.
58
+ - New runnable examples:
59
+ - `examples/07-circuit-breaker.mjs`: circuit breaker tripping, fast-failing, and cooldown recovery.
60
+ - `examples/08-priority-queue.mjs`: priority queue ordering and pause/resume flow control.
61
+ - `config.ahko.example.json`: reference declarative schema configuration file.
62
+ - Extended telemetry in `ahko.stats()`: `isPaused` boolean and `circuitState` indicator.
63
+
64
+ ### Fixed
65
+ - Remediated 2 CodeQL static analysis security alerts:
66
+ - Alert #4: Removed unused `externalController` declaration in `src/__tests__/e2e.test.ts`.
67
+ - Alert #3: Removed unused `sleep` helper declaration in `examples/04-retry-backoff-jitter.mjs`.
68
+
69
+ ---
70
+
8
71
  ## [1.0.0] - 2026-09-23 — Stable Scheduler Release
9
72
 
10
73
  ### Added
package/README.md CHANGED
@@ -15,6 +15,9 @@
15
15
  <a href="https://www.npmjs.com/package/@mrjacket/ahko">
16
16
  <img src="https://img.shields.io/node/v/@mrjacket/ahko.svg" alt="node">
17
17
  </a>
18
+ <a href="https://www.npmjs.com/package/@mrjacket/ahko">
19
+ <img src="https://img.shields.io/npm/dm/@mrjacket/ahko.svg" alt="npm downloads">
20
+ </a>
18
21
  <a href="https://github.com/x-name15/ahko/actions/workflows/ci.yml">
19
22
  <img src="https://github.com/x-name15/ahko/actions/workflows/ci.yml/badge.svg" alt="ci">
20
23
  </a>
@@ -281,6 +284,182 @@ console.log(ahko.battery());
281
284
  // { level: 3, chill: true, status: "low-energy", quote: "Mwee... my battery is low, but all your tasks are handled completely chill." }
282
285
  ```
283
286
 
287
+ ### 12. Priority-Aware Scheduling
288
+
289
+ Ensure critical tasks jump ahead of normal or background work while preserving strict FIFO ordering among peers:
290
+
291
+ ```typescript
292
+ // Named priorities: "high" (10), "normal" (0), "low" (-10), or custom numeric weights
293
+ await ahko.schedule(criticalTask, { priority: "high" });
294
+ await ahko.schedule(backgroundSync, { priority: "low" });
295
+ await ahko.schedule(superUrgent, { priority: 100 });
296
+ ```
297
+
298
+ ### 13. Circuit Breaker Protection
299
+
300
+ Protect fragile downstream services and databases from cascading failures. When consecutive failures meet `failureThreshold`, the circuit trips to `OPEN` and fast-fails tasks immediately without execution:
301
+
302
+ ```typescript
303
+ const ahko = new Ahko({
304
+ concurrency: 2,
305
+ circuitBreaker: {
306
+ failureThreshold: 3, // trip after 3 consecutive failures
307
+ resetTimeoutMs: 15000, // wait 15s before attempting recovery probe
308
+ },
309
+ });
310
+
311
+ try {
312
+ await ahko.schedule(callFlakyService);
313
+ } catch (err) {
314
+ if (err instanceof AhkoCircuitBreakerOpenError) {
315
+ console.warn("Fast-failed: Circuit breaker is OPEN!");
316
+ }
317
+ }
318
+ ```
319
+
320
+ ### 14. Pause & Resume Flow Control
321
+
322
+ Temporarily halt queue dispatching without aborting in-flight tasks. Resuming immediately pumps accumulated tasks up to capacity:
323
+
324
+ ```typescript
325
+ // Stop dispatching new tasks
326
+ ahko.pause();
327
+ console.log(ahko.isPaused()); // true
328
+
329
+ // In-flight tasks finish peacefully...
330
+
331
+ // Resume dispatching
332
+ ahko.resume();
333
+ ```
334
+
335
+ ### 15. Total Timeout Budget
336
+
337
+ Enforce an overarching deadline spanning queue wait time, execution, and retries:
338
+
339
+ ```typescript
340
+ // Task will abort with AhkoTimeoutError if total elapsed time exceeds 5000ms
341
+ await ahko.schedule(fetchWithRetries, {
342
+ totalTimeoutMs: 5000,
343
+ retry: { attempts: 3, baseDelay: 1000 },
344
+ });
345
+ ```
346
+
347
+ ### 16. Function Wrapping (`ahko.wrap`)
348
+
349
+ Decorate any async function to automatically route every invocation through Ahko:
350
+
351
+ ```typescript
352
+ const fetchUser = ahko.wrap(
353
+ async (userId: string) => {
354
+ const res = await fetch(`https://api.example.com/users/${userId}`);
355
+ return res.json();
356
+ },
357
+ { priority: "high", retry: { attempts: 2 } }
358
+ );
359
+
360
+ // Seamlessly executed via scheduler
361
+ const user = await fetchUser("usr_42");
362
+ ```
363
+
364
+ ### 17. Declarative Configuration (`config.ahko.json`)
365
+
366
+ Define scheduler defaults and workload profiles cleanly in JSON:
367
+
368
+ ```json
369
+ {
370
+ "default": {
371
+ "concurrency": 2,
372
+ "minIntervalMs": 50,
373
+ "priority": "normal"
374
+ },
375
+ "profiles": {
376
+ "crawler": {
377
+ "concurrency": 4,
378
+ "minIntervalMs": 200,
379
+ "priority": "low"
380
+ },
381
+ "critical-gateway": {
382
+ "concurrency": 1,
383
+ "circuitBreaker": {
384
+ "failureThreshold": 3,
385
+ "resetTimeoutMs": 10000
386
+ }
387
+ }
388
+ }
389
+ }
390
+ ```
391
+
392
+ ```typescript
393
+ // Programmatically or from config file:
394
+ Ahko.loadConfig(config);
395
+
396
+ // Instantiate configured scheduler from profile
397
+ const gateway = Ahko.fromProfile("critical-gateway");
398
+ ```
399
+
400
+ ### 18. Batch Collections API (`ahko.map` & `ahko.each`)
401
+
402
+ Transform collections concurrently with strict index order preservation and localized concurrency limits:
403
+
404
+ ```typescript
405
+ const urls = ["/api/users", "/api/posts", "/api/comments"];
406
+
407
+ // Processes concurrently (max 2 at a time), guaranteed return in original order
408
+ const responses = await ahko.map(
409
+ urls,
410
+ async (url, index, { signal }) => {
411
+ const res = await fetch(url, { signal });
412
+ return res.json();
413
+ },
414
+ { concurrency: 2, stopOnError: true }
415
+ );
416
+
417
+ // Or iterate over items returning void:
418
+ await ahko.each(userIds, async (id) => syncUser(id), { concurrency: 5 });
419
+ ```
420
+
421
+ ### 19. Dynamic & Adaptive Concurrency (AIMD Auto-Chill)
422
+
423
+ Adjust concurrency dynamically on the fly or let Ahko adapt automatically to network latency:
424
+
425
+ ```typescript
426
+ // Manually update concurrency at runtime:
427
+ ahko.setConcurrency(5);
428
+ console.log(ahko.concurrency); // 5
429
+
430
+ // Or enable AIMD (Additive Increase / Multiplicative Decrease) Auto-Chill mode:
431
+ const adaptiveAhko = new Ahko({
432
+ concurrency: 4,
433
+ adaptive: {
434
+ targetLatencyMs: 150, // if tasks take >150ms, cut concurrency in half
435
+ sampleWindowSize: 5, // adjust after every 5 completed tasks
436
+ minConcurrency: 1,
437
+ maxConcurrency: 10,
438
+ backoffFactor: 0.5,
439
+ },
440
+ });
441
+
442
+ adaptiveAhko.on("concurrency:change", ({ previousConcurrency, currentConcurrency, reason }) => {
443
+ console.log(`Capacity adapted: ${previousConcurrency} -> ${currentConcurrency} (${reason})`);
444
+ });
445
+ ```
446
+
447
+ ### 20. Task Tags & Selective Cancellation
448
+
449
+ Classify tasks by tags, query categorical telemetry, and selectively cancel specific operations:
450
+
451
+ ```typescript
452
+ // Tag tasks during scheduling:
453
+ ahko.schedule(generateReport, { tags: ["reports", "finance"] });
454
+ ahko.schedule(syncDatabase, { tags: ["sync"] });
455
+
456
+ // Check active and pending tasks by tag:
457
+ console.log(ahko.statsByTag("reports")); // { activeTasks: 1, pendingTasks: 0 }
458
+
459
+ // Cancel all tasks associated with a tag without affecting other tasks:
460
+ ahko.cancelByTag("reports", "User navigated away");
461
+ ```
462
+
284
463
  ---
285
464
 
286
465
  ## Documentation
@@ -291,10 +470,11 @@ Comprehensive guides and technical documentation are available in the [`docs/`](
291
470
  |---|---|
292
471
  | [**Documentation Portal**](./docs/README.md) | Master overview and index of all guides and specifications. |
293
472
  | [**Getting Started**](./docs/guides/getting-started.md) | Quickstart guide, installation, and fundamental usage patterns. |
473
+ | [**Declarative Configuration**](./docs/guides/configuration.md) | Centralizing limits in `config.ahko.json`, `$schema` validation, named profiles, and fallback rules. |
294
474
  | [**Library API**](./docs/guides/library.md) | Complete programmatic API reference, TypeScript interfaces, and options. |
295
475
  | [**Production Recipes**](./docs/guides/recipes.md) | Battle-tested recipes (paced API client, debounced search, throttled scroll, graceful shutdown). |
296
476
  | [**Architecture**](./docs/architecture/ARCHITECTURE.md) | Architectural specifications, lifecycle state machine, and design decisions. |
297
- | [**Roadmap**](./docs/architecture/ROADMAP.md) | Milestone progression from 0.1.0 through 1.0.0. |
477
+ | [**Roadmap**](./docs/architecture/ROADMAP.md) | Milestone progression from 0.1.0 through 1.1.0. |
298
478
  | [**Engineering Log**](./docs/architecture/LOG.md) | Chronological log of engineering decisions and ADRs. |
299
479
 
300
480
  > **Runnable Examples:** A comprehensive suite of standalone, runnable Node.js scripts is available in the [`examples/`](./examples/) folder. See [`examples/README.md`](./examples/README.md) for details.
@@ -311,6 +491,33 @@ Creates an ahko scheduler instance.
311
491
  |---|---|---|---|
312
492
  | `concurrency` | `number` | `Infinity` | Maximum concurrent tasks allowed to run simultaneously. Must be $\ge 1$. |
313
493
  | `minIntervalMs` | `number` | `0` | Minimum interval in milliseconds between consecutive task starts. Must be $\ge 0$. |
494
+ | `circuitBreaker` | `ICircuitBreakerOptions` | `undefined` | Optional failure threshold and cooldown reset configuration. |
495
+ | `adaptive` | `IAdaptiveConcurrencyOptions` | `undefined` | Optional AIMD adaptive concurrency options based on task execution latency. |
496
+ | `profile` | `string` | `undefined` | Name of declarative profile to inherit settings from. |
497
+
498
+ ### `ahko.concurrency`
499
+
500
+ Getter returning the current concurrency capacity limit.
501
+
502
+ ### `ahko.setConcurrency(newConcurrency: number): void`
503
+
504
+ Dynamically updates the concurrency limit of the scheduler at runtime.
505
+
506
+ ### `ahko.map<TItem, TResult>(items, fn, options?): Promise<TResult[]>`
507
+
508
+ Concurrently transforms an iterable sequence into an array with strict index ordering. Supports localized `concurrency` limits and `stopOnError`.
509
+
510
+ ### `ahko.each<TItem>(items, fn, options?): Promise<void>`
511
+
512
+ Iterates over an iterable sequence concurrently, executing the callback for each element.
513
+
514
+ ### `ahko.cancelByTag(tag: string, reason?: unknown): number`
515
+
516
+ Cancels all pending, delayed, and active tasks marked with the specified tag. Returns the number of cancelled tasks.
517
+
518
+ ### `ahko.statsByTag(tag: string): { activeTasks: number; pendingTasks: number }`
519
+
520
+ Returns active and pending task counts for a specific classification tag.
314
521
 
315
522
  ### `ahko.schedule<T>(task: ITask<T>, options?: IScheduleOptions): Promise<T>`
316
523
 
@@ -319,29 +526,44 @@ Schedules an asynchronous task with full return type inference.
319
526
  | Option | Type | Default | Description |
320
527
  |---|---|---|---|
321
528
  | `strategy` | `"immediate" \| "delay" \| "idle" \| "throttle" \| "debounce"` | `"immediate"` | Scheduling execution strategy. |
529
+ | `priority` | `"high" \| "normal" \| "low" \| number` | `"normal"` | Task priority weight for queue ordering. |
322
530
  | `delay` | `number` | `0` | Delay in milliseconds when strategy is `"delay"`. |
323
531
  | `key` | `string \| symbol` | `undefined` | Explicit identity key for `"debounce"` and `"throttle"`. |
324
532
  | `waitMs` | `number` | `undefined` | Window duration in ms for debounce quiet period or throttle interval. |
325
533
  | `idleTimeout` | `number` | `undefined` | Maximum time to wait for idle window before forcing queue entry. |
326
534
  | `retry` | `IRetryOptions` | `undefined` | Automatic retry policy (attempts, backoff, jitter, predicate). |
327
535
  | `timeoutMs` | `number` | `undefined` | Maximum execution duration in milliseconds per attempt before aborting with `AhkoTimeoutError`. |
536
+ | `totalTimeoutMs` | `number` | `undefined` | Total execution budget across wait time, retries, and execution. |
328
537
  | `signal` | `AbortSignal` | `undefined` | Optional external `AbortSignal` for cooperative cancellation. |
538
+ | `tags` | `string[]` | `undefined` | Classification tags for selective cancellation and metric grouping. |
539
+
540
+ ### `ahko.wrap(fn, options?)`
541
+
542
+ Returns a wrapped version of `fn` routed through the scheduler.
543
+
544
+ ### `ahko.pause() / ahko.resume() / ahko.isPaused()`
545
+
546
+ Pauses and resumes task dispatching.
547
+
548
+ ### `ahko.circuitState`
549
+
550
+ Returns current circuit breaker state (`"closed" | "open" | "half_open"` or `undefined`).
329
551
 
330
- ### `ahko.debounce<T>(key: string | symbol, task: ITask<T>, waitMs: number, options?: IScheduleOptions): Promise<T>`
552
+ ### `ahko.debounce<T>(key, task, waitMs, options?): Promise<T>`
331
553
 
332
554
  Convenience method scheduling a debounced task with key-based Promise coalescing.
333
555
 
334
- ### `ahko.throttle<T>(key: string | symbol, task: ITask<T>, waitMs: number, options?: IScheduleOptions): Promise<T>`
556
+ ### `ahko.throttle<T>(key, task, waitMs, options?): Promise<T>`
335
557
 
336
558
  Convenience method scheduling a throttled task with leading execution and coalesced trailing run.
337
559
 
338
- ### `ahko.idle<T>(task: ITask<T>, options?: Omit<IScheduleOptions, "strategy">): Promise<T>`
560
+ ### `ahko.idle<T>(task, options?): Promise<T>`
339
561
 
340
562
  Convenience method scheduling a task under `strategy: "idle"`.
341
563
 
342
564
  ### `ahko.on(event, handler)`
343
565
 
344
- Subscribes to scheduler lifecycle events (`task:start`, `task:complete`, `task:fail`, `task:cancel`, `task:timeout`, `idle`). Returns an unsubscribe function.
566
+ Subscribes to scheduler lifecycle events (`task:start`, `task:complete`, `task:fail`, `task:cancel`, `task:timeout`, `idle`, `concurrency:change`). Returns an unsubscribe function.
345
567
 
346
568
  ### `ahko.off(event, handler)`
347
569
 
@@ -369,7 +591,7 @@ Returns mascot battery status and quote.
369
591
 
370
592
  ### `ahko.stats(): IAhkoStats`
371
593
 
372
- Returns a snapshot of current task counters, retry counts, total dispatches, and queue capacity.
594
+ Returns a snapshot of current task counters, retry counts, total dispatches, pause status, circuit state, and queue capacity.
373
595
 
374
596
  ---
375
597
 
@@ -381,7 +603,8 @@ All scheduler errors inherit from `AhkoError`:
381
603
  - `AhkoCancellationError`: Thrown when a task is aborted.
382
604
  - `AhkoConfigurationError`: Thrown when invalid options are provided.
383
605
  - `AhkoQueueError`: Thrown when queue constraints are violated.
384
- - `AhkoTimeoutError`: Thrown when a task exceeds its configured duration.
606
+ - `AhkoTimeoutError`: Thrown when a task exceeds its configured duration or totalTimeoutMs.
607
+ - `AhkoCircuitBreakerOpenError`: Thrown when task execution is fast-failed because the circuit breaker is OPEN.
385
608
 
386
609
  ---
387
610
 
package/dist/ahko.d.ts CHANGED
@@ -1,12 +1,18 @@
1
+ import type { IBatchOptions, IBatchMapOptions } from "./models/batch.model.js";
2
+ import type { ECircuitState } from "./models/circuit-breaker.model.js";
3
+ import type { IAhkoFileConfig } from "./models/config.model.js";
4
+ import type { ITaskContext } from "./models/context.model.js";
1
5
  import type { TAhkoEventName, TAhkoEventHandler, TAhkoUnsubscribe } from "./models/events.model.js";
2
6
  import type { IAhkoOptions, IScheduleOptions } from "./models/options.model.js";
3
7
  import type { IAhkoStats } from "./models/stats.model.js";
4
8
  import type { ITask } from "./models/task.model.js";
9
+ import type { CircuitBreakerCoordinator } from "./scheduler/circuit-breaker.js";
5
10
  /**
6
11
  * Ahko — Low-energy asynchronous task scheduler.
7
12
  *
8
- * Coordinates execution timing, enforces concurrency limits, and cooperates
9
- * natively with AbortSignal cancellation.
13
+ * Coordinates execution timing, enforces concurrency limits, manages priorities,
14
+ * provides circuit-breaker stability, supports pause/resume flow control,
15
+ * and cooperates natively with AbortSignal cancellation.
10
16
  *
11
17
  * @example
12
18
  * ```typescript
@@ -23,6 +29,37 @@ import type { ITask } from "./models/task.model.js";
23
29
  export declare class Ahko {
24
30
  /** Internal queue and concurrency manager */
25
31
  private readonly queue;
32
+ /** Default schedule options inherited from profile if configured */
33
+ private readonly defaultScheduleOptions?;
34
+ /**
35
+ * Programmatically loads a declarative configuration into memory.
36
+ * Works universally across Node.js, browsers, and edge runtimes.
37
+ *
38
+ * @param config - File configuration object containing default and named profiles.
39
+ */
40
+ static loadConfig(config: IAhkoFileConfig): void;
41
+ /**
42
+ * Asynchronously loads a configuration file from disk (Node.js).
43
+ *
44
+ * @param filePath - Path to configuration file (default: "config.ahko.json").
45
+ */
46
+ static loadConfigFile(filePath?: string): Promise<IAhkoFileConfig | undefined>;
47
+ /**
48
+ * Resets the active declarative configuration.
49
+ */
50
+ static resetConfig(): void;
51
+ /**
52
+ * Retrieves the currently active declarative configuration.
53
+ */
54
+ static getActiveConfig(): IAhkoFileConfig | undefined;
55
+ /**
56
+ * Instantiates an Ahko scheduler initialized with settings from a declarative profile.
57
+ *
58
+ * @param profileName - Optional name of the profile (e.g. "api", "background").
59
+ * @param overrides - Optional scheduler options overriding profile values.
60
+ * @returns A new configured Ahko instance.
61
+ */
62
+ static fromProfile(profileName?: string, overrides?: IAhkoOptions): Ahko;
26
63
  /**
27
64
  * Initializes a new Ahko scheduler instance.
28
65
  *
@@ -35,28 +72,73 @@ export declare class Ahko {
35
72
  * ```
36
73
  */
37
74
  constructor(options?: IAhkoOptions);
75
+ /**
76
+ * Current concurrency limit.
77
+ */
78
+ get concurrency(): number;
79
+ /**
80
+ * Dynamically updates the concurrency limit of the scheduler.
81
+ *
82
+ * @param concurrency - New maximum concurrency (must be >= 1).
83
+ * @throws {AhkoConfigurationError} If concurrency is invalid.
84
+ */
85
+ setConcurrency(concurrency: number): void;
86
+ /**
87
+ * Pauses scheduler dispatch. In-flight tasks run to completion, but pending tasks remain queued.
88
+ */
89
+ pause(): void;
90
+ /**
91
+ * Resumes scheduler dispatch, immediately executing waiting tasks up to available concurrency.
92
+ */
93
+ resume(): void;
94
+ /**
95
+ * Checks whether the scheduler is currently paused.
96
+ */
97
+ isPaused(): boolean;
98
+ /**
99
+ * Current circuit breaker state if circuit breaker protection is configured.
100
+ */
101
+ get circuitState(): ECircuitState | undefined;
102
+ /**
103
+ * Access to the underlying circuit breaker coordinator instance if configured.
104
+ */
105
+ get circuitBreaker(): CircuitBreakerCoordinator | undefined;
106
+ /**
107
+ * Wraps an async function so every execution is automatically routed through this Ahko scheduler.
108
+ *
109
+ * @template TArgs - Parameter types of the wrapped function.
110
+ * @template TReturn - Return type of the wrapped function.
111
+ * @param fn - The function to wrap.
112
+ * @param options - Optional scheduling options applied to every wrapped call.
113
+ * @returns A wrapped function returning a Promise.
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * const fetchUser = ahko.wrap(async (id: string) => api.getUser(id), { priority: "high" });
118
+ * const user = await fetchUser("usr_123");
119
+ * ```
120
+ */
121
+ wrap<TArgs extends unknown[], TReturn>(fn: (...args: TArgs) => Promise<TReturn> | TReturn, options?: IScheduleOptions): (...args: TArgs) => Promise<TReturn>;
38
122
  /**
39
123
  * Schedules a task for execution with full return type inference.
40
124
  *
41
125
  * @template T - Inferred return type of the task.
42
126
  * @param task - Asynchronous or synchronous task function accepting an {@link ITaskContext}.
43
- * @param options - Task-specific scheduling options such as strategy, delay, and cancellation signal.
127
+ * @param options - Task-specific scheduling options such as strategy, priority, delay, and cancellation signal.
44
128
  * @returns A promise that resolves with the task's return value.
45
129
  *
46
130
  * @throws {AhkoConfigurationError} If the task is not a function or options are invalid.
47
131
  * @throws {AhkoCancellationError} If the task is cancelled prior to or during execution.
48
- * @throws {AhkoTimeoutError} If task execution exceeds timeoutMs.
132
+ * @throws {AhkoTimeoutError} If task execution exceeds timeoutMs or totalTimeoutMs.
133
+ * @throws {AhkoCircuitBreakerOpenError} If the circuit breaker is OPEN and rejects the execution.
49
134
  *
50
135
  * @example
51
136
  * ```typescript
52
137
  * // Immediate execution (subject to concurrency)
53
138
  * const count = await ahko.schedule(async () => 42);
54
139
  *
55
- * // Delayed execution
56
- * await ahko.schedule(
57
- * async ({ signal }) => doWork({ signal }),
58
- * { strategy: "delay", delay: 1000 }
59
- * );
140
+ * // High priority task
141
+ * await ahko.schedule(doUrgentWork, { priority: "high" });
60
142
  * ```
61
143
  */
62
144
  schedule<T>(task: ITask<T>, options?: IScheduleOptions): Promise<T>;
@@ -99,15 +181,77 @@ export declare class Ahko {
99
181
  * @returns Promise resolving with the leading or coalesced trailing result.
100
182
  */
101
183
  throttle<T>(key: string | symbol, task: ITask<T>, waitMs: number, options?: Omit<IScheduleOptions, "strategy" | "key" | "waitMs">): Promise<T>;
184
+ /**
185
+ * Transforms an iterable of items concurrently using an asynchronous mapping function.
186
+ *
187
+ * Results are guaranteed to be returned in the original index order.
188
+ * Concurrency can be capped per-batch or fall back to the scheduler's global limit.
189
+ *
190
+ * @template TItem - Type of input elements.
191
+ * @template TResult - Type of mapped elements.
192
+ * @param items - Iterable sequence of items to process.
193
+ * @param fn - Mapper callback receiving item, index, and task context.
194
+ * @param options - Batch execution options (concurrency, stopOnError, retry, signal, tags, etc.).
195
+ * @returns Array of transformed results in index order.
196
+ *
197
+ * @throws {AhkoConfigurationError} If fn is not a function or concurrency is invalid.
198
+ * @throws {AhkoCancellationError} If batch or item is cancelled.
199
+ *
200
+ * @example
201
+ * ```typescript
202
+ * const urls = ["/api/1", "/api/2", "/api/3"];
203
+ * const data = await ahko.map(urls, async (url, i, { signal }) => {
204
+ * const res = await fetch(url, { signal });
205
+ * return res.json();
206
+ * }, { concurrency: 2 });
207
+ * ```
208
+ */
209
+ map<TItem, TResult>(items: Iterable<TItem>, fn: (item: TItem, index: number, context: ITaskContext) => Promise<TResult> | TResult, options?: IBatchMapOptions<TItem, TResult>): Promise<TResult[]>;
210
+ /**
211
+ * Iterates sequentially or concurrently over an iterable sequence of items,
212
+ * executing the callback function for each element.
213
+ *
214
+ * @template TItem - Type of input elements.
215
+ * @param items - Iterable sequence of items to process.
216
+ * @param fn - Callback receiving item, index, and task context.
217
+ * @param options - Batch execution options.
218
+ * @returns Promise resolving once all items have finished executing.
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * await ahko.each(userQueue, async (user, index, { signal }) => {
223
+ * await sendWelcomeEmail(user, { signal });
224
+ * }, { concurrency: 5 });
225
+ * ```
226
+ */
227
+ each<TItem>(items: Iterable<TItem>, fn: (item: TItem, index: number, context: ITaskContext) => Promise<void> | void, options?: IBatchOptions): Promise<void>;
228
+ /**
229
+ * Cancels all pending, delayed, and active tasks tagged with the given tag.
230
+ *
231
+ * @param tag - Tag identifier.
232
+ * @param reason - Optional cancellation reason.
233
+ * @returns Total number of tasks cancelled.
234
+ */
235
+ cancelByTag(tag: string, reason?: unknown): number;
236
+ /**
237
+ * Retrieves active and pending task counts for a given tag.
238
+ *
239
+ * @param tag - Tag identifier.
240
+ * @returns Object with activeTasks and pendingTasks counts.
241
+ */
242
+ statsByTag(tag: string): {
243
+ activeTasks: number;
244
+ pendingTasks: number;
245
+ };
102
246
  /**
103
247
  * Retrieves real-time telemetry metrics from the scheduler.
104
248
  *
105
- * @returns An {@link IAhkoStats} snapshot of active, pending, completed, failed, cancelled, and timed out tasks.
249
+ * @returns An {@link IAhkoStats} snapshot of active, pending, completed, failed, cancelled, timed out tasks, pause status, and circuit state.
106
250
  *
107
251
  * @example
108
252
  * ```typescript
109
253
  * const stats = ahko.stats();
110
- * console.log(`Active: ${stats.activeTasks}, Pending: ${stats.pendingTasks}`);
254
+ * console.log(`Active: ${stats.activeTasks}, Pending: ${stats.pendingTasks}, Paused: ${stats.isPaused}`);
111
255
  * ```
112
256
  */
113
257
  stats(): IAhkoStats;
@@ -0,0 +1,31 @@
1
+ import type { IAhkoFileConfig, IAhkoProfileConfig } from "../models/config.model.js";
2
+ /**
3
+ * Programmatically loads and activates a declarative configuration.
4
+ * Universal across Node.js, browsers, and edge environments.
5
+ *
6
+ * @param config - Complete configuration object conforming to `IAhkoFileConfig`.
7
+ */
8
+ export declare function loadConfig(config: IAhkoFileConfig): void;
9
+ /**
10
+ * Resets the currently active configuration in memory to undefined.
11
+ */
12
+ export declare function resetConfig(): void;
13
+ /**
14
+ * Asynchronously loads a `config.ahko.json` or custom config file from the filesystem in Node.js.
15
+ * Sets the active configuration in memory upon successful read and parse.
16
+ *
17
+ * @param filePath - Optional relative or absolute path to the configuration file (default: "config.ahko.json").
18
+ * @returns The parsed configuration object, or `undefined` if not running in Node.js or if file cannot be read.
19
+ */
20
+ export declare function loadConfigFile(filePath?: string): Promise<IAhkoFileConfig | undefined>;
21
+ /**
22
+ * Returns the currently active declarative configuration, attempting auto-discovery if in Node.js.
23
+ */
24
+ export declare function getActiveConfig(): IAhkoFileConfig | undefined;
25
+ /**
26
+ * Retrieves a specific profile configuration by name, or the default profile if no name is provided.
27
+ *
28
+ * @param profileName - Optional name of the profile (e.g. "api", "background").
29
+ * @returns The profile configuration if defined, or undefined.
30
+ */
31
+ export declare function getProfileConfig(profileName?: string): IAhkoProfileConfig | undefined;
@@ -0,0 +1 @@
1
+ export { loadConfig, resetConfig, loadConfigFile, getActiveConfig, getProfileConfig, } from "./config-loader.js";
@@ -0,0 +1,24 @@
1
+ import { AhkoError } from "./ahko.error.js";
2
+ /**
3
+ * Options describing the circuit breaker open state.
4
+ */
5
+ export interface IAhkoCircuitBreakerErrorOptions {
6
+ /** Time remaining in milliseconds before the circuit attempts half-open trial */
7
+ resetTimeoutMs?: number;
8
+ /** Timestamp when the circuit tripped open */
9
+ trippedAt?: number;
10
+ /** Consecutive failures that caused the trip */
11
+ consecutiveFailures?: number;
12
+ }
13
+ /**
14
+ * Thrown when attempting to execute a task while the scheduler's circuit breaker is in OPEN state.
15
+ */
16
+ export declare class AhkoCircuitBreakerOpenError extends AhkoError {
17
+ /** Time remaining in milliseconds before trial execution is allowed */
18
+ readonly resetTimeoutMs?: number;
19
+ /** Timestamp when the circuit tripped open */
20
+ readonly trippedAt?: number;
21
+ /** Total consecutive failures that caused the trip */
22
+ readonly consecutiveFailures?: number;
23
+ constructor(message?: string, options?: IAhkoCircuitBreakerErrorOptions);
24
+ }
@@ -3,3 +3,4 @@ export * from "./cancellation.error.js";
3
3
  export * from "./configuration.error.js";
4
4
  export * from "./queue.error.js";
5
5
  export * from "./timeout.error.js";
6
+ export * from "./circuit-breaker.error.js";