@portel/photon 1.23.1 → 1.25.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/README.md +66 -0
- package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
- package/dist/auto-ui/streamable-http-transport.js +262 -18
- package/dist/auto-ui/streamable-http-transport.js.map +1 -1
- package/dist/beam.bundle.js +58287 -56177
- package/dist/beam.bundle.js.map +4 -4
- package/dist/capability-negotiator.d.ts +9 -0
- package/dist/capability-negotiator.d.ts.map +1 -1
- package/dist/capability-negotiator.js +14 -0
- package/dist/capability-negotiator.js.map +1 -1
- package/dist/cli/commands/claim.d.ts +17 -0
- package/dist/cli/commands/claim.d.ts.map +1 -0
- package/dist/cli/commands/claim.js +124 -0
- package/dist/cli/commands/claim.js.map +1 -0
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +2 -0
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/daemon/claims.d.ts +108 -0
- package/dist/daemon/claims.d.ts.map +1 -0
- package/dist/daemon/claims.js +245 -0
- package/dist/daemon/claims.js.map +1 -0
- package/dist/daemon/client.d.ts.map +1 -1
- package/dist/daemon/client.js +15 -29
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/cron.d.ts +36 -0
- package/dist/daemon/cron.d.ts.map +1 -0
- package/dist/daemon/cron.js +216 -0
- package/dist/daemon/cron.js.map +1 -0
- package/dist/daemon/schedule-loader.d.ts +76 -0
- package/dist/daemon/schedule-loader.d.ts.map +1 -0
- package/dist/daemon/schedule-loader.js +124 -0
- package/dist/daemon/schedule-loader.js.map +1 -0
- package/dist/daemon/server.js +76 -226
- package/dist/daemon/server.js.map +1 -1
- package/dist/deploy/cloudflare.d.ts.map +1 -1
- package/dist/deploy/cloudflare.js +154 -4
- package/dist/deploy/cloudflare.js.map +1 -1
- package/dist/loader.d.ts +22 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +246 -30
- package/dist/loader.js.map +1 -1
- package/dist/photon-cli-runner.d.ts.map +1 -1
- package/dist/photon-cli-runner.js +32 -2
- package/dist/photon-cli-runner.js.map +1 -1
- package/dist/server.d.ts +10 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +50 -1
- package/dist/server.js.map +1 -1
- package/dist/shared/memory-sqlite.d.ts +37 -0
- package/dist/shared/memory-sqlite.d.ts.map +1 -0
- package/dist/shared/memory-sqlite.js +143 -0
- package/dist/shared/memory-sqlite.js.map +1 -0
- package/dist/telemetry/context.d.ts +9 -0
- package/dist/telemetry/context.d.ts.map +1 -1
- package/dist/telemetry/context.js.map +1 -1
- package/package.json +4 -4
- package/templates/cloudflare/worker.ts.template +53 -74
- package/templates/cloudflare/wrangler.toml.template +6 -1
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron parser and scheduling helpers.
|
|
3
|
+
*
|
|
4
|
+
* Five-field POSIX-style cron (minute hour day-of-month month day-of-week).
|
|
5
|
+
* Supports wildcards (*), lists (a,b,c), ranges (a-b), steps (*\/n), and
|
|
6
|
+
* Sunday-as-7 normalization. Minute granularity only.
|
|
7
|
+
*
|
|
8
|
+
* Extracted from daemon/server.ts so it can be shared with the boot loader
|
|
9
|
+
* and exercised by focused tests.
|
|
10
|
+
*/
|
|
11
|
+
export function parseCronField(field, min, max) {
|
|
12
|
+
if (field === '*') {
|
|
13
|
+
const values = [];
|
|
14
|
+
for (let i = min; i <= max; i++)
|
|
15
|
+
values.push(i);
|
|
16
|
+
return values;
|
|
17
|
+
}
|
|
18
|
+
// Comma-separated list
|
|
19
|
+
if (field.includes(',')) {
|
|
20
|
+
const values = new Set();
|
|
21
|
+
for (const part of field.split(',')) {
|
|
22
|
+
const partValues = parseCronField(part, min, max);
|
|
23
|
+
if (!partValues)
|
|
24
|
+
return null;
|
|
25
|
+
partValues.forEach((v) => values.add(v));
|
|
26
|
+
}
|
|
27
|
+
return Array.from(values).sort((a, b) => a - b);
|
|
28
|
+
}
|
|
29
|
+
// Step values: */n, start/n, start-end/n
|
|
30
|
+
if (field.includes('/')) {
|
|
31
|
+
const slashIdx = field.indexOf('/');
|
|
32
|
+
const range = field.slice(0, slashIdx);
|
|
33
|
+
const step = parseInt(field.slice(slashIdx + 1));
|
|
34
|
+
if (isNaN(step) || step <= 0)
|
|
35
|
+
return null;
|
|
36
|
+
let start = min;
|
|
37
|
+
let end = max;
|
|
38
|
+
if (range !== '*') {
|
|
39
|
+
if (range.includes('-')) {
|
|
40
|
+
const [s, e] = range.split('-').map(Number);
|
|
41
|
+
if (isNaN(s) || isNaN(e))
|
|
42
|
+
return null;
|
|
43
|
+
start = s;
|
|
44
|
+
end = e;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
start = parseInt(range);
|
|
48
|
+
if (isNaN(start))
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const values = [];
|
|
53
|
+
for (let i = start; i <= end; i += step)
|
|
54
|
+
values.push(i);
|
|
55
|
+
return values;
|
|
56
|
+
}
|
|
57
|
+
// Range: n-m
|
|
58
|
+
if (field.includes('-')) {
|
|
59
|
+
const [s, e] = field.split('-').map(Number);
|
|
60
|
+
if (isNaN(s) || isNaN(e) || s < min || e > max)
|
|
61
|
+
return null;
|
|
62
|
+
const values = [];
|
|
63
|
+
for (let i = s; i <= e; i++)
|
|
64
|
+
values.push(i);
|
|
65
|
+
return values;
|
|
66
|
+
}
|
|
67
|
+
// Single value
|
|
68
|
+
const value = parseInt(field);
|
|
69
|
+
if (isNaN(value) || value < min || value > max)
|
|
70
|
+
return null;
|
|
71
|
+
return [value];
|
|
72
|
+
}
|
|
73
|
+
function parse(cron) {
|
|
74
|
+
const parts = cron.trim().split(/\s+/);
|
|
75
|
+
if (parts.length !== 5)
|
|
76
|
+
return null;
|
|
77
|
+
const [minuteField, hourField, domField, monthField, dowField] = parts;
|
|
78
|
+
const minutes = parseCronField(minuteField, 0, 59);
|
|
79
|
+
const hours = parseCronField(hourField, 0, 23);
|
|
80
|
+
const doms = parseCronField(domField, 1, 31);
|
|
81
|
+
const months = parseCronField(monthField, 1, 12);
|
|
82
|
+
const dows = parseCronField(dowField, 0, 7);
|
|
83
|
+
if (!minutes || !hours || !doms || !months || !dows)
|
|
84
|
+
return null;
|
|
85
|
+
return {
|
|
86
|
+
minuteSet: new Set(minutes),
|
|
87
|
+
hourSet: new Set(hours),
|
|
88
|
+
domSet: new Set(doms),
|
|
89
|
+
monthSet: new Set(months),
|
|
90
|
+
// Normalize: 7 maps to 0 (both mean Sunday)
|
|
91
|
+
dowSet: new Set(dows.map((d) => (d === 7 ? 0 : d))),
|
|
92
|
+
domIsWild: domField === '*',
|
|
93
|
+
dowIsWild: dowField === '*',
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function matches(parsed, date) {
|
|
97
|
+
if (!parsed.monthSet.has(date.getMonth() + 1))
|
|
98
|
+
return false;
|
|
99
|
+
let dayMatch;
|
|
100
|
+
if (parsed.domIsWild && parsed.dowIsWild)
|
|
101
|
+
dayMatch = true;
|
|
102
|
+
else if (parsed.domIsWild)
|
|
103
|
+
dayMatch = parsed.dowSet.has(date.getDay());
|
|
104
|
+
else if (parsed.dowIsWild)
|
|
105
|
+
dayMatch = parsed.domSet.has(date.getDate());
|
|
106
|
+
else
|
|
107
|
+
dayMatch = parsed.domSet.has(date.getDate()) || parsed.dowSet.has(date.getDay());
|
|
108
|
+
if (!dayMatch)
|
|
109
|
+
return false;
|
|
110
|
+
if (!parsed.hourSet.has(date.getHours()))
|
|
111
|
+
return false;
|
|
112
|
+
return parsed.minuteSet.has(date.getMinutes());
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Compute the next cron occurrence strictly after `fromTime` (defaults to
|
|
116
|
+
* now). Returns `{isValid: false, nextRun: 0}` on malformed cron or if no
|
|
117
|
+
* occurrence is found within four years.
|
|
118
|
+
*/
|
|
119
|
+
export function parseCron(cron, fromTime) {
|
|
120
|
+
const parsed = parse(cron);
|
|
121
|
+
if (!parsed)
|
|
122
|
+
return { isValid: false, nextRun: 0 };
|
|
123
|
+
const base = fromTime !== undefined ? new Date(fromTime) : new Date();
|
|
124
|
+
const candidate = new Date(base);
|
|
125
|
+
candidate.setSeconds(0);
|
|
126
|
+
candidate.setMilliseconds(0);
|
|
127
|
+
candidate.setMinutes(candidate.getMinutes() + 1);
|
|
128
|
+
const limit = new Date(candidate);
|
|
129
|
+
limit.setFullYear(limit.getFullYear() + 4);
|
|
130
|
+
while (candidate < limit) {
|
|
131
|
+
if (!parsed.monthSet.has(candidate.getMonth() + 1)) {
|
|
132
|
+
candidate.setMonth(candidate.getMonth() + 1);
|
|
133
|
+
candidate.setDate(1);
|
|
134
|
+
candidate.setHours(0);
|
|
135
|
+
candidate.setMinutes(0);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
let dayMatch;
|
|
139
|
+
if (parsed.domIsWild && parsed.dowIsWild)
|
|
140
|
+
dayMatch = true;
|
|
141
|
+
else if (parsed.domIsWild)
|
|
142
|
+
dayMatch = parsed.dowSet.has(candidate.getDay());
|
|
143
|
+
else if (parsed.dowIsWild)
|
|
144
|
+
dayMatch = parsed.domSet.has(candidate.getDate());
|
|
145
|
+
else
|
|
146
|
+
dayMatch = parsed.domSet.has(candidate.getDate()) || parsed.dowSet.has(candidate.getDay());
|
|
147
|
+
if (!dayMatch) {
|
|
148
|
+
candidate.setDate(candidate.getDate() + 1);
|
|
149
|
+
candidate.setHours(0);
|
|
150
|
+
candidate.setMinutes(0);
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (!parsed.hourSet.has(candidate.getHours())) {
|
|
154
|
+
const nextHour = [...parsed.hourSet].find((h) => h > candidate.getHours());
|
|
155
|
+
if (nextHour !== undefined) {
|
|
156
|
+
candidate.setHours(nextHour);
|
|
157
|
+
candidate.setMinutes(0);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
candidate.setDate(candidate.getDate() + 1);
|
|
161
|
+
candidate.setHours(0);
|
|
162
|
+
candidate.setMinutes(0);
|
|
163
|
+
}
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (!parsed.minuteSet.has(candidate.getMinutes())) {
|
|
167
|
+
const nextMinute = [...parsed.minuteSet].find((m) => m > candidate.getMinutes());
|
|
168
|
+
if (nextMinute !== undefined) {
|
|
169
|
+
candidate.setMinutes(nextMinute);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
candidate.setHours(candidate.getHours() + 1);
|
|
173
|
+
candidate.setMinutes(0);
|
|
174
|
+
}
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
return { isValid: true, nextRun: candidate.getTime() };
|
|
178
|
+
}
|
|
179
|
+
return { isValid: false, nextRun: 0 };
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Find the most recent cron occurrence strictly after `lastRunAt` and at or
|
|
183
|
+
* before `now`. Returns `null` if no occurrence fits the window, the cron is
|
|
184
|
+
* malformed, or `lastRunAt` is not in the past.
|
|
185
|
+
*
|
|
186
|
+
* Used at daemon boot: if a schedule was supposed to fire while the daemon
|
|
187
|
+
* was down, this identifies the most recent missed occurrence so the caller
|
|
188
|
+
* can trigger one catch-up run. Older missed occurrences are intentionally
|
|
189
|
+
* dropped to avoid a flood of invocations after a long outage.
|
|
190
|
+
*
|
|
191
|
+
* Complexity: iterates backward minute-by-minute from `now` to `lastRunAt`,
|
|
192
|
+
* bounded at 14 days. For typical schedules the first matching minute is
|
|
193
|
+
* found within a few hundred iterations.
|
|
194
|
+
*/
|
|
195
|
+
export function computeMissedRun(cron, lastRunAt, now) {
|
|
196
|
+
if (!Number.isFinite(lastRunAt) || lastRunAt <= 0 || lastRunAt >= now)
|
|
197
|
+
return null;
|
|
198
|
+
const parsed = parse(cron);
|
|
199
|
+
if (!parsed)
|
|
200
|
+
return null;
|
|
201
|
+
const FOURTEEN_DAYS_MINUTES = 14 * 24 * 60;
|
|
202
|
+
const windowMinutes = Math.ceil((now - lastRunAt) / 60_000) + 1;
|
|
203
|
+
const maxIter = Math.min(windowMinutes, FOURTEEN_DAYS_MINUTES);
|
|
204
|
+
const candidate = new Date(now);
|
|
205
|
+
candidate.setSeconds(0);
|
|
206
|
+
candidate.setMilliseconds(0);
|
|
207
|
+
for (let i = 0; i < maxIter; i++) {
|
|
208
|
+
if (candidate.getTime() <= lastRunAt)
|
|
209
|
+
return null;
|
|
210
|
+
if (matches(parsed, candidate))
|
|
211
|
+
return candidate.getTime();
|
|
212
|
+
candidate.setMinutes(candidate.getMinutes() - 1);
|
|
213
|
+
}
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=cron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/daemon/cron.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boot-time persisted-schedule loader.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from server.ts so the logic can be imported by tests
|
|
5
|
+
* without triggering the daemon's bootstrap IIFE. The loader handles
|
|
6
|
+
* BOTH on-disk formats:
|
|
7
|
+
*
|
|
8
|
+
* - IPC (`source: 'ipc'`): written by `photon ps enable` and similar
|
|
9
|
+
* CLI hooks. Carries `photonName`, `args`, and `workingDir` on the
|
|
10
|
+
* task itself. TTL-swept after 30 days of inactivity.
|
|
11
|
+
* - ScheduleProvider: written by `this.schedule.create()` at runtime
|
|
12
|
+
* from photon code. Carries `params` (mapped to args) and `status`.
|
|
13
|
+
* The photon name is inferred from the directory path and passed
|
|
14
|
+
* in as `photonNameHint`. NOT TTL-swept — lifecycle is owned by
|
|
15
|
+
* the photon that created it.
|
|
16
|
+
*
|
|
17
|
+
* Before this unification, the boot scanner only handled IPC and every
|
|
18
|
+
* ScheduleProvider file was silently skipped (`source !== 'ipc'`). That
|
|
19
|
+
* caused schedules to stay dormant across daemon restarts until the
|
|
20
|
+
* owning photon happened to be invoked and triggered the lazy
|
|
21
|
+
* `autoRegisterFromMetadata` path.
|
|
22
|
+
*/
|
|
23
|
+
export interface PersistedScheduleJob {
|
|
24
|
+
id: string;
|
|
25
|
+
method: string;
|
|
26
|
+
args: Record<string, unknown>;
|
|
27
|
+
cron: string;
|
|
28
|
+
runCount: number;
|
|
29
|
+
createdAt: number;
|
|
30
|
+
createdBy: string;
|
|
31
|
+
photonName: string;
|
|
32
|
+
workingDir?: string;
|
|
33
|
+
photonPath?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Absolute path of the backing JSON file this job was loaded from.
|
|
36
|
+
* The fire handler uses it to drop phantom registrations whose
|
|
37
|
+
* backing file has been unlinked (e.g. via
|
|
38
|
+
* `this.schedule.cancel()`) out from under the in-memory cron map.
|
|
39
|
+
*/
|
|
40
|
+
sourceFile?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Epoch-ms of the last successful execution, read from the persisted
|
|
43
|
+
* `lastExecutionAt` field. Used by the daemon boot path to detect fire
|
|
44
|
+
* windows that elapsed while the daemon was down and schedule one
|
|
45
|
+
* catch-up run for the most recent missed occurrence.
|
|
46
|
+
*/
|
|
47
|
+
lastRun?: number;
|
|
48
|
+
}
|
|
49
|
+
export interface LoadScheduleCallbacks {
|
|
50
|
+
/** Called for every valid job. Return `true` if the engine accepted it. */
|
|
51
|
+
register: (job: PersistedScheduleJob) => boolean;
|
|
52
|
+
/** True if the given job id is already known to the cron engine. */
|
|
53
|
+
alreadyRegistered: (jobId: string) => boolean;
|
|
54
|
+
/** Optional logger hooks — no-op by default. */
|
|
55
|
+
warn?: (msg: string, ctx?: Record<string, unknown>) => void;
|
|
56
|
+
info?: (msg: string, ctx?: Record<string, unknown>) => void;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Scan one directory of schedule JSON files and hand every valid job
|
|
60
|
+
* to `cb.register`. Returns counts of loaded + skipped for logging.
|
|
61
|
+
*
|
|
62
|
+
* @param schedulesPath Directory containing {taskId}.json files.
|
|
63
|
+
* @param ttlMs Age in ms above which untouched IPC jobs are deleted.
|
|
64
|
+
* ScheduleProvider jobs ignore TTL (photon owns them).
|
|
65
|
+
* @param photonNameHint Used when task doesn't carry its own
|
|
66
|
+
* `photonName` (ScheduleProvider case — photon
|
|
67
|
+
* name is the parent directory's basename).
|
|
68
|
+
* @param workingDirHint Fallback working dir when task lacks one
|
|
69
|
+
* (the base dir that owns this schedule tree).
|
|
70
|
+
* @param cb Engine hooks.
|
|
71
|
+
*/
|
|
72
|
+
export declare function loadPersistedSchedulesFromDir(schedulesPath: string, ttlMs: number, photonNameHint: string | null, workingDirHint: string | undefined, cb: LoadScheduleCallbacks): {
|
|
73
|
+
loaded: number;
|
|
74
|
+
skipped: number;
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=schedule-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-loader.d.ts","sourceRoot":"","sources":["../../src/daemon/schedule-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,2EAA2E;IAC3E,QAAQ,EAAE,CAAC,GAAG,EAAE,oBAAoB,KAAK,OAAO,CAAC;IACjD,oEAAoE;IACpE,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAC9C,gDAAgD;IAChD,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5D,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAC7D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,6BAA6B,CAC3C,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,GAAG,IAAI,EAC7B,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,EAAE,EAAE,qBAAqB,GACxB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAyFrC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boot-time persisted-schedule loader.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from server.ts so the logic can be imported by tests
|
|
5
|
+
* without triggering the daemon's bootstrap IIFE. The loader handles
|
|
6
|
+
* BOTH on-disk formats:
|
|
7
|
+
*
|
|
8
|
+
* - IPC (`source: 'ipc'`): written by `photon ps enable` and similar
|
|
9
|
+
* CLI hooks. Carries `photonName`, `args`, and `workingDir` on the
|
|
10
|
+
* task itself. TTL-swept after 30 days of inactivity.
|
|
11
|
+
* - ScheduleProvider: written by `this.schedule.create()` at runtime
|
|
12
|
+
* from photon code. Carries `params` (mapped to args) and `status`.
|
|
13
|
+
* The photon name is inferred from the directory path and passed
|
|
14
|
+
* in as `photonNameHint`. NOT TTL-swept — lifecycle is owned by
|
|
15
|
+
* the photon that created it.
|
|
16
|
+
*
|
|
17
|
+
* Before this unification, the boot scanner only handled IPC and every
|
|
18
|
+
* ScheduleProvider file was silently skipped (`source !== 'ipc'`). That
|
|
19
|
+
* caused schedules to stay dormant across daemon restarts until the
|
|
20
|
+
* owning photon happened to be invoked and triggered the lazy
|
|
21
|
+
* `autoRegisterFromMetadata` path.
|
|
22
|
+
*/
|
|
23
|
+
import fs from 'fs';
|
|
24
|
+
import path from 'path';
|
|
25
|
+
/**
|
|
26
|
+
* Scan one directory of schedule JSON files and hand every valid job
|
|
27
|
+
* to `cb.register`. Returns counts of loaded + skipped for logging.
|
|
28
|
+
*
|
|
29
|
+
* @param schedulesPath Directory containing {taskId}.json files.
|
|
30
|
+
* @param ttlMs Age in ms above which untouched IPC jobs are deleted.
|
|
31
|
+
* ScheduleProvider jobs ignore TTL (photon owns them).
|
|
32
|
+
* @param photonNameHint Used when task doesn't carry its own
|
|
33
|
+
* `photonName` (ScheduleProvider case — photon
|
|
34
|
+
* name is the parent directory's basename).
|
|
35
|
+
* @param workingDirHint Fallback working dir when task lacks one
|
|
36
|
+
* (the base dir that owns this schedule tree).
|
|
37
|
+
* @param cb Engine hooks.
|
|
38
|
+
*/
|
|
39
|
+
export function loadPersistedSchedulesFromDir(schedulesPath, ttlMs, photonNameHint, workingDirHint, cb) {
|
|
40
|
+
let loaded = 0;
|
|
41
|
+
let skipped = 0;
|
|
42
|
+
let files;
|
|
43
|
+
try {
|
|
44
|
+
files = fs.readdirSync(schedulesPath).filter((f) => f.endsWith('.json'));
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return { loaded, skipped };
|
|
48
|
+
}
|
|
49
|
+
for (const file of files) {
|
|
50
|
+
const filePath = path.join(schedulesPath, file);
|
|
51
|
+
try {
|
|
52
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
53
|
+
const task = JSON.parse(content);
|
|
54
|
+
const isIpc = task.source === 'ipc';
|
|
55
|
+
const photonName = task.photonName || photonNameHint;
|
|
56
|
+
if (!task.id || !task.method || !task.cron || !photonName) {
|
|
57
|
+
cb.warn?.('Skipping invalid persisted schedule', { file: filePath });
|
|
58
|
+
skipped++;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
// Respect explicit pause/complete from ScheduleProvider tasks.
|
|
62
|
+
if (!isIpc && task.status && task.status !== 'active') {
|
|
63
|
+
skipped++;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// TTL applies only to IPC jobs — ScheduleProvider files are owned
|
|
67
|
+
// by the photon that created them and must persist until that
|
|
68
|
+
// photon removes them.
|
|
69
|
+
const lastExec = task.lastExecutionAt ? new Date(task.lastExecutionAt).getTime() : 0;
|
|
70
|
+
const created = task.createdAt ? new Date(task.createdAt).getTime() : 0;
|
|
71
|
+
const lastActivity = Math.max(lastExec, created);
|
|
72
|
+
if (isIpc && lastActivity > 0 && Date.now() - lastActivity > ttlMs) {
|
|
73
|
+
cb.info?.('Removing expired schedule (TTL)', {
|
|
74
|
+
jobId: task.id,
|
|
75
|
+
lastActivity: new Date(lastActivity).toISOString(),
|
|
76
|
+
});
|
|
77
|
+
try {
|
|
78
|
+
fs.unlinkSync(filePath);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
/* ignore */
|
|
82
|
+
}
|
|
83
|
+
skipped++;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
// ScheduleProvider ids are namespaced so they can't collide with
|
|
87
|
+
// raw IPC ids, and they read `params` where IPC reads `args`.
|
|
88
|
+
const jobId = isIpc ? task.id : `${photonName}:sched:${task.id}`;
|
|
89
|
+
const jobArgs = isIpc ? task.args || {} : task.params || {};
|
|
90
|
+
const jobWorkingDir = task.workingDir || workingDirHint;
|
|
91
|
+
if (cb.alreadyRegistered(jobId))
|
|
92
|
+
continue;
|
|
93
|
+
const job = {
|
|
94
|
+
id: jobId,
|
|
95
|
+
method: task.method,
|
|
96
|
+
args: jobArgs,
|
|
97
|
+
cron: task.cron,
|
|
98
|
+
runCount: task.executionCount || 0,
|
|
99
|
+
createdAt: created || Date.now(),
|
|
100
|
+
createdBy: task.createdBy || (isIpc ? 'ipc' : 'schedule-provider'),
|
|
101
|
+
photonName,
|
|
102
|
+
workingDir: jobWorkingDir,
|
|
103
|
+
sourceFile: filePath,
|
|
104
|
+
lastRun: lastExec > 0 ? lastExec : undefined,
|
|
105
|
+
};
|
|
106
|
+
if (cb.register(job)) {
|
|
107
|
+
loaded++;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
cb.warn?.('Failed to schedule persisted job (invalid cron?)', { jobId });
|
|
111
|
+
skipped++;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
cb.warn?.('Failed to load persisted schedule file', {
|
|
116
|
+
file: filePath,
|
|
117
|
+
error: err instanceof Error ? err.message : String(err),
|
|
118
|
+
});
|
|
119
|
+
skipped++;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return { loaded, skipped };
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=schedule-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-loader.js","sourceRoot":"","sources":["../../src/daemon/schedule-loader.ts"],"names":[],"mappings":"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"}
|