@hasna/loops 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.
@@ -0,0 +1,7 @@
1
+ import type { ExecutorResult, Loop, LoopRun } from "../types.js";
2
+ export interface ExecuteOptions {
3
+ maxOutputBytes?: number;
4
+ env?: NodeJS.ProcessEnv;
5
+ log?: (message: string) => void;
6
+ }
7
+ export declare function executeLoop(loop: Loop, run: LoopRun, opts?: ExecuteOptions): Promise<ExecutorResult>;
@@ -0,0 +1,4 @@
1
+ import type { Loop, LoopRun } from "../types.js";
2
+ export declare function redact(value: string | undefined, visible?: number): string | undefined;
3
+ export declare function publicLoop(loop: Loop): Record<string, unknown>;
4
+ export declare function publicRun(run: LoopRun, showOutput?: boolean): Record<string, unknown>;
@@ -0,0 +1,2 @@
1
+ export declare function genId(length?: number): string;
2
+ export declare function nowIso(): string;
@@ -0,0 +1,7 @@
1
+ export declare function dataDir(): string;
2
+ export declare function ensureDataDir(): string;
3
+ export declare function dbPath(): string;
4
+ export declare function pidFilePath(): string;
5
+ export declare function daemonLogPath(): string;
6
+ export declare function systemdServicePath(): string;
7
+ export declare function launchdPlistPath(): string;
@@ -0,0 +1,21 @@
1
+ import type { Loop, ScheduleSpec } from "../types.js";
2
+ interface ParsedCron {
3
+ minute: Set<number>;
4
+ hour: Set<number>;
5
+ dom: Set<number>;
6
+ month: Set<number>;
7
+ dow: Set<number>;
8
+ domRestricted: boolean;
9
+ dowRestricted: boolean;
10
+ }
11
+ export declare function parseCron(expr: string): ParsedCron;
12
+ export declare function nextCronRun(expr: string, from: Date): Date;
13
+ export declare function initialNextRun(schedule: ScheduleSpec, from?: Date): string;
14
+ export declare function computeNextAfter(schedule: ScheduleSpec, scheduledFor: Date, finishedAt: Date): string | undefined;
15
+ export interface DuePlan {
16
+ slots: string[];
17
+ skippedToNextRunAt?: string;
18
+ }
19
+ export declare function dueSlots(loop: Loop, now: Date): DuePlan;
20
+ export declare function parseDuration(input: string): number;
21
+ export {};
@@ -0,0 +1,18 @@
1
+ import type { ExecutorResult, Loop, LoopRun } from "../types.js";
2
+ import type { Store } from "./store.js";
3
+ export interface SchedulerDeps {
4
+ store: Store;
5
+ runnerId: string;
6
+ now?: () => Date;
7
+ execute?: (loop: Loop, run: LoopRun) => Promise<ExecutorResult>;
8
+ onError?: (loop: Loop, error: unknown) => void;
9
+ onRun?: (run: LoopRun) => void;
10
+ }
11
+ export interface TickResult {
12
+ claimed: LoopRun[];
13
+ completed: LoopRun[];
14
+ skipped: LoopRun[];
15
+ recovered: LoopRun[];
16
+ expired: Loop[];
17
+ }
18
+ export declare function tick(deps: SchedulerDeps): Promise<TickResult>;
@@ -0,0 +1,56 @@
1
+ import type { CreateLoopInput, Loop, LoopRun, LoopStatus, RunStatus } from "../types.js";
2
+ export interface DaemonLease {
3
+ id: string;
4
+ pid: number;
5
+ hostname: string;
6
+ heartbeatAt: string;
7
+ expiresAt: string;
8
+ createdAt: string;
9
+ updatedAt: string;
10
+ }
11
+ export interface ClaimRunResult {
12
+ run: LoopRun;
13
+ loop: Loop;
14
+ }
15
+ export declare class Store {
16
+ private db;
17
+ constructor(path?: string);
18
+ private migrate;
19
+ createLoop(input: CreateLoopInput, from?: Date): Loop;
20
+ getLoop(id: string): Loop | undefined;
21
+ findLoopByName(name: string): Loop | undefined;
22
+ requireLoop(idOrName: string): Loop;
23
+ listLoops(opts?: {
24
+ status?: LoopStatus;
25
+ limit?: number;
26
+ }): Loop[];
27
+ dueLoops(now: Date): Loop[];
28
+ updateLoop(id: string, patch: Partial<Pick<Loop, "status" | "nextRunAt" | "retryScheduledFor" | "expiresAt">>): Loop;
29
+ deleteLoop(idOrName: string): boolean;
30
+ hasRunningRun(loopId: string): boolean;
31
+ createSkippedRun(loop: Loop, scheduledFor: string, reason: string): LoopRun;
32
+ getRun(id: string): LoopRun | undefined;
33
+ getRunBySlot(loopId: string, scheduledFor: string): LoopRun | undefined;
34
+ claimRun(loop: Loop, scheduledFor: string, runnerId: string, now?: Date): ClaimRunResult | undefined;
35
+ finalizeRun(id: string, patch: Pick<LoopRun, "status" | "finishedAt" | "durationMs" | "stdout" | "stderr"> & Partial<Pick<LoopRun, "exitCode" | "error" | "pid">>): LoopRun;
36
+ listRuns(opts?: {
37
+ loopId?: string;
38
+ status?: RunStatus;
39
+ limit?: number;
40
+ }): LoopRun[];
41
+ recoverExpiredRunLeases(now?: Date): LoopRun[];
42
+ expireLoops(now?: Date): Loop[];
43
+ countLoops(status?: LoopStatus): number;
44
+ countRuns(status?: RunStatus): number;
45
+ acquireDaemonLease(input: {
46
+ id: string;
47
+ pid: number;
48
+ hostname: string;
49
+ ttlMs: number;
50
+ now?: Date;
51
+ }): DaemonLease | undefined;
52
+ heartbeatDaemonLease(id: string, ttlMs: number, now?: Date): DaemonLease | undefined;
53
+ releaseDaemonLease(id: string): void;
54
+ getDaemonLease(): DaemonLease | undefined;
55
+ close(): void;
56
+ }