bareloop 0.42.0 → 0.43.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 +46 -0
- package/bareloop.context.md +53 -30
- package/package.json +1 -1
- package/src/authorjob.js +6 -0
- package/src/declaredclose.js +2 -2
- package/src/interviewrun.js +0 -1
- package/src/job.js +38 -11
- package/src/panel/authorroutes.js +107 -33
- package/src/panel/authorsession.js +59 -27
- package/src/panel/index.html +813 -484
- package/src/panel/runroutes.js +163 -5
- package/src/panel/scheduler.js +156 -0
- package/src/panel/schedules.js +667 -0
- package/src/panel/schedulestart.js +243 -0
- package/src/panel/server.js +451 -48
- package/src/planrun.js +39 -7
- package/src/providerrows.js +3 -3
- package/src/reviewdoor.js +37 -0
- package/src/runlist.js +35 -0
- package/src/schedulewords.js +296 -0
- package/src/trigger.js +48 -0
- package/src/triggerclock.js +127 -0
- package/src/triggerfiles.js +215 -0
- package/src/triggerledger.js +79 -0
- package/src/userrun.js +6 -7
- package/types/declaredclose.d.ts +1 -1
- package/types/job.d.ts +8 -1
- package/types/panel/authorroutes.d.ts +34 -1
- package/types/panel/authorsession.d.ts +37 -12
- package/types/panel/runroutes.d.ts +32 -1
- package/types/panel/scheduler.d.ts +17 -0
- package/types/panel/schedules.d.ts +412 -0
- package/types/panel/schedulestart.d.ts +106 -0
- package/types/panel/server.d.ts +143 -14
- package/types/planrun.d.ts +2 -0
- package/types/providerrows.d.ts +2 -2
- package/types/reviewdoor.d.ts +27 -0
- package/types/runlist.d.ts +20 -0
- package/types/schedulewords.d.ts +135 -0
- package/types/trigger.d.ts +37 -0
- package/types/triggerclock.d.ts +52 -0
- package/types/triggerfiles.d.ts +93 -0
- package/types/triggerledger.d.ts +35 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The only way a clock schedule enters the system. Refuses anything else, naming the field.
|
|
3
|
+
* @param {unknown} s
|
|
4
|
+
* @returns {Schedule}
|
|
5
|
+
*/
|
|
6
|
+
export function validateSchedule(s: unknown): Schedule;
|
|
7
|
+
/**
|
|
8
|
+
* Is a run due at `now`? Slots missed (panel off) collapse to ONE fire, for the latest slot, marked catch-up.
|
|
9
|
+
* Catch-up = more than one slot was missed, or the latest slot is more than GRACE_MS old.
|
|
10
|
+
* @param {Schedule} schedule
|
|
11
|
+
* @param {ClockRow[]} rows
|
|
12
|
+
* @param {number} now epoch ms
|
|
13
|
+
* @returns {Due}
|
|
14
|
+
*/
|
|
15
|
+
export function due(schedule: Schedule, rows: ClockRow[], now: number): Due;
|
|
16
|
+
/**
|
|
17
|
+
* The next slot time strictly after `afterMs` (epoch ms). Words are the caller's (schedulewords.js).
|
|
18
|
+
* @param {Schedule} schedule
|
|
19
|
+
* @param {number} afterMs
|
|
20
|
+
* @returns {number}
|
|
21
|
+
*/
|
|
22
|
+
export function nextSlot(schedule: Schedule, afterMs: number): number;
|
|
23
|
+
/** The trigger was set at `now` under signature `sig`: no slot before this ever fires. @param {string} file @param {number} now @param {string} sig */
|
|
24
|
+
export function armTrigger(file: string, now: number, sig: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Record that the run for this due slot is starting (the consuming row). Write-once per slot.
|
|
27
|
+
* @param {string} file @param {Due} d the result of `due` with fire true @param {number} now @param {string} sig
|
|
28
|
+
*/
|
|
29
|
+
export function recordFire(file: string, d: Due, now: number, sig: string): void;
|
|
30
|
+
/** @typedef {{kind:'daily'|'weekdays', hour:number, minute:number} | {kind:'weekly', day:string, hour:number, minute:number}} Schedule */
|
|
31
|
+
/** @typedef {import('./triggerledger.js').LedgerRow} ClockRow */
|
|
32
|
+
/** @typedef {{fire:boolean, catchUp:boolean, missed:number, slot?:number}} Due */
|
|
33
|
+
/** A slot seen MORE than this after its set time is a catch-up. Exactly this late is on time. */
|
|
34
|
+
export const GRACE_MS: 120000;
|
|
35
|
+
export const DAYS: string[];
|
|
36
|
+
export type Schedule = {
|
|
37
|
+
kind: "daily" | "weekdays";
|
|
38
|
+
hour: number;
|
|
39
|
+
minute: number;
|
|
40
|
+
} | {
|
|
41
|
+
kind: "weekly";
|
|
42
|
+
day: string;
|
|
43
|
+
hour: number;
|
|
44
|
+
minute: number;
|
|
45
|
+
};
|
|
46
|
+
export type ClockRow = import("./triggerledger.js").LedgerRow;
|
|
47
|
+
export type Due = {
|
|
48
|
+
fire: boolean;
|
|
49
|
+
catchUp: boolean;
|
|
50
|
+
missed: number;
|
|
51
|
+
slot?: number;
|
|
52
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/** The file-kind rows of the job's ledger that still count (a released `ran` does not). @param {string} file @returns {SeenRow[]} */
|
|
2
|
+
export function readSeen(file: string): SeenRow[];
|
|
3
|
+
/** Arrived rows are never overwritten: the 2nd arrival of a sha (after a drop) gets its own id. @param {string} ledger @param {ToRun & {name?:string}} item @param {number} at the scheduler's clock, never the file's mtime @param {string} sig */
|
|
4
|
+
export function recordArrived(ledger: string, item: ToRun & {
|
|
5
|
+
name?: string;
|
|
6
|
+
}, at: number, sig: string): boolean;
|
|
7
|
+
/** `of` = the arrived row it cancels (item.id when a queue row is passed). @param {string} ledger @param {{sha:string, path:string, size:number, id?:string}} item @param {string} why a plain reason: deleted, changed, schedule-changed, schedule-cancelled @param {number} at @param {string} sig */
|
|
8
|
+
export function recordDropped(ledger: string, item: {
|
|
9
|
+
sha: string;
|
|
10
|
+
path: string;
|
|
11
|
+
size: number;
|
|
12
|
+
id?: string;
|
|
13
|
+
}, why: string, at: number, sig: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* The queue: arrived and neither ran nor dropped, oldest arrival first. Identical arrival times: by name, then by sha (deterministic).
|
|
16
|
+
* @param {SeenRow[]} rows @returns {(SeenRow & {path:string})[]}
|
|
17
|
+
*/
|
|
18
|
+
export function queueOf(rows: SeenRow[]): (SeenRow & {
|
|
19
|
+
path: string;
|
|
20
|
+
})[];
|
|
21
|
+
/**
|
|
22
|
+
* At a queued file's turn, look at it again, at use time: lstat (no symlink, a regular file), realpath of its folder, re-hash.
|
|
23
|
+
* @param {{path:string, sha:string}} item
|
|
24
|
+
* @returns {{state:'ok', path:string, sha:string, size:number} | {state:'deleted', say:string} | {state:'changed', sha:string}}
|
|
25
|
+
*/
|
|
26
|
+
export function recheck(item: {
|
|
27
|
+
path: string;
|
|
28
|
+
sha: string;
|
|
29
|
+
}): {
|
|
30
|
+
state: "ok";
|
|
31
|
+
path: string;
|
|
32
|
+
sha: string;
|
|
33
|
+
size: number;
|
|
34
|
+
} | {
|
|
35
|
+
state: "deleted";
|
|
36
|
+
say: string;
|
|
37
|
+
} | {
|
|
38
|
+
state: "changed";
|
|
39
|
+
sha: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* The target is usable NOW, or an Error naming why: a file that is not a symlink and not something else (a file that does not exist yet
|
|
43
|
+
* is allowed: it may arrive), a folder that exists, resolved with realpathSync. The one rule `arm` and a door's set-time check share.
|
|
44
|
+
* @param {'new'|'updated'} mode @param {string} target
|
|
45
|
+
*/
|
|
46
|
+
export function checkTarget(mode: "new" | "updated", target: string): void;
|
|
47
|
+
/**
|
|
48
|
+
* @param {{mode:'new'|'updated', target:string, ledger:string, sig:string, now?:() => number}} opts target = folder (new) or file (updated)
|
|
49
|
+
*/
|
|
50
|
+
export function createFileTrigger({ mode, target, ledger, sig, now }: {
|
|
51
|
+
mode: "new" | "updated";
|
|
52
|
+
target: string;
|
|
53
|
+
ledger: string;
|
|
54
|
+
sig: string;
|
|
55
|
+
now?: () => number;
|
|
56
|
+
}): {
|
|
57
|
+
arm: () => void;
|
|
58
|
+
poll: () => {
|
|
59
|
+
arrived: ToRun[];
|
|
60
|
+
refused: Refused[];
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
/** @typedef {{id:string, kind:'baseline'|'arrived'|'ran'|'dropped', sha:string, name:string, size:number, at:number, sig?:string, path?:string, why?:string, of?:string}} SeenRow */
|
|
64
|
+
/** @typedef {{path:string, sha:string, size:number}} ToRun */
|
|
65
|
+
/** @typedef {{path:string, why:string}} Refused */
|
|
66
|
+
/** Consecutive polls with the same size and mtime before a file is taken. (Two matches in a row = taken on the third sighting.) */
|
|
67
|
+
export const STABLE_POLLS: 2;
|
|
68
|
+
export function recordRan(ledger: string, item: {
|
|
69
|
+
sha: string;
|
|
70
|
+
path: string;
|
|
71
|
+
size: number;
|
|
72
|
+
}, at: number, sig: string): boolean;
|
|
73
|
+
export type SeenRow = {
|
|
74
|
+
id: string;
|
|
75
|
+
kind: "baseline" | "arrived" | "ran" | "dropped";
|
|
76
|
+
sha: string;
|
|
77
|
+
name: string;
|
|
78
|
+
size: number;
|
|
79
|
+
at: number;
|
|
80
|
+
sig?: string;
|
|
81
|
+
path?: string;
|
|
82
|
+
why?: string;
|
|
83
|
+
of?: string;
|
|
84
|
+
};
|
|
85
|
+
export type ToRun = {
|
|
86
|
+
path: string;
|
|
87
|
+
sha: string;
|
|
88
|
+
size: number;
|
|
89
|
+
};
|
|
90
|
+
export type Refused = {
|
|
91
|
+
path: string;
|
|
92
|
+
why: string;
|
|
93
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** @typedef {{id?: string, kind: string, sig?: string, at?: number, [k: string]: unknown}} LedgerRow */
|
|
2
|
+
/**
|
|
3
|
+
* Every row that parses, oldest first, and how many lines did not. A missing file is no rows.
|
|
4
|
+
* @param {string} file
|
|
5
|
+
* @returns {{rows: LedgerRow[], skipped: number}}
|
|
6
|
+
*/
|
|
7
|
+
export function readLedger(file: string): {
|
|
8
|
+
rows: LedgerRow[];
|
|
9
|
+
skipped: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Append one row (dir 0700, file 0600). A torn tail gets a newline first. `once` refuses a row whose `id` is
|
|
13
|
+
* already on disk (write-once ids), by throwing.
|
|
14
|
+
* @param {string} file
|
|
15
|
+
* @param {LedgerRow} row
|
|
16
|
+
* @param {{once?: boolean}} [opts]
|
|
17
|
+
*/
|
|
18
|
+
export function appendRow(file: string, row: LedgerRow, opts?: {
|
|
19
|
+
once?: boolean;
|
|
20
|
+
}): void;
|
|
21
|
+
/**
|
|
22
|
+
* Walk the rows in order: a `released` row (`of` = an id) cancels the latest earlier live row with that id, and
|
|
23
|
+
* is itself dropped. A released `fire` or `ran` is not consumed, so its slot or file is retryable (Part 4) and
|
|
24
|
+
* the same id may be written again.
|
|
25
|
+
* @param {LedgerRow[]} rows
|
|
26
|
+
* @returns {LedgerRow[]}
|
|
27
|
+
*/
|
|
28
|
+
export function withoutReleased(rows: LedgerRow[]): LedgerRow[];
|
|
29
|
+
export type LedgerRow = {
|
|
30
|
+
id?: string;
|
|
31
|
+
kind: string;
|
|
32
|
+
sig?: string;
|
|
33
|
+
at?: number;
|
|
34
|
+
[k: string]: unknown;
|
|
35
|
+
};
|