@mrjacket/ahko 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/README.md +103 -5
- package/dist/ahko.d.ts +64 -0
- package/dist/events/event-emitter.d.ts +34 -0
- package/dist/events/index.d.ts +1 -0
- package/dist/index.cjs +313 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +313 -3
- package/dist/index.js.map +1 -1
- package/dist/models/events.model.d.ts +50 -0
- package/dist/models/index.d.ts +1 -0
- package/dist/models/stats.model.d.ts +4 -0
- package/dist/scheduler/task-queue.d.ts +30 -0
- package/dist/scheduler/task-runner.d.ts +2 -0
- package/dist/version.d.ts +1 -1
- package/package.json +6 -1
package/dist/index.cjs
CHANGED
|
@@ -278,7 +278,7 @@ var DebounceCoordinator = class {
|
|
|
278
278
|
* Cancels all pending debounced entries and clears the map.
|
|
279
279
|
*/
|
|
280
280
|
clear() {
|
|
281
|
-
for (const
|
|
281
|
+
for (const entry of this.entries.values()) {
|
|
282
282
|
clearTimeout(entry.timerId);
|
|
283
283
|
if (entry.options?.signal && entry.abortListener) {
|
|
284
284
|
entry.options.signal.removeEventListener("abort", entry.abortListener);
|
|
@@ -450,7 +450,7 @@ var ThrottleCoordinator = class {
|
|
|
450
450
|
* Clears all throttled entries and timers.
|
|
451
451
|
*/
|
|
452
452
|
clear() {
|
|
453
|
-
for (const
|
|
453
|
+
for (const entry of this.entries.values()) {
|
|
454
454
|
if (entry.windowTimerId !== void 0) {
|
|
455
455
|
clearTimeout(entry.windowTimerId);
|
|
456
456
|
}
|
|
@@ -462,6 +462,74 @@ var ThrottleCoordinator = class {
|
|
|
462
462
|
}
|
|
463
463
|
};
|
|
464
464
|
|
|
465
|
+
// src/events/event-emitter.ts
|
|
466
|
+
var AhkoEventEmitter = class {
|
|
467
|
+
listeners = /* @__PURE__ */ new Map();
|
|
468
|
+
/**
|
|
469
|
+
* Subscribes a listener to a specific Ahko lifecycle event.
|
|
470
|
+
*
|
|
471
|
+
* @param event - The event name to subscribe to.
|
|
472
|
+
* @param handler - The callback function to invoke when the event is emitted.
|
|
473
|
+
* @returns An unsubscribe function to remove the listener.
|
|
474
|
+
*/
|
|
475
|
+
on(event, handler) {
|
|
476
|
+
let set = this.listeners.get(event);
|
|
477
|
+
if (!set) {
|
|
478
|
+
set = /* @__PURE__ */ new Set();
|
|
479
|
+
this.listeners.set(event, set);
|
|
480
|
+
}
|
|
481
|
+
set.add(handler);
|
|
482
|
+
return () => {
|
|
483
|
+
this.off(event, handler);
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Unsubscribes a listener from a specific Ahko lifecycle event.
|
|
488
|
+
*
|
|
489
|
+
* @param event - The event name.
|
|
490
|
+
* @param handler - The callback function to remove.
|
|
491
|
+
*/
|
|
492
|
+
off(event, handler) {
|
|
493
|
+
const set = this.listeners.get(event);
|
|
494
|
+
if (set) {
|
|
495
|
+
set.delete(handler);
|
|
496
|
+
if (set.size === 0) {
|
|
497
|
+
this.listeners.delete(event);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Emits an event with the corresponding typed payload to all subscribed listeners.
|
|
503
|
+
* Listener invocations are safely isolated in try/catch to protect scheduler integrity.
|
|
504
|
+
*
|
|
505
|
+
* @param event - The event name to emit.
|
|
506
|
+
* @param payload - The event-specific payload data.
|
|
507
|
+
*/
|
|
508
|
+
emit(event, payload) {
|
|
509
|
+
const set = this.listeners.get(event);
|
|
510
|
+
if (!set || set.size === 0) {
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
const handlers = Array.from(set);
|
|
514
|
+
for (const handler of handlers) {
|
|
515
|
+
try {
|
|
516
|
+
const result = handler(payload);
|
|
517
|
+
if (result && typeof result.catch === "function") {
|
|
518
|
+
result.catch(() => {
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
} catch {
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Removes all registered event listeners.
|
|
527
|
+
*/
|
|
528
|
+
clear() {
|
|
529
|
+
this.listeners.clear();
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
|
|
465
533
|
// src/scheduler/task-queue.ts
|
|
466
534
|
var TaskQueue = class {
|
|
467
535
|
/** Maximum concurrent active tasks */
|
|
@@ -486,6 +554,10 @@ var TaskQueue = class {
|
|
|
486
554
|
debounceCoordinator = new DebounceCoordinator();
|
|
487
555
|
/** Coordinator for throttled tasks with leading/trailing coalescing */
|
|
488
556
|
throttleCoordinator = new ThrottleCoordinator();
|
|
557
|
+
/** Lifecycle event emitter for task and scheduler events */
|
|
558
|
+
emitter = new AhkoEventEmitter();
|
|
559
|
+
/** Set of pending resolvers awaiting scheduler idle transition */
|
|
560
|
+
idleResolvers = /* @__PURE__ */ new Set();
|
|
489
561
|
/** WeakMap associating task runners with their scheduling options */
|
|
490
562
|
runnerOptions = /* @__PURE__ */ new WeakMap();
|
|
491
563
|
/** Cumulative completed tasks counter */
|
|
@@ -496,6 +568,10 @@ var TaskQueue = class {
|
|
|
496
568
|
cancelledTasks = 0;
|
|
497
569
|
/** Cumulative timed out tasks counter */
|
|
498
570
|
timedOutTasks = 0;
|
|
571
|
+
/** Cumulative count of retry attempts triggered */
|
|
572
|
+
retriedTasks = 0;
|
|
573
|
+
/** Cumulative count of tasks dispatched to concurrency slots */
|
|
574
|
+
totalDispatched = 0;
|
|
499
575
|
/**
|
|
500
576
|
* Creates a new TaskQueue.
|
|
501
577
|
*
|
|
@@ -601,6 +677,11 @@ var TaskQueue = class {
|
|
|
601
677
|
if (index !== -1) {
|
|
602
678
|
this.queue.splice(index, 1);
|
|
603
679
|
this.cancelledTasks++;
|
|
680
|
+
this.emitter.emit("task:cancel", {
|
|
681
|
+
taskId: runner.taskId,
|
|
682
|
+
reason: "Task cancelled while queued"
|
|
683
|
+
});
|
|
684
|
+
this.checkIdle();
|
|
604
685
|
}
|
|
605
686
|
};
|
|
606
687
|
this.queue.push(runner);
|
|
@@ -624,6 +705,11 @@ var TaskQueue = class {
|
|
|
624
705
|
if (index !== -1) {
|
|
625
706
|
this.queue.splice(index, 1);
|
|
626
707
|
this.cancelledTasks++;
|
|
708
|
+
this.emitter.emit("task:cancel", {
|
|
709
|
+
taskId: runner.taskId,
|
|
710
|
+
reason: "Task cancelled while queued"
|
|
711
|
+
});
|
|
712
|
+
this.checkIdle();
|
|
627
713
|
}
|
|
628
714
|
};
|
|
629
715
|
this.queue.push(runner);
|
|
@@ -636,6 +722,11 @@ var TaskQueue = class {
|
|
|
636
722
|
clearTimeout(delayedEntry.timerId);
|
|
637
723
|
this.delayedEntries.delete(delayedEntry);
|
|
638
724
|
this.cancelledTasks++;
|
|
725
|
+
this.emitter.emit("task:cancel", {
|
|
726
|
+
taskId: runner.taskId,
|
|
727
|
+
reason: "Task cancelled while waiting in delay"
|
|
728
|
+
});
|
|
729
|
+
this.checkIdle();
|
|
639
730
|
}
|
|
640
731
|
};
|
|
641
732
|
}
|
|
@@ -655,6 +746,11 @@ var TaskQueue = class {
|
|
|
655
746
|
if (index !== -1) {
|
|
656
747
|
this.queue.splice(index, 1);
|
|
657
748
|
this.cancelledTasks++;
|
|
749
|
+
this.emitter.emit("task:cancel", {
|
|
750
|
+
taskId: runner.taskId,
|
|
751
|
+
reason: "Task cancelled while queued"
|
|
752
|
+
});
|
|
753
|
+
this.checkIdle();
|
|
658
754
|
}
|
|
659
755
|
};
|
|
660
756
|
this.queue.push(runner);
|
|
@@ -667,6 +763,11 @@ var TaskQueue = class {
|
|
|
667
763
|
handle.cancel();
|
|
668
764
|
this.idleEntries.delete(idleEntry);
|
|
669
765
|
this.cancelledTasks++;
|
|
766
|
+
this.emitter.emit("task:cancel", {
|
|
767
|
+
taskId: runner.taskId,
|
|
768
|
+
reason: "Task cancelled while waiting for idle"
|
|
769
|
+
});
|
|
770
|
+
this.checkIdle();
|
|
670
771
|
}
|
|
671
772
|
};
|
|
672
773
|
}
|
|
@@ -735,36 +836,69 @@ var TaskQueue = class {
|
|
|
735
836
|
*/
|
|
736
837
|
async executeRunner(runner) {
|
|
737
838
|
const options = this.runnerOptions.get(runner);
|
|
839
|
+
this.totalDispatched++;
|
|
840
|
+
this.emitter.emit("task:start", {
|
|
841
|
+
taskId: runner.taskId,
|
|
842
|
+
attempt: runner.attempt
|
|
843
|
+
});
|
|
738
844
|
try {
|
|
739
845
|
const result = await runner.run();
|
|
740
846
|
this.completedTasks++;
|
|
741
847
|
this.activeRunners.delete(runner);
|
|
742
848
|
this.runnerOptions.delete(runner);
|
|
849
|
+
this.emitter.emit("task:complete", {
|
|
850
|
+
taskId: runner.taskId,
|
|
851
|
+
attempt: runner.attempt,
|
|
852
|
+
durationMs: runner.lastDurationMs,
|
|
853
|
+
result
|
|
854
|
+
});
|
|
743
855
|
runner.resolve(result);
|
|
744
856
|
} catch (error) {
|
|
745
857
|
if (runner.state === "cancelled" /* CANCELLED */) {
|
|
746
858
|
this.cancelledTasks++;
|
|
747
859
|
this.activeRunners.delete(runner);
|
|
748
860
|
this.runnerOptions.delete(runner);
|
|
861
|
+
this.emitter.emit("task:cancel", {
|
|
862
|
+
taskId: runner.taskId,
|
|
863
|
+
reason: error
|
|
864
|
+
});
|
|
749
865
|
runner.reject(error);
|
|
750
866
|
return;
|
|
751
867
|
}
|
|
752
868
|
const shouldRetry = await runner.canRetry(error, options?.retry);
|
|
753
869
|
if (shouldRetry) {
|
|
870
|
+
this.retriedTasks++;
|
|
754
871
|
this.activeRunners.delete(runner);
|
|
872
|
+
this.emitter.emit("task:fail", {
|
|
873
|
+
taskId: runner.taskId,
|
|
874
|
+
attempt: runner.attempt - 1,
|
|
875
|
+
error,
|
|
876
|
+
willRetry: true
|
|
877
|
+
});
|
|
755
878
|
this.scheduleRetry(runner, options);
|
|
756
879
|
return;
|
|
757
880
|
}
|
|
758
881
|
if (runner.state === "timed_out" /* TIMED_OUT */ || error instanceof AhkoTimeoutError) {
|
|
759
882
|
this.timedOutTasks++;
|
|
883
|
+
this.emitter.emit("task:timeout", {
|
|
884
|
+
taskId: runner.taskId,
|
|
885
|
+
timeoutMs: runner.timeoutMs
|
|
886
|
+
});
|
|
760
887
|
} else {
|
|
761
888
|
this.failedTasks++;
|
|
762
889
|
}
|
|
763
890
|
this.activeRunners.delete(runner);
|
|
764
891
|
this.runnerOptions.delete(runner);
|
|
892
|
+
this.emitter.emit("task:fail", {
|
|
893
|
+
taskId: runner.taskId,
|
|
894
|
+
attempt: runner.attempt,
|
|
895
|
+
error,
|
|
896
|
+
willRetry: false
|
|
897
|
+
});
|
|
765
898
|
runner.reject(error);
|
|
766
899
|
} finally {
|
|
767
900
|
this.pump();
|
|
901
|
+
this.checkIdle();
|
|
768
902
|
}
|
|
769
903
|
}
|
|
770
904
|
/**
|
|
@@ -779,6 +913,11 @@ var TaskQueue = class {
|
|
|
779
913
|
if (index !== -1) {
|
|
780
914
|
this.queue.splice(index, 1);
|
|
781
915
|
this.cancelledTasks++;
|
|
916
|
+
this.emitter.emit("task:cancel", {
|
|
917
|
+
taskId: runner.taskId,
|
|
918
|
+
reason: "Task cancelled while queued"
|
|
919
|
+
});
|
|
920
|
+
this.checkIdle();
|
|
782
921
|
}
|
|
783
922
|
};
|
|
784
923
|
this.queue.push(runner);
|
|
@@ -797,6 +936,11 @@ var TaskQueue = class {
|
|
|
797
936
|
if (index !== -1) {
|
|
798
937
|
this.queue.splice(index, 1);
|
|
799
938
|
this.cancelledTasks++;
|
|
939
|
+
this.emitter.emit("task:cancel", {
|
|
940
|
+
taskId: runner.taskId,
|
|
941
|
+
reason: "Task cancelled while queued"
|
|
942
|
+
});
|
|
943
|
+
this.checkIdle();
|
|
800
944
|
}
|
|
801
945
|
};
|
|
802
946
|
this.queue.push(runner);
|
|
@@ -809,9 +953,91 @@ var TaskQueue = class {
|
|
|
809
953
|
clearTimeout(retryEntry.timerId);
|
|
810
954
|
this.retryEntries.delete(retryEntry);
|
|
811
955
|
this.cancelledTasks++;
|
|
956
|
+
this.emitter.emit("task:cancel", {
|
|
957
|
+
taskId: runner.taskId,
|
|
958
|
+
reason: "Task cancelled during retry backoff"
|
|
959
|
+
});
|
|
960
|
+
this.checkIdle();
|
|
812
961
|
}
|
|
813
962
|
};
|
|
814
963
|
}
|
|
964
|
+
/**
|
|
965
|
+
* Checks whether the scheduler has transitioned to idle and notifies listeners/resolvers.
|
|
966
|
+
*/
|
|
967
|
+
checkIdle() {
|
|
968
|
+
if (this.isIdle()) {
|
|
969
|
+
if (this.idleResolvers.size > 0) {
|
|
970
|
+
for (const resolve of this.idleResolvers) {
|
|
971
|
+
resolve();
|
|
972
|
+
}
|
|
973
|
+
this.idleResolvers.clear();
|
|
974
|
+
}
|
|
975
|
+
this.emitter.emit("idle", { timestamp: Date.now() });
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
/**
|
|
979
|
+
* Checks whether the scheduler is currently idle (no active runners and no pending tasks).
|
|
980
|
+
*
|
|
981
|
+
* @returns True if completely idle, false otherwise.
|
|
982
|
+
*/
|
|
983
|
+
isIdle() {
|
|
984
|
+
return this.activeRunners.size === 0 && this.queue.length === 0 && this.delayedEntries.size === 0 && this.idleEntries.size === 0 && this.retryEntries.size === 0 && this.debounceCoordinator.size === 0 && this.throttleCoordinator.size === 0;
|
|
985
|
+
}
|
|
986
|
+
/**
|
|
987
|
+
* Returns a promise that resolves once the scheduler has processed all tasks and is idle.
|
|
988
|
+
*
|
|
989
|
+
* @returns Promise resolving when idle.
|
|
990
|
+
*/
|
|
991
|
+
onIdle() {
|
|
992
|
+
if (this.isIdle()) {
|
|
993
|
+
return Promise.resolve();
|
|
994
|
+
}
|
|
995
|
+
return new Promise((resolve) => {
|
|
996
|
+
this.idleResolvers.add(resolve);
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* Clears all pending and waiting tasks from the scheduler, cancelling their runners.
|
|
1001
|
+
* Active tasks currently in flight will continue to run to completion or abort via signal.
|
|
1002
|
+
*/
|
|
1003
|
+
clear() {
|
|
1004
|
+
while (this.queue.length > 0) {
|
|
1005
|
+
const runner = this.queue.shift();
|
|
1006
|
+
if (runner && runner.state !== "cancelled" /* CANCELLED */) {
|
|
1007
|
+
runner.cancel("Scheduler cleared");
|
|
1008
|
+
this.cancelledTasks++;
|
|
1009
|
+
this.emitter.emit("task:cancel", { taskId: runner.taskId, reason: "Scheduler cleared" });
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
for (const entry of this.delayedEntries.values()) {
|
|
1013
|
+
clearTimeout(entry.timerId);
|
|
1014
|
+
entry.runner.cancel("Scheduler cleared");
|
|
1015
|
+
this.cancelledTasks++;
|
|
1016
|
+
this.emitter.emit("task:cancel", { taskId: entry.runner.taskId, reason: "Scheduler cleared" });
|
|
1017
|
+
}
|
|
1018
|
+
this.delayedEntries.clear();
|
|
1019
|
+
for (const entry of this.idleEntries.values()) {
|
|
1020
|
+
entry.handle.cancel();
|
|
1021
|
+
entry.runner.cancel("Scheduler cleared");
|
|
1022
|
+
this.cancelledTasks++;
|
|
1023
|
+
this.emitter.emit("task:cancel", { taskId: entry.runner.taskId, reason: "Scheduler cleared" });
|
|
1024
|
+
}
|
|
1025
|
+
this.idleEntries.clear();
|
|
1026
|
+
for (const entry of this.retryEntries.values()) {
|
|
1027
|
+
clearTimeout(entry.timerId);
|
|
1028
|
+
entry.runner.cancel("Scheduler cleared");
|
|
1029
|
+
this.cancelledTasks++;
|
|
1030
|
+
this.emitter.emit("task:cancel", { taskId: entry.runner.taskId, reason: "Scheduler cleared" });
|
|
1031
|
+
}
|
|
1032
|
+
this.retryEntries.clear();
|
|
1033
|
+
this.debounceCoordinator.clear();
|
|
1034
|
+
this.throttleCoordinator.clear();
|
|
1035
|
+
if (this.rateLimitTimer !== void 0) {
|
|
1036
|
+
clearTimeout(this.rateLimitTimer);
|
|
1037
|
+
this.rateLimitTimer = void 0;
|
|
1038
|
+
}
|
|
1039
|
+
this.checkIdle();
|
|
1040
|
+
}
|
|
815
1041
|
/**
|
|
816
1042
|
* Returns telemetry snapshot for the scheduler.
|
|
817
1043
|
*
|
|
@@ -825,6 +1051,8 @@ var TaskQueue = class {
|
|
|
825
1051
|
failedTasks: this.failedTasks,
|
|
826
1052
|
cancelledTasks: this.cancelledTasks,
|
|
827
1053
|
timedOutTasks: this.timedOutTasks,
|
|
1054
|
+
retriedTasks: this.retriedTasks,
|
|
1055
|
+
totalDispatched: this.totalDispatched,
|
|
828
1056
|
capacity: this.concurrency
|
|
829
1057
|
});
|
|
830
1058
|
}
|
|
@@ -859,6 +1087,8 @@ var TaskRunner = class {
|
|
|
859
1087
|
onCancel;
|
|
860
1088
|
/** Current execution attempt count (1-indexed) */
|
|
861
1089
|
attempt = 1;
|
|
1090
|
+
/** Duration of the most recent execution attempt in milliseconds */
|
|
1091
|
+
lastDurationMs = 0;
|
|
862
1092
|
/**
|
|
863
1093
|
* Creates a new TaskRunner instance.
|
|
864
1094
|
*
|
|
@@ -1017,9 +1247,11 @@ var TaskRunner = class {
|
|
|
1017
1247
|
if (timeoutPromise) {
|
|
1018
1248
|
racePromises.push(timeoutPromise);
|
|
1019
1249
|
}
|
|
1250
|
+
const startTime = Date.now();
|
|
1020
1251
|
try {
|
|
1021
1252
|
const result = await Promise.race(racePromises);
|
|
1022
1253
|
this.clearTimeoutTimer();
|
|
1254
|
+
this.lastDurationMs = Math.max(0, Date.now() - startTime);
|
|
1023
1255
|
if (abortListener) {
|
|
1024
1256
|
this.abortController.signal.removeEventListener("abort", abortListener);
|
|
1025
1257
|
}
|
|
@@ -1036,6 +1268,7 @@ var TaskRunner = class {
|
|
|
1036
1268
|
return result;
|
|
1037
1269
|
} catch (error) {
|
|
1038
1270
|
this.clearTimeoutTimer();
|
|
1271
|
+
this.lastDurationMs = Math.max(0, Date.now() - startTime);
|
|
1039
1272
|
if (abortListener) {
|
|
1040
1273
|
this.abortController.signal.removeEventListener("abort", abortListener);
|
|
1041
1274
|
}
|
|
@@ -1277,10 +1510,87 @@ var Ahko = class {
|
|
|
1277
1510
|
stats() {
|
|
1278
1511
|
return this.queue.getStats();
|
|
1279
1512
|
}
|
|
1513
|
+
/**
|
|
1514
|
+
* Subscribes to a scheduler lifecycle event.
|
|
1515
|
+
*
|
|
1516
|
+
* @param event - Event name to listen for.
|
|
1517
|
+
* @param handler - Callback function invoked when the event is emitted.
|
|
1518
|
+
* @returns Unsubscribe function to remove the listener.
|
|
1519
|
+
*
|
|
1520
|
+
* @example
|
|
1521
|
+
* ```typescript
|
|
1522
|
+
* const unsubscribe = ahko.on("task:start", ({ taskId, attempt }) => {
|
|
1523
|
+
* console.log(`Task ${taskId} started attempt ${attempt}`);
|
|
1524
|
+
* });
|
|
1525
|
+
* ```
|
|
1526
|
+
*/
|
|
1527
|
+
on(event, handler) {
|
|
1528
|
+
return this.queue.emitter.on(event, handler);
|
|
1529
|
+
}
|
|
1530
|
+
/**
|
|
1531
|
+
* Unsubscribes an event listener from a scheduler lifecycle event.
|
|
1532
|
+
*
|
|
1533
|
+
* @param event - Event name.
|
|
1534
|
+
* @param handler - The exact listener callback to remove.
|
|
1535
|
+
*/
|
|
1536
|
+
off(event, handler) {
|
|
1537
|
+
this.queue.emitter.off(event, handler);
|
|
1538
|
+
}
|
|
1539
|
+
/**
|
|
1540
|
+
* Checks whether the scheduler is currently idle (no active runners and no pending tasks).
|
|
1541
|
+
*
|
|
1542
|
+
* @returns True if completely idle, false otherwise.
|
|
1543
|
+
*/
|
|
1544
|
+
isIdle() {
|
|
1545
|
+
return this.queue.isIdle();
|
|
1546
|
+
}
|
|
1547
|
+
/**
|
|
1548
|
+
* Returns a promise that resolves once the scheduler has completed all tasks and is idle.
|
|
1549
|
+
*
|
|
1550
|
+
* @returns Promise resolving when the scheduler is idle.
|
|
1551
|
+
*
|
|
1552
|
+
* @example
|
|
1553
|
+
* ```typescript
|
|
1554
|
+
* ahko.schedule(doWork);
|
|
1555
|
+
* await ahko.onIdle();
|
|
1556
|
+
* console.log("All work finished!");
|
|
1557
|
+
* ```
|
|
1558
|
+
*/
|
|
1559
|
+
onIdle() {
|
|
1560
|
+
return this.queue.onIdle();
|
|
1561
|
+
}
|
|
1562
|
+
/**
|
|
1563
|
+
* Clears all pending, delayed, and throttled/debounced tasks from the scheduler.
|
|
1564
|
+
* In-flight active tasks will continue executing to completion or abort via signal.
|
|
1565
|
+
*/
|
|
1566
|
+
clear() {
|
|
1567
|
+
this.queue.clear();
|
|
1568
|
+
}
|
|
1569
|
+
/**
|
|
1570
|
+
* Returns the delightful Ahko mascot battery telemetry status.
|
|
1571
|
+
*
|
|
1572
|
+
* Low energy, completely chill.
|
|
1573
|
+
*/
|
|
1574
|
+
battery() {
|
|
1575
|
+
return {
|
|
1576
|
+
level: 3,
|
|
1577
|
+
chill: true,
|
|
1578
|
+
status: "low-energy",
|
|
1579
|
+
quote: "Mwee... my battery is low, but all your tasks are handled completely chill."
|
|
1580
|
+
};
|
|
1581
|
+
}
|
|
1582
|
+
/**
|
|
1583
|
+
* Delightful alias for `onIdle()`: wait for all tasks to settle chill and relaxed.
|
|
1584
|
+
*
|
|
1585
|
+
* @returns Promise resolving when all tasks have finished.
|
|
1586
|
+
*/
|
|
1587
|
+
chill() {
|
|
1588
|
+
return this.onIdle();
|
|
1589
|
+
}
|
|
1280
1590
|
};
|
|
1281
1591
|
|
|
1282
1592
|
// src/version.ts
|
|
1283
|
-
var VERSION = "0.
|
|
1593
|
+
var VERSION = "0.6.0";
|
|
1284
1594
|
|
|
1285
1595
|
// src/errors/queue.error.ts
|
|
1286
1596
|
var AhkoQueueError = class extends AhkoError {
|