@apisurf/ngn-core 0.3.1 → 0.4.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/core.d.ts +19 -1
- package/dist/core.js +39 -2
- package/package.json +4 -4
package/dist/core.d.ts
CHANGED
|
@@ -774,6 +774,13 @@ type Options$1 = {
|
|
|
774
774
|
/** Called when a scheduled run throws, with the run it was recorded as when there is one. */
|
|
775
775
|
onRunError?: (path: string, error: unknown, runId: number | null) => void;
|
|
776
776
|
};
|
|
777
|
+
/** What `runNow()` did: started a run, or why it did not. */
|
|
778
|
+
type RunNowOutcome = {
|
|
779
|
+
started: true;
|
|
780
|
+
} | {
|
|
781
|
+
started: false;
|
|
782
|
+
reason: string;
|
|
783
|
+
};
|
|
777
784
|
/** What `start()` did with each task: scheduled on its pattern, or left out and why. */
|
|
778
785
|
interface ScheduleReport {
|
|
779
786
|
scheduled: {
|
|
@@ -793,6 +800,17 @@ declare class TaskLibraryScheduler {
|
|
|
793
800
|
start(): Promise<ScheduleReport>;
|
|
794
801
|
stop(): Promise<void>;
|
|
795
802
|
scheduleTask(task: Task): Promise<void>;
|
|
803
|
+
/**
|
|
804
|
+
* Start one run of a scheduled task now, outside its schedule, the way a tick
|
|
805
|
+
* would: retries, budget, locks and hooks all apply, and errors go where a
|
|
806
|
+
* tick's go. It is not a tick, so the breaker does not hold it back. Resolves
|
|
807
|
+
* once the run is under way, not when it ends: a run can take longer than
|
|
808
|
+
* anyone waits on a button.
|
|
809
|
+
*
|
|
810
|
+
* A run still going is reported rather than recorded as a skip, since nothing
|
|
811
|
+
* was due: the person asking can simply wait.
|
|
812
|
+
*/
|
|
813
|
+
runNow(taskPath: string): RunNowOutcome;
|
|
796
814
|
unscheduleTask(task: Task): void;
|
|
797
815
|
isCronPatternValid(cronPattern: string): boolean;
|
|
798
816
|
}
|
|
@@ -824,4 +842,4 @@ declare function createControlsGenerator({ dbClient, env, report, }: {
|
|
|
824
842
|
report?: (problem: RunProblem) => void;
|
|
825
843
|
}): BuildCompiledTaskConfigFn;
|
|
826
844
|
|
|
827
|
-
export { type AddJob, type Backoff, type ClaimOptions, Compiler, type DBInstance, type Duration, type InitDBOptions, type Job, type JobFilter, type JobStatus, LockBusyError, type LockOptions, type Migration, type OverlapPolicy, Queue, type QueueOptions, type QueueStats, type RunProblem, type ScheduleReport, Task, type TaskContext, TaskLibrary, TaskLibraryScheduler, TaskOnceRunner, type TaskRun, type TaskSqlite, type WorkHandler, type WorkOptions, type WorkSummary, type WorkerHandle, closeTaskDatabases, createControlsGenerator, executeEsm, failedRunId, getDbClient, isCronPatternValid, releaseTaskDatabases, runFailure, scheduleTask, setupDbClient };
|
|
845
|
+
export { type AddJob, type Backoff, type ClaimOptions, Compiler, type DBInstance, type Duration, type InitDBOptions, type Job, type JobFilter, type JobStatus, LockBusyError, type LockOptions, type Migration, type OverlapPolicy, Queue, type QueueOptions, type QueueStats, type RunNowOutcome, type RunProblem, type ScheduleReport, Task, type TaskContext, TaskLibrary, TaskLibraryScheduler, TaskOnceRunner, type TaskRun, type TaskSqlite, type WorkHandler, type WorkOptions, type WorkSummary, type WorkerHandle, closeTaskDatabases, createControlsGenerator, executeEsm, failedRunId, getDbClient, isCronPatternValid, releaseTaskDatabases, runFailure, scheduleTask, setupDbClient };
|
package/dist/core.js
CHANGED
|
@@ -385,10 +385,17 @@ function deadlineSignal(deadline) {
|
|
|
385
385
|
return { signal: controller.signal, dispose: () => {
|
|
386
386
|
} };
|
|
387
387
|
}
|
|
388
|
-
|
|
389
|
-
|
|
388
|
+
let timer;
|
|
389
|
+
const arm = () => {
|
|
390
|
+
const left = deadline - Date.now();
|
|
391
|
+
if (left <= 0) return abort();
|
|
392
|
+
timer = setTimeout(arm, Math.min(left, MAX_TIMER_MS));
|
|
393
|
+
timer.unref();
|
|
394
|
+
};
|
|
395
|
+
arm();
|
|
390
396
|
return { signal: controller.signal, dispose: () => clearTimeout(timer) };
|
|
391
397
|
}
|
|
398
|
+
var MAX_TIMER_MS = 2 ** 31 - 1;
|
|
392
399
|
|
|
393
400
|
// src/runtime/locks.ts
|
|
394
401
|
var LockBusyError = class extends Error {
|
|
@@ -1664,6 +1671,36 @@ var TaskLibraryScheduler = class {
|
|
|
1664
1671
|
this.scheduledTasks.set(task.taskPath, scheduledTask);
|
|
1665
1672
|
logTaskLibraryScheduler(`Scheduled: ${task.taskPath}`);
|
|
1666
1673
|
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Start one run of a scheduled task now, outside its schedule, the way a tick
|
|
1676
|
+
* would: retries, budget, locks and hooks all apply, and errors go where a
|
|
1677
|
+
* tick's go. It is not a tick, so the breaker does not hold it back. Resolves
|
|
1678
|
+
* once the run is under way, not when it ends: a run can take longer than
|
|
1679
|
+
* anyone waits on a button.
|
|
1680
|
+
*
|
|
1681
|
+
* A run still going is reported rather than recorded as a skip, since nothing
|
|
1682
|
+
* was due: the person asking can simply wait.
|
|
1683
|
+
*/
|
|
1684
|
+
runNow(taskPath) {
|
|
1685
|
+
const task = this.taskLibrary.getTasks().find((t) => t.taskPath === taskPath);
|
|
1686
|
+
const cron = this.scheduledTasks.get(taskPath);
|
|
1687
|
+
if (!task || !cron) {
|
|
1688
|
+
return { started: false, reason: `${taskPath} is not scheduled by this ngn run` };
|
|
1689
|
+
}
|
|
1690
|
+
if (task.isRunning && task.overlapPolicy === "skip") {
|
|
1691
|
+
return { started: false, reason: "a run of it is still going" };
|
|
1692
|
+
}
|
|
1693
|
+
void tick(
|
|
1694
|
+
task,
|
|
1695
|
+
(error) => {
|
|
1696
|
+
logTaskLibrarySchedulerError(`Run failed: ${task.taskPath}`);
|
|
1697
|
+
logTaskLibrarySchedulerError(error);
|
|
1698
|
+
this.onRunError?.(task.taskPath, error, failedRunId(error));
|
|
1699
|
+
},
|
|
1700
|
+
{ scheduledAt: null, nextAt: cron.nextRun()?.getTime() ?? null }
|
|
1701
|
+
);
|
|
1702
|
+
return { started: true };
|
|
1703
|
+
}
|
|
1667
1704
|
unscheduleTask(task) {
|
|
1668
1705
|
const existingTask = this.scheduledTasks.get(task.taskPath);
|
|
1669
1706
|
if (!existingTask) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apisurf/ngn-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "ngn runtime: task compilation, scheduling and the run/log/timing services.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Luka Vidakovic",
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"esbuild": "^0.27.1",
|
|
39
39
|
"tiny-invariant": "^1.3.3",
|
|
40
40
|
"zod": "^3.24.2",
|
|
41
|
-
"@apisurf/ngn-os": "0.
|
|
42
|
-
"@apisurf/ngn-
|
|
43
|
-
"@apisurf/ngn-
|
|
41
|
+
"@apisurf/ngn-os": "0.4.0",
|
|
42
|
+
"@apisurf/ngn-persistence": "0.4.0",
|
|
43
|
+
"@apisurf/ngn-schema": "0.4.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "^22.8.1",
|