@objectstack/trigger-schedule 17.2.0 → 17.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/CHANGELOG.md +479 -0
- package/dist/index.d.mts +150 -4
- package/dist/index.d.ts +150 -4
- package/dist/index.js +208 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +208 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
package/dist/index.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ import { TimeRelativeTrigger as TimeRelativeTrigger$1 } from '@objectstack/spec/
|
|
|
23
23
|
*/
|
|
24
24
|
declare class ScheduleTriggerPlugin implements Plugin {
|
|
25
25
|
name: string;
|
|
26
|
-
type:
|
|
26
|
+
type: "standard";
|
|
27
27
|
version: string;
|
|
28
28
|
dependencies: string[];
|
|
29
29
|
init(ctx: PluginContext): Promise<void>;
|
|
@@ -61,14 +61,71 @@ interface FlowTrigger {
|
|
|
61
61
|
start(binding: FlowTriggerBinding, callback: (ctx: AutomationContext) => Promise<void>): void;
|
|
62
62
|
stop(flowName: string): void;
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* What a {@link ReplayGuard} answers when a job service is about to replay a
|
|
66
|
+
* job it does not itself understand. Structural mirror of the job adapter's
|
|
67
|
+
* own type — see the note on {@link JobServiceSurface}.
|
|
68
|
+
*/
|
|
69
|
+
type ReplayGuardDecision = {
|
|
70
|
+
readonly allow: true;
|
|
71
|
+
} | {
|
|
72
|
+
readonly allow: false;
|
|
73
|
+
/** Human-readable identity of the window that was already delivered. */
|
|
74
|
+
readonly window: string;
|
|
75
|
+
/** When that window's claim was taken (ISO-8601), if the ledger knows. */
|
|
76
|
+
readonly claimedAt: string | null;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* A per-job pre-flight the job service runs before `replay()` (#14501).
|
|
80
|
+
*
|
|
81
|
+
* It is asked, and it also PREPARES: a guard that answers `{ allow: true }`
|
|
82
|
+
* has already armed whatever its owner needs to let the replayed run through
|
|
83
|
+
* its own idempotency gate. So a job service must call it exactly once per
|
|
84
|
+
* replay, and must not call it for a replay it then abandons.
|
|
85
|
+
*/
|
|
86
|
+
type ReplayGuard = (options: {
|
|
87
|
+
readonly force: boolean;
|
|
88
|
+
}) => Promise<ReplayGuardDecision>;
|
|
64
89
|
/**
|
|
65
90
|
* The slice of `IJobService` this trigger needs: schedule a named job and
|
|
66
91
|
* cancel it. Typed structurally so the plugin depends on the spec contract
|
|
67
92
|
* shape, not a concrete adapter.
|
|
93
|
+
*
|
|
94
|
+
* `setReplayGuard` is OPTIONAL and is NOT part of the `IJobService` spec
|
|
95
|
+
* contract — it is the adapter-local registration `DbJobAdapter` grew for
|
|
96
|
+
* #14501, and a job service without it (the bootstrap `IntervalJobAdapter`,
|
|
97
|
+
* any third-party adapter) simply never installs the guard. That degradation
|
|
98
|
+
* is declared, not silent: see {@link ScheduleTrigger} for what is lost.
|
|
68
99
|
*/
|
|
69
100
|
interface JobServiceSurface {
|
|
70
101
|
schedule(name: string, schedule: JobSchedule, handler: JobHandler): Promise<void>;
|
|
71
102
|
cancel(name: string): Promise<void>;
|
|
103
|
+
setReplayGuard?(name: string, guard: ReplayGuard | null): void;
|
|
104
|
+
}
|
|
105
|
+
/** What a claimed dispatch turned into — mirror of the ledger's own type. */
|
|
106
|
+
type ScheduleDispatchOutcome = 'succeeded' | 'failed';
|
|
107
|
+
/** One dispatch-claim row, as this trigger reads it back. */
|
|
108
|
+
interface ScheduleDispatchClaim {
|
|
109
|
+
readonly outcome: ScheduleDispatchOutcome | null;
|
|
110
|
+
readonly claimedAt: string | null;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The slice of the automation service this trigger needs for once-per-window
|
|
114
|
+
* delivery (#14501): the same `sys_flow_dispatch` claim ledger the
|
|
115
|
+
* time-relative trigger uses for its per-record keys (#10220), plus the
|
|
116
|
+
* outcome half the #14501 ruling added.
|
|
117
|
+
*
|
|
118
|
+
* Typed structurally — like {@link JobServiceSurface} — so this plugin never
|
|
119
|
+
* learns the ledger's table name and takes no build dependency on
|
|
120
|
+
* `@objectstack/service-automation`. `settleDispatch` / `readDispatch` are
|
|
121
|
+
* optional for the same reason `claim` is resolved defensively: an automation
|
|
122
|
+
* service predating either one resolves to a partial surface, and the trigger
|
|
123
|
+
* degrades honestly rather than throwing at bind time.
|
|
124
|
+
*/
|
|
125
|
+
interface ScheduleDispatchLedger {
|
|
126
|
+
claim(key: string): Promise<boolean>;
|
|
127
|
+
settleDispatch?(key: string, outcome: ScheduleDispatchOutcome): Promise<void>;
|
|
128
|
+
readDispatch?(key: string): Promise<ScheduleDispatchClaim | null>;
|
|
72
129
|
}
|
|
73
130
|
/** Minimal logger surface (matches core's `ctx.logger`). */
|
|
74
131
|
interface TriggerLogger {
|
|
@@ -105,6 +162,26 @@ declare function normalizeSchedule(raw: unknown): JobSchedule | null;
|
|
|
105
162
|
* The job service is resolved lazily (per `start()`) via the supplied accessor,
|
|
106
163
|
* so we always pick up the job service's *upgraded* adapter (e.g. the durable
|
|
107
164
|
* DbJobAdapter that replaces the bootstrap interval adapter on `kernel:ready`).
|
|
165
|
+
*
|
|
166
|
+
* ## Once-per-window delivery (#14501)
|
|
167
|
+
*
|
|
168
|
+
* A scheduled flow claims a `(flow, tick-window)` key in the shared
|
|
169
|
+
* `sys_flow_dispatch` ledger before it launches, and settles that claim with
|
|
170
|
+
* the run's outcome afterwards — the same ledger the time-relative trigger
|
|
171
|
+
* claims per `(flow, record, window)` (#10220), with the key shape the
|
|
172
|
+
* maintainer's A + a2 ruling named. Three doors close at once:
|
|
173
|
+
*
|
|
174
|
+
* - a second tick inside one window finds the claim and does nothing;
|
|
175
|
+
* - a restart inside a window is that same case, because the key is a pure
|
|
176
|
+
* function of the schedule descriptor and the clock, not of process state;
|
|
177
|
+
* - an operator `replay()` of a window that was DELIVERED is refused with an
|
|
178
|
+
* ADR-0112 `RESOURCE_CONFLICT` / 409 envelope, via the
|
|
179
|
+
* {@link ReplayGuard} this trigger registers on the job service.
|
|
180
|
+
*
|
|
181
|
+
* What did NOT change is the error isolation: a throwing flow is still caught
|
|
182
|
+
* and swallowed so the ticker survives. It stopped being SILENT — the throw
|
|
183
|
+
* settles the window's claim `failed`, and a plain `replay()` re-runs a failed
|
|
184
|
+
* window — but the ticker's protection is unchanged and must stay that way.
|
|
108
185
|
*/
|
|
109
186
|
declare class ScheduleTrigger implements FlowTrigger {
|
|
110
187
|
readonly type = "schedule";
|
|
@@ -112,8 +189,77 @@ declare class ScheduleTrigger implements FlowTrigger {
|
|
|
112
189
|
private readonly logger;
|
|
113
190
|
/** flowName → job name registered for it, so stop() can cancel it. */
|
|
114
191
|
private readonly bound;
|
|
115
|
-
|
|
192
|
+
/** Dispatch-claim ledger (#14501), resolved lazily per fire. */
|
|
193
|
+
private readonly getLedger;
|
|
194
|
+
/** Injectable clock so window math is deterministic under test. */
|
|
195
|
+
private readonly now;
|
|
196
|
+
/**
|
|
197
|
+
* flowName → the ONE dispatch key a {@link ReplayGuard} has authorised for
|
|
198
|
+
* re-dispatch (#14501). A replay of a window whose claim is absent or
|
|
199
|
+
* failed must actually re-run it — but the handler's own claim gate would
|
|
200
|
+
* see the existing row and no-op, so the guard leaves a one-shot pass here
|
|
201
|
+
* and the handler consumes it. In-process by construction and correctly
|
|
202
|
+
* so: the pass is written and read inside a single `replay()` call chain.
|
|
203
|
+
*
|
|
204
|
+
* Keyed by FLOW rather than accumulated in a set, so a pass a job service
|
|
205
|
+
* asked for and then abandoned is overwritten by the next one instead of
|
|
206
|
+
* outliving its window — at most one outstanding pass per bound flow, and
|
|
207
|
+
* `stop()` takes it with the binding.
|
|
208
|
+
*
|
|
209
|
+
* ⚠️ Residue is therefore bounded but not zero: an abandoned pass survives
|
|
210
|
+
* until this flow's next guard call replaces it, or `stop()` drops it. A
|
|
211
|
+
* later fire does NOT clear it — the handler deletes the entry only when
|
|
212
|
+
* the pass MATCHES the window it just computed — so an abandoned pass
|
|
213
|
+
* outlives every fire in every other window. It stays inert through all of
|
|
214
|
+
* them for the same reason: a pass naming a window that has passed can
|
|
215
|
+
* never match again. Its blast radius is one fire of one flow inside the
|
|
216
|
+
* window the pass names, and only if that window is still current — a fire
|
|
217
|
+
* that would have been a no-op runs instead.
|
|
218
|
+
*/
|
|
219
|
+
private readonly replayPasses;
|
|
220
|
+
/** Whether the in-process-only dedup degradation has been said (once). */
|
|
221
|
+
private claimDegradationWarned;
|
|
222
|
+
/** Whether the "no replay guard could be installed" degradation has been said (once). */
|
|
223
|
+
private replayGuardDegradationWarned;
|
|
224
|
+
constructor(getJobService: () => JobServiceSurface | null, logger: TriggerLogger, getLedger?: () => ScheduleDispatchLedger | null, now?: () => Date);
|
|
116
225
|
start(binding: FlowTriggerBinding, callback: (ctx: AutomationContext) => Promise<void>): void;
|
|
226
|
+
/**
|
|
227
|
+
* Install the `replay()` pre-flight for this job (#14501), when the job
|
|
228
|
+
* service has somewhere to put one.
|
|
229
|
+
*
|
|
230
|
+
* Degradation contract, declared once: a job service without
|
|
231
|
+
* `setReplayGuard` (the bootstrap `IntervalJobAdapter`, any adapter
|
|
232
|
+
* predating #14501) keeps every other guarantee here — a second tick in a
|
|
233
|
+
* window is still a no-op, a throw is still recorded failed — but an
|
|
234
|
+
* operator replay of a DELIVERED window can no longer be refused loudly.
|
|
235
|
+
* It hits the handler's claim gate and returns having done nothing, which
|
|
236
|
+
* is the silent no-op the ruling exists to prevent, so it is said out loud
|
|
237
|
+
* here instead.
|
|
238
|
+
*
|
|
239
|
+
* ⚠ Said only when a ledger is actually attached. With no ledger nothing is
|
|
240
|
+
* ever RECORDED as delivered, so there is no refusal to lose and the line
|
|
241
|
+
* would be a false alarm — that deployment's real degradation is the
|
|
242
|
+
* "delivery is NOT deduplicated" warning {@link claimDispatch} already
|
|
243
|
+
* emits, and stacking a second, vacuous warning on top of it buries the
|
|
244
|
+
* one that matters.
|
|
245
|
+
*/
|
|
246
|
+
private installReplayGuard;
|
|
247
|
+
/**
|
|
248
|
+
* Claim one `(flow, tick-window)` dispatch key (#14501): `true` = launch,
|
|
249
|
+
* `false` = this window was already dispatched (an earlier tick this
|
|
250
|
+
* process, or a previous process lifetime).
|
|
251
|
+
*
|
|
252
|
+
* Degradation contract, deliberately identical to the time-relative
|
|
253
|
+
* trigger's: a ledger call that THROWS dispatches anyway (availability
|
|
254
|
+
* over strict-once — a broken ledger must never silently swallow a
|
|
255
|
+
* digest), and a missing ledger is warned once because the once-per-window
|
|
256
|
+
* guarantee then no longer survives a kernel rebuild.
|
|
257
|
+
*/
|
|
258
|
+
private claimDispatch;
|
|
259
|
+
/** Record what a dispatch turned into. Best-effort: never fails the run. */
|
|
260
|
+
private settleDispatch;
|
|
261
|
+
/** Read one dispatch claim. A ledger that cannot answer reports `null`. */
|
|
262
|
+
private readDispatch;
|
|
117
263
|
stop(flowName: string): void;
|
|
118
264
|
}
|
|
119
265
|
|
|
@@ -136,7 +282,7 @@ declare class ScheduleTrigger implements FlowTrigger {
|
|
|
136
282
|
*/
|
|
137
283
|
declare class TimeRelativeTriggerPlugin implements Plugin {
|
|
138
284
|
name: string;
|
|
139
|
-
type:
|
|
285
|
+
type: "standard";
|
|
140
286
|
version: string;
|
|
141
287
|
dependencies: string[];
|
|
142
288
|
init(ctx: PluginContext): Promise<void>;
|
|
@@ -304,4 +450,4 @@ declare class TimeRelativeTrigger implements FlowTrigger {
|
|
|
304
450
|
stop(flowName: string): void;
|
|
305
451
|
}
|
|
306
452
|
|
|
307
|
-
export { type DateWindow, type FlowDispatchClaimSurface, type FlowTrigger, type FlowTriggerBinding, type JobServiceSurface, ScheduleTrigger, ScheduleTriggerPlugin, type TimeRelativeDataEngine, TimeRelativeTrigger, TimeRelativeTriggerPlugin, type TriggerLogger, type WindowClaimScope, buildWindowWhere, computeDateWindows, computeWindowClaimScopes, normalizeSchedule };
|
|
453
|
+
export { type DateWindow, type FlowDispatchClaimSurface, type FlowTrigger, type FlowTriggerBinding, type JobServiceSurface, type ReplayGuard, type ReplayGuardDecision, type ScheduleDispatchClaim, type ScheduleDispatchLedger, type ScheduleDispatchOutcome, ScheduleTrigger, ScheduleTriggerPlugin, type TimeRelativeDataEngine, TimeRelativeTrigger, TimeRelativeTriggerPlugin, type TriggerLogger, type WindowClaimScope, buildWindowWhere, computeDateWindows, computeWindowClaimScopes, normalizeSchedule };
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,50 @@ __export(index_exports, {
|
|
|
32
32
|
module.exports = __toCommonJS(index_exports);
|
|
33
33
|
|
|
34
34
|
// src/schedule-trigger.ts
|
|
35
|
+
var import_croner = require("croner");
|
|
36
|
+
function computeTickWindow(schedule, now) {
|
|
37
|
+
const nowMs = now.getTime();
|
|
38
|
+
if (!Number.isFinite(nowMs)) return null;
|
|
39
|
+
if (schedule.type === "cron") {
|
|
40
|
+
const expression = schedule.expression;
|
|
41
|
+
if (!expression) return null;
|
|
42
|
+
const reference = new Date(Math.floor(nowMs / 1e3) * 1e3 + 1e3);
|
|
43
|
+
let previous;
|
|
44
|
+
try {
|
|
45
|
+
const pattern = new import_croner.Cron(expression, { timezone: schedule.timezone ?? "UTC" });
|
|
46
|
+
previous = pattern.previousRuns(1, reference)[0];
|
|
47
|
+
pattern.stop();
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
if (!previous) return null;
|
|
52
|
+
const startedAt = previous.toISOString();
|
|
53
|
+
return {
|
|
54
|
+
startedAt,
|
|
55
|
+
label: `cron '${expression}' window starting ${startedAt}`
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (schedule.type === "interval") {
|
|
59
|
+
const intervalMs = schedule.intervalMs;
|
|
60
|
+
if (!intervalMs || intervalMs <= 0) return null;
|
|
61
|
+
const startedAt = new Date(Math.floor(nowMs / intervalMs) * intervalMs).toISOString();
|
|
62
|
+
return {
|
|
63
|
+
startedAt,
|
|
64
|
+
label: `interval ${intervalMs}ms window starting ${startedAt}`
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (schedule.type === "once") {
|
|
68
|
+
if (!schedule.at) return null;
|
|
69
|
+
const at = new Date(schedule.at);
|
|
70
|
+
if (!Number.isFinite(at.getTime())) return null;
|
|
71
|
+
const startedAt = at.toISOString();
|
|
72
|
+
return { startedAt, label: `one-shot window at ${startedAt}` };
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
function scheduleDispatchKey(flowName, window) {
|
|
77
|
+
return `schedule:${flowName}:${window.startedAt}`;
|
|
78
|
+
}
|
|
35
79
|
var JOB_PREFIX = "flow-schedule";
|
|
36
80
|
function reportBindFailure(logger, tag, flowName, err) {
|
|
37
81
|
const report = logger.error?.bind(logger) ?? logger.warn.bind(logger);
|
|
@@ -68,12 +112,42 @@ function normalizeSchedule(raw) {
|
|
|
68
112
|
return null;
|
|
69
113
|
}
|
|
70
114
|
var ScheduleTrigger = class {
|
|
71
|
-
constructor(getJobService, logger) {
|
|
115
|
+
constructor(getJobService, logger, getLedger = () => null, now = () => /* @__PURE__ */ new Date()) {
|
|
72
116
|
this.type = "schedule";
|
|
73
117
|
/** flowName → job name registered for it, so stop() can cancel it. */
|
|
74
118
|
this.bound = /* @__PURE__ */ new Map();
|
|
119
|
+
/**
|
|
120
|
+
* flowName → the ONE dispatch key a {@link ReplayGuard} has authorised for
|
|
121
|
+
* re-dispatch (#14501). A replay of a window whose claim is absent or
|
|
122
|
+
* failed must actually re-run it — but the handler's own claim gate would
|
|
123
|
+
* see the existing row and no-op, so the guard leaves a one-shot pass here
|
|
124
|
+
* and the handler consumes it. In-process by construction and correctly
|
|
125
|
+
* so: the pass is written and read inside a single `replay()` call chain.
|
|
126
|
+
*
|
|
127
|
+
* Keyed by FLOW rather than accumulated in a set, so a pass a job service
|
|
128
|
+
* asked for and then abandoned is overwritten by the next one instead of
|
|
129
|
+
* outliving its window — at most one outstanding pass per bound flow, and
|
|
130
|
+
* `stop()` takes it with the binding.
|
|
131
|
+
*
|
|
132
|
+
* ⚠️ Residue is therefore bounded but not zero: an abandoned pass survives
|
|
133
|
+
* until this flow's next guard call replaces it, or `stop()` drops it. A
|
|
134
|
+
* later fire does NOT clear it — the handler deletes the entry only when
|
|
135
|
+
* the pass MATCHES the window it just computed — so an abandoned pass
|
|
136
|
+
* outlives every fire in every other window. It stays inert through all of
|
|
137
|
+
* them for the same reason: a pass naming a window that has passed can
|
|
138
|
+
* never match again. Its blast radius is one fire of one flow inside the
|
|
139
|
+
* window the pass names, and only if that window is still current — a fire
|
|
140
|
+
* that would have been a no-op runs instead.
|
|
141
|
+
*/
|
|
142
|
+
this.replayPasses = /* @__PURE__ */ new Map();
|
|
143
|
+
/** Whether the in-process-only dedup degradation has been said (once). */
|
|
144
|
+
this.claimDegradationWarned = false;
|
|
145
|
+
/** Whether the "no replay guard could be installed" degradation has been said (once). */
|
|
146
|
+
this.replayGuardDegradationWarned = false;
|
|
75
147
|
this.getJobService = getJobService;
|
|
76
148
|
this.logger = logger;
|
|
149
|
+
this.getLedger = getLedger;
|
|
150
|
+
this.now = now;
|
|
77
151
|
}
|
|
78
152
|
start(binding, callback) {
|
|
79
153
|
const raw = binding.schedule ?? binding.config?.schedule;
|
|
@@ -94,6 +168,19 @@ var ScheduleTrigger = class {
|
|
|
94
168
|
this.stop(binding.flowName);
|
|
95
169
|
const jobName = `${JOB_PREFIX}:${binding.flowName}`;
|
|
96
170
|
const handler = async ({ jobId }) => {
|
|
171
|
+
const window = computeTickWindow(schedule, this.now());
|
|
172
|
+
const key = window ? scheduleDispatchKey(binding.flowName, window) : null;
|
|
173
|
+
if (key) {
|
|
174
|
+
const replayPass = this.replayPasses.get(binding.flowName) === key;
|
|
175
|
+
if (replayPass) this.replayPasses.delete(binding.flowName);
|
|
176
|
+
const claimed = await this.claimDispatch(binding.flowName, key);
|
|
177
|
+
if (!claimed && !replayPass) {
|
|
178
|
+
this.logger.debug?.(
|
|
179
|
+
`[schedule] flow '${binding.flowName}' already dispatched for ${window.label} \u2014 skipping`
|
|
180
|
+
);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
97
184
|
try {
|
|
98
185
|
const ctx = {
|
|
99
186
|
event: "schedule",
|
|
@@ -104,12 +191,15 @@ var ScheduleTrigger = class {
|
|
|
104
191
|
}
|
|
105
192
|
};
|
|
106
193
|
await callback(ctx);
|
|
194
|
+
if (key) await this.settleDispatch(binding.flowName, key, "succeeded");
|
|
107
195
|
} catch (err) {
|
|
108
196
|
this.logger.warn(
|
|
109
197
|
`[schedule] flow '${binding.flowName}' execution failed: ${err?.message ?? String(err)}`
|
|
110
198
|
);
|
|
199
|
+
if (key) await this.settleDispatch(binding.flowName, key, "failed");
|
|
111
200
|
}
|
|
112
201
|
};
|
|
202
|
+
this.installReplayGuard(jobService, jobName, binding.flowName, schedule);
|
|
113
203
|
this.bound.set(binding.flowName, jobName);
|
|
114
204
|
void Promise.resolve(jobService.schedule(jobName, schedule, handler)).then(() => {
|
|
115
205
|
this.logger.info(
|
|
@@ -120,12 +210,117 @@ var ScheduleTrigger = class {
|
|
|
120
210
|
reportBindFailure(this.logger, "schedule", binding.flowName, err);
|
|
121
211
|
});
|
|
122
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* Install the `replay()` pre-flight for this job (#14501), when the job
|
|
215
|
+
* service has somewhere to put one.
|
|
216
|
+
*
|
|
217
|
+
* Degradation contract, declared once: a job service without
|
|
218
|
+
* `setReplayGuard` (the bootstrap `IntervalJobAdapter`, any adapter
|
|
219
|
+
* predating #14501) keeps every other guarantee here — a second tick in a
|
|
220
|
+
* window is still a no-op, a throw is still recorded failed — but an
|
|
221
|
+
* operator replay of a DELIVERED window can no longer be refused loudly.
|
|
222
|
+
* It hits the handler's claim gate and returns having done nothing, which
|
|
223
|
+
* is the silent no-op the ruling exists to prevent, so it is said out loud
|
|
224
|
+
* here instead.
|
|
225
|
+
*
|
|
226
|
+
* ⚠ Said only when a ledger is actually attached. With no ledger nothing is
|
|
227
|
+
* ever RECORDED as delivered, so there is no refusal to lose and the line
|
|
228
|
+
* would be a false alarm — that deployment's real degradation is the
|
|
229
|
+
* "delivery is NOT deduplicated" warning {@link claimDispatch} already
|
|
230
|
+
* emits, and stacking a second, vacuous warning on top of it buries the
|
|
231
|
+
* one that matters.
|
|
232
|
+
*/
|
|
233
|
+
installReplayGuard(jobService, jobName, flowName, schedule) {
|
|
234
|
+
if (typeof jobService.setReplayGuard !== "function") {
|
|
235
|
+
if (!this.replayGuardDegradationWarned && this.getLedger() !== null) {
|
|
236
|
+
this.replayGuardDegradationWarned = true;
|
|
237
|
+
this.logger.warn(
|
|
238
|
+
`[schedule] job service has no replay guard registration \u2014 a replay of a scheduled flow's ALREADY-DELIVERED tick window cannot be refused and will quietly do nothing instead of raising RESOURCE_CONFLICT. Ticks are unaffected.`
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
jobService.setReplayGuard(jobName, async ({ force }) => {
|
|
244
|
+
const window = computeTickWindow(schedule, this.now());
|
|
245
|
+
if (!window) return { allow: true };
|
|
246
|
+
const key = scheduleDispatchKey(flowName, window);
|
|
247
|
+
const claim = force ? null : await this.readDispatch(flowName, key);
|
|
248
|
+
if (claim?.outcome === "succeeded") {
|
|
249
|
+
return { allow: false, window: window.label, claimedAt: claim.claimedAt };
|
|
250
|
+
}
|
|
251
|
+
this.replayPasses.set(flowName, key);
|
|
252
|
+
return { allow: true };
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Claim one `(flow, tick-window)` dispatch key (#14501): `true` = launch,
|
|
257
|
+
* `false` = this window was already dispatched (an earlier tick this
|
|
258
|
+
* process, or a previous process lifetime).
|
|
259
|
+
*
|
|
260
|
+
* Degradation contract, deliberately identical to the time-relative
|
|
261
|
+
* trigger's: a ledger call that THROWS dispatches anyway (availability
|
|
262
|
+
* over strict-once — a broken ledger must never silently swallow a
|
|
263
|
+
* digest), and a missing ledger is warned once because the once-per-window
|
|
264
|
+
* guarantee then no longer survives a kernel rebuild.
|
|
265
|
+
*/
|
|
266
|
+
async claimDispatch(flowName, key) {
|
|
267
|
+
const ledger = this.getLedger();
|
|
268
|
+
if (ledger && typeof ledger.claim === "function") {
|
|
269
|
+
try {
|
|
270
|
+
return await ledger.claim(key);
|
|
271
|
+
} catch (err) {
|
|
272
|
+
this.logger.warn(
|
|
273
|
+
`[schedule] flow '${flowName}' dispatch-claim failed for key '${key}' \u2014 dispatching anyway (availability over strict-once; the same window may re-fire until the claim store recovers): ${err?.message ?? String(err)}`
|
|
274
|
+
);
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (!this.claimDegradationWarned) {
|
|
279
|
+
this.claimDegradationWarned = true;
|
|
280
|
+
this.logger.warn(
|
|
281
|
+
`[schedule] no dispatch-claim surface (automation service missing or without claim()) \u2014 scheduled-flow delivery is NOT deduplicated: a restart inside a tick window, or an operator replay, can deliver the same window twice.`
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
/** Record what a dispatch turned into. Best-effort: never fails the run. */
|
|
287
|
+
async settleDispatch(flowName, key, outcome) {
|
|
288
|
+
const ledger = this.getLedger();
|
|
289
|
+
if (!ledger || typeof ledger.settleDispatch !== "function") return;
|
|
290
|
+
try {
|
|
291
|
+
await ledger.settleDispatch(key, outcome);
|
|
292
|
+
} catch (err) {
|
|
293
|
+
this.logger.warn(
|
|
294
|
+
`[schedule] flow '${flowName}' could not record dispatch outcome '${outcome}' for key '${key}' \u2014 the claim stays unsettled and reads as NOT delivered, so a later replay is allowed through: ${err?.message ?? String(err)}`
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
/** Read one dispatch claim. A ledger that cannot answer reports `null`. */
|
|
299
|
+
async readDispatch(flowName, key) {
|
|
300
|
+
const ledger = this.getLedger();
|
|
301
|
+
if (!ledger || typeof ledger.readDispatch !== "function") return null;
|
|
302
|
+
try {
|
|
303
|
+
return await ledger.readDispatch(key);
|
|
304
|
+
} catch (err) {
|
|
305
|
+
this.logger.warn(
|
|
306
|
+
`[schedule] flow '${flowName}' dispatch-claim read failed for key '${key}' \u2014 treating the window as unclaimed so the replay proceeds: ${err?.message ?? String(err)}`
|
|
307
|
+
);
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
123
311
|
stop(flowName) {
|
|
124
312
|
const jobName = this.bound.get(flowName);
|
|
125
313
|
if (!jobName) return;
|
|
126
314
|
this.bound.delete(flowName);
|
|
315
|
+
this.replayPasses.delete(flowName);
|
|
127
316
|
const jobService = this.getJobService();
|
|
128
317
|
if (!jobService || typeof jobService.cancel !== "function") return;
|
|
318
|
+
if (typeof jobService.setReplayGuard === "function") {
|
|
319
|
+
try {
|
|
320
|
+
jobService.setReplayGuard(jobName, null);
|
|
321
|
+
} catch {
|
|
322
|
+
}
|
|
323
|
+
}
|
|
129
324
|
void Promise.resolve(jobService.cancel(jobName)).then(() => this.logger.debug?.(`[schedule] unbound flow '${flowName}'`)).catch((err) => {
|
|
130
325
|
this.logger.warn(
|
|
131
326
|
`[schedule] failed to unbind flow '${flowName}': ${err?.message ?? String(err)}`
|
|
@@ -161,7 +356,18 @@ var ScheduleTriggerPlugin = class {
|
|
|
161
356
|
}
|
|
162
357
|
const trigger = new ScheduleTrigger(
|
|
163
358
|
() => this.resolveService(ctx, "job"),
|
|
164
|
-
ctx.logger
|
|
359
|
+
ctx.logger,
|
|
360
|
+
// #14501 — once-per-(flow, tick-window) delivery goes through
|
|
361
|
+
// the SAME automation service this plugin already resolves,
|
|
362
|
+
// and the same `sys_flow_dispatch` ledger the time-relative
|
|
363
|
+
// trigger claims against (#10220). The trigger computes the
|
|
364
|
+
// key and never learns the ledger's table name. An automation
|
|
365
|
+
// service predating claim() resolves to null and the trigger
|
|
366
|
+
// degrades — honestly, warned once — to no dedup at all.
|
|
367
|
+
() => {
|
|
368
|
+
const svc = this.resolveService(ctx, "automation");
|
|
369
|
+
return svc && typeof svc.claim === "function" ? svc : null;
|
|
370
|
+
}
|
|
165
371
|
);
|
|
166
372
|
automation.registerTrigger(trigger);
|
|
167
373
|
ctx.logger.info("ScheduleTriggerPlugin: schedule trigger registered");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/schedule-trigger.ts","../src/plugin.ts","../src/time-relative-trigger.ts","../src/time-relative-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nexport { ScheduleTriggerPlugin } from './plugin.js';\nexport { ScheduleTrigger, normalizeSchedule } from './schedule-trigger.js';\nexport type {\n FlowTrigger,\n FlowTriggerBinding,\n JobServiceSurface,\n TriggerLogger,\n} from './schedule-trigger.js';\n\nexport { TimeRelativeTriggerPlugin } from './time-relative-plugin.js';\nexport {\n TimeRelativeTrigger,\n computeDateWindows,\n computeWindowClaimScopes,\n buildWindowWhere,\n} from './time-relative-trigger.js';\nexport type {\n TimeRelativeDataEngine,\n DateWindow,\n WindowClaimScope,\n FlowDispatchClaimSurface,\n} from './time-relative-trigger.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { AutomationContext } from '@objectstack/spec/contracts';\nimport type { JobSchedule, JobHandler } from '@objectstack/spec/contracts';\n\n/**\n * Structural mirror of the automation engine's `FlowTriggerBinding`\n * (service-automation/src/engine.ts). Declared locally so this trigger plugin\n * stays decoupled from the automation package — same pattern the record-change\n * trigger and the connector / messaging integrations use. The engine parses the\n * flow's start node and hands us a binding whose `schedule` carries the\n * cron/interval/once descriptor.\n */\nexport interface FlowTriggerBinding {\n readonly flowName: string;\n readonly object?: string;\n readonly event?: string;\n readonly condition?: string | { dialect?: string; source?: string; ast?: unknown };\n readonly schedule?: unknown;\n readonly config?: Record<string, unknown>;\n}\n\n/**\n * Structural mirror of the engine's `FlowTrigger` extension point. The engine\n * calls {@link start} with a parsed binding + a callback that runs the flow,\n * and {@link stop} when the flow is unregistered/disabled.\n */\nexport interface FlowTrigger {\n readonly type: string;\n start(binding: FlowTriggerBinding, callback: (ctx: AutomationContext) => Promise<void>): void;\n stop(flowName: string): void;\n}\n\n/**\n * The slice of `IJobService` this trigger needs: schedule a named job and\n * cancel it. Typed structurally so the plugin depends on the spec contract\n * shape, not a concrete adapter.\n */\nexport interface JobServiceSurface {\n schedule(name: string, schedule: JobSchedule, handler: JobHandler): Promise<void>;\n cancel(name: string): Promise<void>;\n}\n\n/** Minimal logger surface (matches core's `ctx.logger`). */\nexport interface TriggerLogger {\n info(msg: string, ...args: unknown[]): void;\n warn(msg: string, ...args: unknown[]): void;\n debug?(msg: string, ...args: unknown[]): void;\n /**\n * Execution failures log here when available (falling back to `warn`).\n * ERROR matters operationally: the CLI's boot-quiet window swallows\n * stdout (debug/info/warn) but stderr (error/fatal) always lands — so a\n * per-record sweep failure stays visible. Mirrors the record-change\n * trigger's logger surface.\n */\n error?(msg: string, ...args: unknown[]): void;\n}\n\nconst JOB_PREFIX = 'flow-schedule';\n\n/**\n * Report a scheduled flow that failed to bind to the job service.\n *\n * **Why this is `error` and not `warn`** — the repo's degradation-log-level\n * rule (AGENTS.md) decides the level with one question: after the degradation,\n * does the system still look normal from the outside while something it claims\n * is in place has not landed? Here it does, completely: the flow stays\n * published and active in `sys_metadata`, Studio lists it, the metadata API\n * serves it and `verify_build` passes — while nothing will ever fire it. That\n * is persisted state and runtime state disagreeing, which the rule puts in the\n * `error` class, not the functional-degradation class.\n *\n * The neighbouring composition branch — \"no job service is registered at all\" —\n * deliberately stays at `warn`: the system is *visibly* smaller and the rule\n * names that exact message as correctly a `warn`. The distinction is not the\n * severity of the outcome, it is whether the outside can see it.\n *\n * An `error` here owes two things, both in the first line it prints: the\n * concrete consequence (including that everything else keeps looking healthy)\n * and the remedy. Kept in one helper so both triggers say it the same way.\n */\nexport function reportBindFailure(\n logger: TriggerLogger,\n tag: 'schedule' | 'time-relative',\n flowName: string,\n err: unknown,\n): void {\n const report = logger.error?.bind(logger) ?? logger.warn.bind(logger);\n report(\n `[${tag}] flow '${flowName}' FAILED to bind to the job service: ${(err as Error)?.message ?? String(err)}. ` +\n 'The flow stays published and active — Studio, the metadata API and verify_build all keep reporting it ' +\n 'healthy — but nothing will fire it until it binds. Re-publish the flow (or restart the environment) to retry.',\n );\n}\n\n/**\n * Normalize a flow's raw `schedule` descriptor into a {@link JobSchedule}, or\n * `null` if it can't be understood. Accepts the canonical\n * `{ type: 'cron'|'interval'|'once', ... }` shape plus a few ergonomic\n * shorthands (a bare cron string, `{ cron }`, `{ expression }`, `{ every }` /\n * `{ intervalMs }`, `{ at }`).\n */\nexport function normalizeSchedule(raw: unknown): JobSchedule | null {\n if (raw == null) return null;\n\n // Bare cron string, e.g. '0 1 * * *'.\n if (typeof raw === 'string') {\n const expr = raw.trim();\n return expr ? { type: 'cron', expression: expr } : null;\n }\n\n if (typeof raw !== 'object') return null;\n const s = raw as Record<string, unknown>;\n\n const type = typeof s.type === 'string' ? s.type : undefined;\n\n if (type === 'cron' || (!type && (typeof s.cron === 'string' || typeof s.expression === 'string'))) {\n const expression =\n (typeof s.expression === 'string' && s.expression) ||\n (typeof s.cron === 'string' && s.cron) ||\n undefined;\n if (!expression) return null;\n const out: JobSchedule = { type: 'cron', expression };\n if (typeof s.timezone === 'string') out.timezone = s.timezone;\n return out;\n }\n\n if (type === 'interval' || (!type && (typeof s.intervalMs === 'number' || typeof s.every === 'number'))) {\n const intervalMs =\n (typeof s.intervalMs === 'number' && s.intervalMs) ||\n (typeof s.every === 'number' && s.every) ||\n undefined;\n if (!intervalMs || intervalMs <= 0) return null;\n return { type: 'interval', intervalMs };\n }\n\n if (type === 'once' || (!type && typeof s.at === 'string')) {\n const at = typeof s.at === 'string' ? s.at : undefined;\n if (!at) return null;\n return { type: 'once', at };\n }\n\n return null;\n}\n\n/**\n * ScheduleTrigger\n *\n * Bridges the automation engine's {@link FlowTrigger} extension point to the\n * platform {@link JobServiceSurface}. For each schedule-triggered flow the\n * engine activates, it registers a job whose handler runs the flow; the job\n * service owns the actual cron/interval/once timing (so this trigger stays\n * adapter-agnostic — cron schedules need a cron-capable adapter, which the\n * job service selects).\n *\n * The job service is resolved lazily (per `start()`) via the supplied accessor,\n * so we always pick up the job service's *upgraded* adapter (e.g. the durable\n * DbJobAdapter that replaces the bootstrap interval adapter on `kernel:ready`).\n */\nexport class ScheduleTrigger implements FlowTrigger {\n readonly type = 'schedule';\n\n private readonly getJobService: () => JobServiceSurface | null;\n private readonly logger: TriggerLogger;\n /** flowName → job name registered for it, so stop() can cancel it. */\n private readonly bound = new Map<string, string>();\n\n constructor(getJobService: () => JobServiceSurface | null, logger: TriggerLogger) {\n this.getJobService = getJobService;\n this.logger = logger;\n }\n\n start(binding: FlowTriggerBinding, callback: (ctx: AutomationContext) => Promise<void>): void {\n const raw = binding.schedule ?? (binding.config as Record<string, unknown> | undefined)?.schedule;\n const schedule = normalizeSchedule(raw);\n if (!schedule) {\n this.logger.warn(\n `[schedule] flow '${binding.flowName}' has no recognizable schedule descriptor — not bound`,\n );\n return;\n }\n\n const jobService = this.getJobService();\n if (!jobService || typeof jobService.schedule !== 'function') {\n this.logger.warn(\n `[schedule] job service unavailable — flow '${binding.flowName}' not scheduled`,\n );\n return;\n }\n\n // Idempotent: drop any prior schedule for this flow before re-binding\n // (covers disable→enable cycles and hot reload).\n this.stop(binding.flowName);\n\n const jobName = `${JOB_PREFIX}:${binding.flowName}`;\n\n const handler: JobHandler = async ({ jobId }) => {\n try {\n const ctx: AutomationContext = {\n event: 'schedule',\n params: {\n jobId,\n flowName: binding.flowName,\n schedule,\n },\n };\n await callback(ctx);\n } catch (err) {\n // Error isolation: a scheduled flow failure must not crash the\n // job runner / ticker. Log and swallow.\n this.logger.warn(\n `[schedule] flow '${binding.flowName}' execution failed: ${(err as Error)?.message ?? String(err)}`,\n );\n }\n };\n\n this.bound.set(binding.flowName, jobName);\n // FlowTrigger.start is sync; the job service's schedule() is async.\n // Fire-and-forget with error logging.\n void Promise.resolve(jobService.schedule(jobName, schedule, handler))\n .then(() => {\n this.logger.info(\n `[schedule] bound flow '${binding.flowName}' → ${schedule.type}` +\n (schedule.expression ? ` '${schedule.expression}'` : '') +\n (schedule.intervalMs ? ` every ${schedule.intervalMs}ms` : '') +\n (schedule.at ? ` at ${schedule.at}` : ''),\n );\n })\n .catch((err) => {\n this.bound.delete(binding.flowName);\n reportBindFailure(this.logger, 'schedule', binding.flowName, err);\n });\n }\n\n stop(flowName: string): void {\n const jobName = this.bound.get(flowName);\n if (!jobName) return;\n this.bound.delete(flowName);\n const jobService = this.getJobService();\n if (!jobService || typeof jobService.cancel !== 'function') return;\n void Promise.resolve(jobService.cancel(jobName))\n .then(() => this.logger.debug?.(`[schedule] unbound flow '${flowName}'`))\n .catch((err) => {\n this.logger.warn(\n `[schedule] failed to unbind flow '${flowName}': ${(err as Error)?.message ?? String(err)}`,\n );\n });\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { ScheduleTrigger } from './schedule-trigger.js';\nimport type { FlowTrigger, JobServiceSurface } from './schedule-trigger.js';\n\n/**\n * The slice of the automation engine this plugin needs: register a trigger on\n * its `FlowTrigger` extension point. Declared structurally so the plugin does\n * not take a build dependency on `@objectstack/service-automation`.\n */\ninterface AutomationTriggerRegistry {\n registerTrigger(trigger: FlowTrigger): void;\n unregisterTrigger?(type: string): void;\n}\n\n/**\n * ScheduleTriggerPlugin\n *\n * Makes schedule-triggered flows actually fire. The automation engine ships the\n * `FlowTrigger` wiring (it parses each flow's start node — `flow.type ===\n * 'schedule'` or a start-node `config.schedule` descriptor — into a binding and\n * calls `trigger.start(...)`), but the *concrete* schedule trigger lives here as\n * a plugin and delegates timing to the platform `IJobService` (the `'job'`\n * service). This mirrors the connector / record-change split (engine baseline +\n * trigger plugin).\n *\n * With this plugin (and a job service) installed, a flow whose start node\n * declares `config: { schedule: { type: 'cron', expression: '0 1 * * *' } }`\n * auto-launches on that schedule — no manual `engine.execute()`.\n *\n * Depends on the job service plugin so its `kernel:ready` upgrade (to the\n * durable DbJobAdapter) runs before ours; the job service is nonetheless\n * resolved lazily per `start()` so we always use its current adapter.\n */\nexport class ScheduleTriggerPlugin implements Plugin {\n name = 'com.objectstack.trigger.schedule';\n type = 'standard';\n version = '7.3.0';\n dependencies = ['com.objectstack.service.job'];\n\n async init(ctx: PluginContext): Promise<void> {\n ctx.logger.info('Schedule trigger plugin initialized');\n }\n\n async start(ctx: PluginContext): Promise<void> {\n // The automation service + job service are resolvable once the kernel is\n // ready (kernel:ready fires after AutomationServicePlugin.start() has\n // pulled flows in and after the job service upgrades its adapter).\n ctx.hook('kernel:ready', async () => {\n const automation = this.resolveService<AutomationTriggerRegistry>(ctx, 'automation');\n if (!automation || typeof automation.registerTrigger !== 'function') {\n ctx.logger.warn(\n 'ScheduleTriggerPlugin: automation service not available — schedule trigger NOT installed',\n );\n return;\n }\n\n // Probe once for a clear startup warning; the trigger re-resolves\n // lazily on each start() so adapter upgrades are always picked up.\n if (!this.resolveService<JobServiceSurface>(ctx, 'job')) {\n ctx.logger.warn(\n 'ScheduleTriggerPlugin: job service not available — scheduled flows will not run until one is registered',\n );\n }\n\n const trigger = new ScheduleTrigger(\n () => this.resolveService<JobServiceSurface>(ctx, 'job'),\n ctx.logger,\n );\n automation.registerTrigger(trigger);\n ctx.logger.info('ScheduleTriggerPlugin: schedule trigger registered');\n });\n }\n\n private resolveService<T>(ctx: PluginContext, name: string): T | null {\n try {\n return ctx.getService<T>(name) ?? null;\n } catch {\n return null;\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { AutomationContext, JobSchedule, JobHandler } from '@objectstack/spec/contracts';\nimport {\n TimeRelativeTriggerSchema,\n TIME_RELATIVE_DEFAULT_CRON,\n TIME_RELATIVE_DEFAULT_MAX_RECORDS,\n} from '@objectstack/spec/automation';\nimport type { TimeRelativeTrigger as TimeRelativeDescriptor } from '@objectstack/spec/automation';\nimport { normalizeSchedule, reportBindFailure } from './schedule-trigger.js';\nimport type { FlowTrigger, FlowTriggerBinding, JobServiceSurface, TriggerLogger } from './schedule-trigger.js';\n\n/**\n * The slice of the ObjectQL data engine this trigger needs: run a filtered\n * `find` (to discover the records whose date field falls in the window) and,\n * optionally, probe whether an object is registered. Typed structurally — same\n * decoupling pattern the record-change trigger uses for its hook surface — so\n * this plugin does not take a build dependency on the engine package.\n */\nexport interface TimeRelativeDataEngine {\n find(\n objectName: string,\n query?: {\n where?: Record<string, unknown>;\n fields?: string[];\n limit?: number;\n /** Elevated context — a background sweep must see all rows, not RLS-scoped ones. */\n context?: { isSystem?: boolean };\n },\n ): Promise<Array<Record<string, unknown>> | undefined>;\n /**\n * Optional object-existence probe (the ObjectQL engine's `getObject`).\n * When present, {@link TimeRelativeTrigger.start} uses it to call out a\n * descriptor whose `object` matches no registered object at bind time —\n * otherwise the sweep just quietly finds nothing forever.\n */\n getObject?(name: string): unknown;\n}\n\n/**\n * The slice of the automation service this trigger needs for dispatch\n * idempotency (#10220): claim a dispatch key against the persisted\n * `sys_flow_dispatch` ledger. `true` = this caller owns the dispatch; `false` =\n * an earlier sweep (possibly in a previous process lifetime) already made it.\n * Typed structurally — like {@link TimeRelativeDataEngine} — so this plugin\n * never learns the ledger's table name and takes no build dependency on\n * `@objectstack/service-automation`.\n */\nexport interface FlowDispatchClaimSurface {\n claim(key: string): Promise<boolean>;\n}\n\n/** Job-name namespace so time-relative sweeps never collide with plain schedule jobs. */\nconst JOB_PREFIX = 'flow-time-relative';\n\nconst MS_PER_DAY = 86_400_000;\n\n/**\n * TTL for the trigger's IN-PROCESS claim fallback (#10220): every dispatch key\n * embeds a calendar day, so no key is producible more than ~48h after it was\n * first claimable — pruning at that age keeps the fallback map bounded without\n * ever forgetting a key a sweep could still produce.\n */\nconst LOCAL_CLAIM_TTL_MS = 48 * 60 * 60 * 1000;\n\n/** A closed, inclusive instant window `[gte, lte]` as ISO-8601 strings. */\nexport interface DateWindow {\n /** Lower bound (inclusive), ISO-8601. */\n gte: string;\n /** Upper bound (inclusive), ISO-8601. */\n lte: string;\n}\n\n// ─── Pure window math (day-granular, UTC) ───────────────────────────\n\n/** Start of `d`'s UTC calendar day (00:00:00.000Z). */\nfunction startOfUtcDay(d: Date): Date {\n return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), 0, 0, 0, 0));\n}\n\n/** End of `d`'s UTC calendar day (23:59:59.999Z) — inclusive upper bound. */\nfunction endOfUtcDay(d: Date): Date {\n return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), 23, 59, 59, 999));\n}\n\n/** `d`'s UTC day shifted by `n` whole days (exact in UTC — no DST drift). */\nfunction addUtcDays(d: Date, n: number): Date {\n return new Date(startOfUtcDay(d).getTime() + n * MS_PER_DAY);\n}\n\n/**\n * Compute the inclusive date window(s) a descriptor selects, relative to `now`.\n *\n * - `offsetDays` → one single-day window per offset (`today + offset`), so the\n * sweep fires exactly on each threshold day (the robust T-minus reminder).\n * - `withinDays` → one range window: `[today, today + N]` when N ≥ 0 (upcoming),\n * or `[today − |N|, today]` when N < 0 (overdue lookback). Always includes today.\n *\n * Day-granular and computed in UTC. The upper bound is the *end* of its day\n * (`23:59:59.999Z`), so a `datetime` field matches for the whole day and a\n * `date` field (compared as `YYYY-MM-DD` after the driver truncates) is inclusive.\n */\nexport function computeDateWindows(desc: TimeRelativeDescriptor, now: Date): DateWindow[] {\n return computeWindowClaimScopes(desc, now).map((s) => s.window);\n}\n\n/**\n * A date window paired with the **claim scope** naming its identity for the\n * dispatch dedup key (#10220, maintainer ruling 2026-08-20).\n */\nexport interface WindowClaimScope {\n window: DateWindow;\n /**\n * Window-identity fragment of the dispatch key — what makes a re-scan of\n * the SAME window dedup while a genuinely new window fires again:\n *\n * - offset mode → `<windowDay>:offset<n>`: the window day is the date the\n * record's field must fall on, so editing the field to a new day (or a\n * different offset matching) yields a new key and legitimately re-fires.\n * Re-scans of one window all derive the same day → deduped.\n * - range mode → `<sweepDay>:within<n>`: keyed on the SWEEP day, not the\n * (constant) field value, so the documented `withinDays` semantic —\n * \"fires every day the record stays in range\" — remains true: each new\n * day is a new key, but never twice in one day.\n */\n scope: string;\n}\n\n/**\n * {@link computeDateWindows}, with each window's claim scope (#10220). One\n * derivation for both so the matching rule and the dedup key can never drift.\n */\nexport function computeWindowClaimScopes(desc: TimeRelativeDescriptor, now: Date): WindowClaimScope[] {\n const today = startOfUtcDay(now);\n\n if (desc.offsetDays && desc.offsetDays.length > 0) {\n return desc.offsetDays.map((offset) => {\n const day = addUtcDays(today, offset);\n const window = { gte: startOfUtcDay(day).toISOString(), lte: endOfUtcDay(day).toISOString() };\n return { window, scope: `${window.gte.slice(0, 10)}:offset${offset}` };\n });\n }\n\n const n = desc.withinDays ?? 0;\n const sweepDay = today.toISOString().slice(0, 10);\n const window: DateWindow =\n n >= 0\n ? { gte: startOfUtcDay(today).toISOString(), lte: endOfUtcDay(addUtcDays(today, n)).toISOString() }\n // Negative: window extends into the past, still anchored to (and including) today.\n : { gte: startOfUtcDay(addUtcDays(today, n)).toISOString(), lte: endOfUtcDay(today).toISOString() };\n return [{ window, scope: `${sweepDay}:within${n}` }];\n}\n\n/**\n * Build the ObjectQL `where` map for one date window: the descriptor's static\n * `filter` (if any) ANDed with a `$gte`/`$lte` range on the date field. The map\n * form is the canonical filter shape both drivers evaluate verbatim (the same\n * shape the platform's own retention sweep uses).\n */\nexport function buildWindowWhere(desc: TimeRelativeDescriptor, window: DateWindow): Record<string, unknown> {\n return {\n ...(desc.filter ?? {}),\n [desc.dateField]: { $gte: window.gte, $lte: window.lte },\n };\n}\n\nfunction errMessage(err: unknown): string {\n return (err as Error)?.message ?? String(err);\n}\n\n/**\n * TimeRelativeTrigger\n *\n * The declarative answer to \"act on records whose date field is coming up (or\n * overdue)\" (#1874). Instead of the fragile date-equality-on-record-change\n * pattern (which only fires if the record happens to be edited on the threshold\n * day) or a hand-rolled cron + range query per flow, a flow whose start node\n * declares `config.timeRelative` is swept on a schedule (daily by default) and\n * launched **once per matching record**.\n *\n * It composes the schedule trigger's two collaborators:\n * - the platform {@link JobServiceSurface} owns the sweep cadence (like the\n * plain schedule trigger), and\n * - the {@link TimeRelativeDataEngine} runs the date-window query (like the\n * record-change trigger reaching ObjectQL).\n *\n * Both are resolved lazily (per call) so adapter upgrades — the durable job\n * adapter that replaces the bootstrap ticker on `kernel:ready`, a late-registered\n * data engine — are always picked up. The engine owns the start-node `condition`\n * gate and `runAs` identity, so this trigger only has to put the matched record\n * on the {@link AutomationContext}; `{record.<field>}` interpolation and the\n * condition work exactly as they do for a record-change flow.\n */\nexport class TimeRelativeTrigger implements FlowTrigger {\n readonly type = 'time_relative';\n\n private readonly getJobService: () => JobServiceSurface | null;\n private readonly getDataEngine: () => TimeRelativeDataEngine | null;\n private readonly logger: TriggerLogger;\n /** Injectable clock so window math is deterministic under test. */\n private readonly now: () => Date;\n /** flowName → job name registered for it, so stop() can cancel it. */\n private readonly bound = new Map<string, string>();\n /** Dispatch-idempotency claim surface (#10220), resolved lazily per sweep. */\n private readonly getClaimSurface: () => FlowDispatchClaimSurface | null;\n /**\n * In-process claim fallback when no claim surface resolves (#10220):\n * key → claim time (epoch ms), TTL-pruned. Dedups re-scans within THIS\n * process only — which is why falling to it is warned once, below.\n */\n private readonly localClaims = new Map<string, number>();\n /** Whether the in-process-only dedup degradation has been said (once). */\n private claimDegradationWarned = false;\n\n constructor(\n getJobService: () => JobServiceSurface | null,\n getDataEngine: () => TimeRelativeDataEngine | null,\n logger: TriggerLogger,\n now: () => Date = () => new Date(),\n getClaimSurface: () => FlowDispatchClaimSurface | null = () => null,\n ) {\n this.getJobService = getJobService;\n this.getDataEngine = getDataEngine;\n this.logger = logger;\n this.now = now;\n this.getClaimSurface = getClaimSurface;\n }\n\n start(binding: FlowTriggerBinding, callback: (ctx: AutomationContext) => Promise<void>): void {\n const raw = (binding.config as Record<string, unknown> | undefined)?.timeRelative;\n const parsed = TimeRelativeTriggerSchema.safeParse(raw);\n if (!parsed.success) {\n this.logger.warn(\n `[time-relative] flow '${binding.flowName}' has no valid \\`timeRelative\\` descriptor — not bound. ` +\n `Provide { object, dateField, and exactly one of withinDays | offsetDays }. ` +\n `(${parsed.error.issues.map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`).join('; ')})`,\n );\n return;\n }\n const desc = parsed.data;\n\n // Cadence: the flow's start-node schedule descriptor, or a daily default.\n // A daily sweep is the whole point (evaluate the window every day so a\n // threshold day is never missed), so an omitted schedule means \"daily\",\n // not \"never\".\n const schedule: JobSchedule =\n normalizeSchedule(binding.schedule) ?? { type: 'cron', expression: TIME_RELATIVE_DEFAULT_CRON };\n\n const jobService = this.getJobService();\n if (!jobService || typeof jobService.schedule !== 'function') {\n this.logger.warn(\n `[time-relative] job service unavailable — flow '${binding.flowName}' not scheduled`,\n );\n return;\n }\n\n // Best-effort object-existence probe at bind time (the engine may be\n // available now even though the sweep resolves it lazily). A descriptor\n // targeting an unknown object would sweep forever finding nothing.\n const engineNow = this.getDataEngine();\n if (desc.object && engineNow && typeof engineNow.getObject === 'function') {\n let known: unknown;\n try {\n known = engineNow.getObject(desc.object);\n } catch {\n known = undefined;\n }\n if (!known) {\n this.logger.warn(\n `[time-relative] flow '${binding.flowName}' targets unknown object '${desc.object}' — the sweep is bound but will match nothing until that object is registered. ` +\n `Object names match exactly; check config.timeRelative.object.`,\n );\n }\n }\n\n // Idempotent: drop any prior schedule for this flow before re-binding\n // (covers disable→enable cycles and hot reload).\n this.stop(binding.flowName);\n\n const jobName = `${JOB_PREFIX}:${binding.flowName}`;\n const maxRecords = desc.maxRecords ?? TIME_RELATIVE_DEFAULT_MAX_RECORDS;\n\n const handler: JobHandler = async () => {\n try {\n await this.sweep(binding.flowName, desc, maxRecords, callback);\n } catch (err) {\n // Error isolation: a sweep failure must not crash the job\n // runner / ticker. Log and swallow.\n this.logger.warn(\n `[time-relative] flow '${binding.flowName}' sweep failed: ${errMessage(err)}`,\n );\n }\n };\n\n this.bound.set(binding.flowName, jobName);\n // FlowTrigger.start is sync; the job service's schedule() is async.\n // Fire-and-forget with error logging (mirrors ScheduleTrigger).\n void Promise.resolve(jobService.schedule(jobName, schedule, handler))\n .then(() => {\n const mode = desc.offsetDays\n ? `offsets [${desc.offsetDays.join(', ')}]d`\n : `within ${desc.withinDays}d`;\n this.logger.info(\n `[time-relative] bound flow '${binding.flowName}' → sweep '${desc.object}.${desc.dateField}' ${mode} on ${schedule.type}` +\n (schedule.expression ? ` '${schedule.expression}'` : '') +\n (schedule.intervalMs ? ` every ${schedule.intervalMs}ms` : ''),\n );\n })\n .catch((err) => {\n this.bound.delete(binding.flowName);\n reportBindFailure(this.logger, 'time-relative', binding.flowName, err);\n });\n }\n\n /**\n * Run one sweep: query each date window, union the matched records (deduped\n * by id, capped at `maxRecords`), and launch the flow once per record. A\n * per-record failure is isolated so one bad row never aborts the batch.\n */\n private async sweep(\n flowName: string,\n desc: TimeRelativeDescriptor,\n maxRecords: number,\n callback: (ctx: AutomationContext) => Promise<void>,\n ): Promise<void> {\n const engine = this.getDataEngine();\n if (!engine || typeof engine.find !== 'function') {\n this.logger.warn(\n `[time-relative] data engine unavailable — flow '${flowName}' sweep skipped this tick`,\n );\n return;\n }\n\n const scopes = computeWindowClaimScopes(desc, this.now());\n const seenIds = new Set<unknown>();\n const matched: Array<{ record: Record<string, unknown>; claimKey: string | null }> = [];\n\n for (const { window, scope } of scopes) {\n if (matched.length >= maxRecords) break;\n const where = buildWindowWhere(desc, window);\n const rows =\n (await engine.find(desc.object, {\n where,\n limit: maxRecords,\n context: { isSystem: true },\n })) ?? [];\n for (const row of rows) {\n const id = (row as { id?: unknown }).id;\n // Dedup across windows (offset mode) by id; rows without an id\n // are always kept (can't dedup, better than dropping).\n if (id != null) {\n if (seenIds.has(id)) continue;\n seenIds.add(id);\n }\n // #10220 — dispatch key: the MATCHED WINDOW's identity + the\n // record. A row without an id can't be keyed; it is dispatched\n // unconditionally, exactly as it was never dedupable before.\n const claimKey = id != null ? `time-relative:${flowName}:${scope}:${String(id)}` : null;\n matched.push({ record: row, claimKey });\n if (matched.length >= maxRecords) break;\n }\n }\n\n if (matched.length >= maxRecords) {\n this.logger.warn(\n `[time-relative] flow '${flowName}' sweep hit the ${maxRecords}-record cap — some matching records were NOT processed this tick. ` +\n `Narrow the window/filter, or raise config.timeRelative.maxRecords.`,\n );\n }\n\n let launched = 0;\n let failed = 0;\n let deduped = 0;\n for (const { record, claimKey } of matched) {\n // #10220 — idempotency gate: launch only if this (flow, record,\n // window) key has not been dispatched before. A re-scan of the same\n // window (denser schedule, kernel rebuild + persisted ledger,\n // future catch-up sweep) skips instead of re-minting.\n if (claimKey != null && !(await this.claimDispatch(flowName, claimKey))) {\n deduped++;\n continue;\n }\n try {\n const ctx: AutomationContext = {\n record,\n object: desc.object,\n event: 'time_relative',\n // Expose the record as params too, so flows with named `isInput`\n // variables matching record fields get them seeded (parity with\n // the record-change trigger).\n params: record,\n };\n await callback(ctx);\n launched++;\n } catch (err) {\n failed++;\n // Error isolation per record: one failing flow run must not stop\n // the sweep. ERROR when available (stderr survives the CLI's\n // boot-quiet stdout window), else warn.\n const log = this.logger.error?.bind(this.logger) ?? this.logger.warn.bind(this.logger);\n log(\n `[time-relative] flow '${flowName}' failed for record '${String((record as { id?: unknown }).id ?? '?')}': ${errMessage(err)}`,\n );\n }\n }\n\n this.logger.debug?.(\n `[time-relative] flow '${flowName}' swept '${desc.object}': ${matched.length} matched, ${launched} launched, ${deduped} already dispatched, ${failed} failed`,\n );\n }\n\n /**\n * Claim one dispatch key (#10220): `true` = launch, `false` = an earlier\n * sweep already dispatched this (flow, record, window).\n *\n * Degradation contract:\n * - Claim surface resolves (the automation service's `claim()`, backed by\n * the persisted `sys_flow_dispatch` ledger) → its answer is used; if the\n * CALL throws, the failure is logged and the dispatch proceeds —\n * availability over strict-once: a broken ledger must never silently\n * swallow reminders.\n * - No claim surface (automation service missing, or one predating\n * `claim()`) → in-process dedup only, warned ONCE: a silent fallback\n * would hide that the once-per-window guarantee no longer survives a\n * kernel rebuild.\n */\n private async claimDispatch(flowName: string, key: string): Promise<boolean> {\n const surface = this.getClaimSurface();\n if (surface && typeof surface.claim === 'function') {\n try {\n return await surface.claim(key);\n } catch (err) {\n this.logger.warn(\n `[time-relative] flow '${flowName}' dispatch-claim failed for key '${key}' — dispatching anyway ` +\n `(availability over strict-once; the same window may re-fire until the claim store recovers): ${errMessage(err)}`,\n );\n return true;\n }\n }\n if (!this.claimDegradationWarned) {\n this.claimDegradationWarned = true;\n this.logger.warn(\n `[time-relative] no dispatch-claim surface (automation service missing or without claim()) — ` +\n `sweep dedup is IN-PROCESS ONLY and will NOT survive a kernel rebuild: ` +\n `the same record/window can re-fire after a restart.`,\n );\n }\n const now = this.now().getTime();\n const cutoff = now - LOCAL_CLAIM_TTL_MS;\n for (const [k, t] of this.localClaims) {\n if (t < cutoff) this.localClaims.delete(k);\n }\n if (this.localClaims.has(key)) return false;\n this.localClaims.set(key, now);\n return true;\n }\n\n stop(flowName: string): void {\n const jobName = this.bound.get(flowName);\n if (!jobName) return;\n this.bound.delete(flowName);\n const jobService = this.getJobService();\n if (!jobService || typeof jobService.cancel !== 'function') return;\n void Promise.resolve(jobService.cancel(jobName))\n .then(() => this.logger.debug?.(`[time-relative] unbound flow '${flowName}'`))\n .catch((err) => {\n this.logger.warn(\n `[time-relative] failed to unbind flow '${flowName}': ${errMessage(err)}`,\n );\n });\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { TimeRelativeTrigger } from './time-relative-trigger.js';\nimport type { FlowDispatchClaimSurface, TimeRelativeDataEngine } from './time-relative-trigger.js';\nimport type { FlowTrigger, JobServiceSurface } from './schedule-trigger.js';\n\n/**\n * The slice of the automation engine this plugin needs: register a trigger on\n * its `FlowTrigger` extension point. Declared structurally so the plugin does\n * not take a build dependency on `@objectstack/service-automation`.\n */\ninterface AutomationTriggerRegistry {\n registerTrigger(trigger: FlowTrigger): void;\n unregisterTrigger?(type: string): void;\n}\n\n/**\n * TimeRelativeTriggerPlugin\n *\n * Arms **declarative time-relative flows** (#1874): a flow whose start node\n * declares `config.timeRelative` (object + dateField + `withinDays`/`offsetDays`)\n * is swept on a schedule and launched once per record whose date field falls in\n * the window — no hand-written cron + range query, no fragile\n * date-equality-on-record-change.\n *\n * It ships in `@objectstack/trigger-schedule` alongside the plain schedule\n * trigger (both are schedule-driven) but is a **separate** plugin: the\n * time-relative trigger additionally needs the ObjectQL engine (for the sweep\n * query), so keeping it separate leaves the plain `ScheduleTriggerPlugin`'s\n * dependency surface unchanged. Depends on the job service (sweep cadence) and\n * the ObjectQL engine (record discovery); both are resolved lazily per `start()`\n * so adapter upgrades are always picked up.\n */\nexport class TimeRelativeTriggerPlugin implements Plugin {\n name = 'com.objectstack.trigger.time-relative';\n type = 'standard';\n version = '1.0.0';\n dependencies = ['com.objectstack.service.job', 'com.objectstack.engine.objectql'];\n\n async init(ctx: PluginContext): Promise<void> {\n ctx.logger.info('Time-relative trigger plugin initialized');\n }\n\n async start(ctx: PluginContext): Promise<void> {\n // The automation service, job service, and ObjectQL engine are all\n // resolvable once the kernel is ready (kernel:ready fires after\n // AutomationServicePlugin.start() has pulled flows in and after the job\n // service upgrades its adapter).\n ctx.hook('kernel:ready', async () => {\n const automation = this.resolveService<AutomationTriggerRegistry>(ctx, 'automation');\n if (!automation || typeof automation.registerTrigger !== 'function') {\n ctx.logger.warn(\n 'TimeRelativeTriggerPlugin: automation service not available — time-relative trigger NOT installed',\n );\n return;\n }\n\n // Probe once for a clear startup warning; the trigger re-resolves\n // both collaborators lazily on each start()/sweep so late upgrades\n // are always picked up.\n if (!this.resolveService<JobServiceSurface>(ctx, 'job')) {\n ctx.logger.warn(\n 'TimeRelativeTriggerPlugin: job service not available — time-relative sweeps will not run until one is registered',\n );\n }\n if (!this.resolveDataEngine(ctx)) {\n ctx.logger.warn(\n 'TimeRelativeTriggerPlugin: ObjectQL engine not available — time-relative sweeps will find no records until it is',\n );\n }\n\n const trigger = new TimeRelativeTrigger(\n () => this.resolveService<JobServiceSurface>(ctx, 'job'),\n () => this.resolveDataEngine(ctx),\n ctx.logger,\n undefined, // default wall clock\n // #10220 — dispatch-idempotency claims go through the SAME\n // automation service this plugin already resolves; the trigger\n // computes the key and never learns the ledger's table name. An\n // automation service predating claim() resolves to null and the\n // trigger degrades (honestly, warned once) to in-process dedup.\n () => {\n const svc = this.resolveService<Partial<FlowDispatchClaimSurface>>(ctx, 'automation');\n return svc && typeof svc.claim === 'function' ? (svc as FlowDispatchClaimSurface) : null;\n },\n );\n automation.registerTrigger(trigger);\n ctx.logger.info('TimeRelativeTriggerPlugin: time-relative trigger registered');\n });\n }\n\n private resolveService<T>(ctx: PluginContext, name: string): T | null {\n try {\n return ctx.getService<T>(name) ?? null;\n } catch {\n return null;\n }\n }\n\n private resolveDataEngine(ctx: PluginContext): TimeRelativeDataEngine | null {\n // Primary alias 'objectql', fallback 'data' (some kernels register the\n // engine under both) — same lookup the record-change trigger uses.\n return (\n this.resolveService<TimeRelativeDataEngine>(ctx, 'objectql') ??\n this.resolveService<TimeRelativeDataEngine>(ctx, 'data')\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC0DA,IAAM,aAAa;AAuBZ,SAAS,kBACZ,QACA,KACA,UACA,KACI;AACJ,QAAM,SAAS,OAAO,OAAO,KAAK,MAAM,KAAK,OAAO,KAAK,KAAK,MAAM;AACpE;AAAA,IACI,IAAI,GAAG,WAAW,QAAQ,wCAAyC,KAAe,WAAW,OAAO,GAAG,CAAC;AAAA,EAG5G;AACJ;AASO,SAAS,kBAAkB,KAAkC;AAChE,MAAI,OAAO,KAAM,QAAO;AAGxB,MAAI,OAAO,QAAQ,UAAU;AACzB,UAAM,OAAO,IAAI,KAAK;AACtB,WAAO,OAAO,EAAE,MAAM,QAAQ,YAAY,KAAK,IAAI;AAAA,EACvD;AAEA,MAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,QAAM,IAAI;AAEV,QAAM,OAAO,OAAO,EAAE,SAAS,WAAW,EAAE,OAAO;AAEnD,MAAI,SAAS,UAAW,CAAC,SAAS,OAAO,EAAE,SAAS,YAAY,OAAO,EAAE,eAAe,WAAY;AAChG,UAAM,aACD,OAAO,EAAE,eAAe,YAAY,EAAE,cACtC,OAAO,EAAE,SAAS,YAAY,EAAE,QACjC;AACJ,QAAI,CAAC,WAAY,QAAO;AACxB,UAAM,MAAmB,EAAE,MAAM,QAAQ,WAAW;AACpD,QAAI,OAAO,EAAE,aAAa,SAAU,KAAI,WAAW,EAAE;AACrD,WAAO;AAAA,EACX;AAEA,MAAI,SAAS,cAAe,CAAC,SAAS,OAAO,EAAE,eAAe,YAAY,OAAO,EAAE,UAAU,WAAY;AACrG,UAAM,aACD,OAAO,EAAE,eAAe,YAAY,EAAE,cACtC,OAAO,EAAE,UAAU,YAAY,EAAE,SAClC;AACJ,QAAI,CAAC,cAAc,cAAc,EAAG,QAAO;AAC3C,WAAO,EAAE,MAAM,YAAY,WAAW;AAAA,EAC1C;AAEA,MAAI,SAAS,UAAW,CAAC,QAAQ,OAAO,EAAE,OAAO,UAAW;AACxD,UAAM,KAAK,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC7C,QAAI,CAAC,GAAI,QAAO;AAChB,WAAO,EAAE,MAAM,QAAQ,GAAG;AAAA,EAC9B;AAEA,SAAO;AACX;AAgBO,IAAM,kBAAN,MAA6C;AAAA,EAQhD,YAAY,eAA+C,QAAuB;AAPlF,SAAS,OAAO;AAKhB;AAAA,SAAiB,QAAQ,oBAAI,IAAoB;AAG7C,SAAK,gBAAgB;AACrB,SAAK,SAAS;AAAA,EAClB;AAAA,EAEA,MAAM,SAA6B,UAA2D;AAC1F,UAAM,MAAM,QAAQ,YAAa,QAAQ,QAAgD;AACzF,UAAM,WAAW,kBAAkB,GAAG;AACtC,QAAI,CAAC,UAAU;AACX,WAAK,OAAO;AAAA,QACR,oBAAoB,QAAQ,QAAQ;AAAA,MACxC;AACA;AAAA,IACJ;AAEA,UAAM,aAAa,KAAK,cAAc;AACtC,QAAI,CAAC,cAAc,OAAO,WAAW,aAAa,YAAY;AAC1D,WAAK,OAAO;AAAA,QACR,mDAA8C,QAAQ,QAAQ;AAAA,MAClE;AACA;AAAA,IACJ;AAIA,SAAK,KAAK,QAAQ,QAAQ;AAE1B,UAAM,UAAU,GAAG,UAAU,IAAI,QAAQ,QAAQ;AAEjD,UAAM,UAAsB,OAAO,EAAE,MAAM,MAAM;AAC7C,UAAI;AACA,cAAM,MAAyB;AAAA,UAC3B,OAAO;AAAA,UACP,QAAQ;AAAA,YACJ;AAAA,YACA,UAAU,QAAQ;AAAA,YAClB;AAAA,UACJ;AAAA,QACJ;AACA,cAAM,SAAS,GAAG;AAAA,MACtB,SAAS,KAAK;AAGV,aAAK,OAAO;AAAA,UACR,oBAAoB,QAAQ,QAAQ,uBAAwB,KAAe,WAAW,OAAO,GAAG,CAAC;AAAA,QACrG;AAAA,MACJ;AAAA,IACJ;AAEA,SAAK,MAAM,IAAI,QAAQ,UAAU,OAAO;AAGxC,SAAK,QAAQ,QAAQ,WAAW,SAAS,SAAS,UAAU,OAAO,CAAC,EAC/D,KAAK,MAAM;AACR,WAAK,OAAO;AAAA,QACR,0BAA0B,QAAQ,QAAQ,YAAO,SAAS,IAAI,MACzD,SAAS,aAAa,KAAK,SAAS,UAAU,MAAM,OACpD,SAAS,aAAa,UAAU,SAAS,UAAU,OAAO,OAC1D,SAAS,KAAK,OAAO,SAAS,EAAE,KAAK;AAAA,MAC9C;AAAA,IACJ,CAAC,EACA,MAAM,CAAC,QAAQ;AACZ,WAAK,MAAM,OAAO,QAAQ,QAAQ;AAClC,wBAAkB,KAAK,QAAQ,YAAY,QAAQ,UAAU,GAAG;AAAA,IACpE,CAAC;AAAA,EACT;AAAA,EAEA,KAAK,UAAwB;AACzB,UAAM,UAAU,KAAK,MAAM,IAAI,QAAQ;AACvC,QAAI,CAAC,QAAS;AACd,SAAK,MAAM,OAAO,QAAQ;AAC1B,UAAM,aAAa,KAAK,cAAc;AACtC,QAAI,CAAC,cAAc,OAAO,WAAW,WAAW,WAAY;AAC5D,SAAK,QAAQ,QAAQ,WAAW,OAAO,OAAO,CAAC,EAC1C,KAAK,MAAM,KAAK,OAAO,QAAQ,4BAA4B,QAAQ,GAAG,CAAC,EACvE,MAAM,CAAC,QAAQ;AACZ,WAAK,OAAO;AAAA,QACR,qCAAqC,QAAQ,MAAO,KAAe,WAAW,OAAO,GAAG,CAAC;AAAA,MAC7F;AAAA,IACJ,CAAC;AAAA,EACT;AACJ;;;ACrNO,IAAM,wBAAN,MAA8C;AAAA,EAA9C;AACH,gBAAO;AACP,gBAAO;AACP,mBAAU;AACV,wBAAe,CAAC,6BAA6B;AAAA;AAAA,EAE7C,MAAM,KAAK,KAAmC;AAC1C,QAAI,OAAO,KAAK,qCAAqC;AAAA,EACzD;AAAA,EAEA,MAAM,MAAM,KAAmC;AAI3C,QAAI,KAAK,gBAAgB,YAAY;AACjC,YAAM,aAAa,KAAK,eAA0C,KAAK,YAAY;AACnF,UAAI,CAAC,cAAc,OAAO,WAAW,oBAAoB,YAAY;AACjE,YAAI,OAAO;AAAA,UACP;AAAA,QACJ;AACA;AAAA,MACJ;AAIA,UAAI,CAAC,KAAK,eAAkC,KAAK,KAAK,GAAG;AACrD,YAAI,OAAO;AAAA,UACP;AAAA,QACJ;AAAA,MACJ;AAEA,YAAM,UAAU,IAAI;AAAA,QAChB,MAAM,KAAK,eAAkC,KAAK,KAAK;AAAA,QACvD,IAAI;AAAA,MACR;AACA,iBAAW,gBAAgB,OAAO;AAClC,UAAI,OAAO,KAAK,oDAAoD;AAAA,IACxE,CAAC;AAAA,EACL;AAAA,EAEQ,eAAkB,KAAoB,MAAwB;AAClE,QAAI;AACA,aAAO,IAAI,WAAc,IAAI,KAAK;AAAA,IACtC,QAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AACJ;;;AC/EA,wBAIO;AA8CP,IAAMA,cAAa;AAEnB,IAAM,aAAa;AAQnB,IAAM,qBAAqB,KAAK,KAAK,KAAK;AAa1C,SAAS,cAAc,GAAe;AAClC,SAAO,IAAI,KAAK,KAAK,IAAI,EAAE,eAAe,GAAG,EAAE,YAAY,GAAG,EAAE,WAAW,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAC7F;AAGA,SAAS,YAAY,GAAe;AAChC,SAAO,IAAI,KAAK,KAAK,IAAI,EAAE,eAAe,GAAG,EAAE,YAAY,GAAG,EAAE,WAAW,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC;AAClG;AAGA,SAAS,WAAW,GAAS,GAAiB;AAC1C,SAAO,IAAI,KAAK,cAAc,CAAC,EAAE,QAAQ,IAAI,IAAI,UAAU;AAC/D;AAcO,SAAS,mBAAmB,MAA8B,KAAyB;AACtF,SAAO,yBAAyB,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM;AAClE;AA4BO,SAAS,yBAAyB,MAA8B,KAA+B;AAClG,QAAM,QAAQ,cAAc,GAAG;AAE/B,MAAI,KAAK,cAAc,KAAK,WAAW,SAAS,GAAG;AAC/C,WAAO,KAAK,WAAW,IAAI,CAAC,WAAW;AACnC,YAAM,MAAM,WAAW,OAAO,MAAM;AACpC,YAAMC,UAAS,EAAE,KAAK,cAAc,GAAG,EAAE,YAAY,GAAG,KAAK,YAAY,GAAG,EAAE,YAAY,EAAE;AAC5F,aAAO,EAAE,QAAAA,SAAQ,OAAO,GAAGA,QAAO,IAAI,MAAM,GAAG,EAAE,CAAC,UAAU,MAAM,GAAG;AAAA,IACzE,CAAC;AAAA,EACL;AAEA,QAAM,IAAI,KAAK,cAAc;AAC7B,QAAM,WAAW,MAAM,YAAY,EAAE,MAAM,GAAG,EAAE;AAChD,QAAM,SACF,KAAK,IACC,EAAE,KAAK,cAAc,KAAK,EAAE,YAAY,GAAG,KAAK,YAAY,WAAW,OAAO,CAAC,CAAC,EAAE,YAAY,EAAE,IAEhG,EAAE,KAAK,cAAc,WAAW,OAAO,CAAC,CAAC,EAAE,YAAY,GAAG,KAAK,YAAY,KAAK,EAAE,YAAY,EAAE;AAC1G,SAAO,CAAC,EAAE,QAAQ,OAAO,GAAG,QAAQ,UAAU,CAAC,GAAG,CAAC;AACvD;AAQO,SAAS,iBAAiB,MAA8B,QAA6C;AACxG,SAAO;AAAA,IACH,GAAI,KAAK,UAAU,CAAC;AAAA,IACpB,CAAC,KAAK,SAAS,GAAG,EAAE,MAAM,OAAO,KAAK,MAAM,OAAO,IAAI;AAAA,EAC3D;AACJ;AAEA,SAAS,WAAW,KAAsB;AACtC,SAAQ,KAAe,WAAW,OAAO,GAAG;AAChD;AAyBO,IAAM,sBAAN,MAAiD;AAAA,EAqBpD,YACI,eACA,eACA,QACA,MAAkB,MAAM,oBAAI,KAAK,GACjC,kBAAyD,MAAM,MACjE;AA1BF,SAAS,OAAO;AAQhB;AAAA,SAAiB,QAAQ,oBAAI,IAAoB;AAQjD;AAAA;AAAA;AAAA;AAAA;AAAA,SAAiB,cAAc,oBAAI,IAAoB;AAEvD;AAAA,SAAQ,yBAAyB;AAS7B,SAAK,gBAAgB;AACrB,SAAK,gBAAgB;AACrB,SAAK,SAAS;AACd,SAAK,MAAM;AACX,SAAK,kBAAkB;AAAA,EAC3B;AAAA,EAEA,MAAM,SAA6B,UAA2D;AAC1F,UAAM,MAAO,QAAQ,QAAgD;AACrE,UAAM,SAAS,4CAA0B,UAAU,GAAG;AACtD,QAAI,CAAC,OAAO,SAAS;AACjB,WAAK,OAAO;AAAA,QACR,yBAAyB,QAAQ,QAAQ,4IAEjC,OAAO,MAAM,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,KAAK,GAAG,KAAK,QAAQ,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,MACtG;AACA;AAAA,IACJ;AACA,UAAM,OAAO,OAAO;AAMpB,UAAM,WACF,kBAAkB,QAAQ,QAAQ,KAAK,EAAE,MAAM,QAAQ,YAAY,6CAA2B;AAElG,UAAM,aAAa,KAAK,cAAc;AACtC,QAAI,CAAC,cAAc,OAAO,WAAW,aAAa,YAAY;AAC1D,WAAK,OAAO;AAAA,QACR,wDAAmD,QAAQ,QAAQ;AAAA,MACvE;AACA;AAAA,IACJ;AAKA,UAAM,YAAY,KAAK,cAAc;AACrC,QAAI,KAAK,UAAU,aAAa,OAAO,UAAU,cAAc,YAAY;AACvE,UAAI;AACJ,UAAI;AACA,gBAAQ,UAAU,UAAU,KAAK,MAAM;AAAA,MAC3C,QAAQ;AACJ,gBAAQ;AAAA,MACZ;AACA,UAAI,CAAC,OAAO;AACR,aAAK,OAAO;AAAA,UACR,yBAAyB,QAAQ,QAAQ,6BAA6B,KAAK,MAAM;AAAA,QAErF;AAAA,MACJ;AAAA,IACJ;AAIA,SAAK,KAAK,QAAQ,QAAQ;AAE1B,UAAM,UAAU,GAAGD,WAAU,IAAI,QAAQ,QAAQ;AACjD,UAAM,aAAa,KAAK,cAAc;AAEtC,UAAM,UAAsB,YAAY;AACpC,UAAI;AACA,cAAM,KAAK,MAAM,QAAQ,UAAU,MAAM,YAAY,QAAQ;AAAA,MACjE,SAAS,KAAK;AAGV,aAAK,OAAO;AAAA,UACR,yBAAyB,QAAQ,QAAQ,mBAAmB,WAAW,GAAG,CAAC;AAAA,QAC/E;AAAA,MACJ;AAAA,IACJ;AAEA,SAAK,MAAM,IAAI,QAAQ,UAAU,OAAO;AAGxC,SAAK,QAAQ,QAAQ,WAAW,SAAS,SAAS,UAAU,OAAO,CAAC,EAC/D,KAAK,MAAM;AACR,YAAM,OAAO,KAAK,aACZ,YAAY,KAAK,WAAW,KAAK,IAAI,CAAC,OACtC,UAAU,KAAK,UAAU;AAC/B,WAAK,OAAO;AAAA,QACR,+BAA+B,QAAQ,QAAQ,mBAAc,KAAK,MAAM,IAAI,KAAK,SAAS,KAAK,IAAI,OAAO,SAAS,IAAI,MAClH,SAAS,aAAa,KAAK,SAAS,UAAU,MAAM,OACpD,SAAS,aAAa,UAAU,SAAS,UAAU,OAAO;AAAA,MACnE;AAAA,IACJ,CAAC,EACA,MAAM,CAAC,QAAQ;AACZ,WAAK,MAAM,OAAO,QAAQ,QAAQ;AAClC,wBAAkB,KAAK,QAAQ,iBAAiB,QAAQ,UAAU,GAAG;AAAA,IACzE,CAAC;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,MACV,UACA,MACA,YACA,UACa;AACb,UAAM,SAAS,KAAK,cAAc;AAClC,QAAI,CAAC,UAAU,OAAO,OAAO,SAAS,YAAY;AAC9C,WAAK,OAAO;AAAA,QACR,wDAAmD,QAAQ;AAAA,MAC/D;AACA;AAAA,IACJ;AAEA,UAAM,SAAS,yBAAyB,MAAM,KAAK,IAAI,CAAC;AACxD,UAAM,UAAU,oBAAI,IAAa;AACjC,UAAM,UAA+E,CAAC;AAEtF,eAAW,EAAE,QAAQ,MAAM,KAAK,QAAQ;AACpC,UAAI,QAAQ,UAAU,WAAY;AAClC,YAAM,QAAQ,iBAAiB,MAAM,MAAM;AAC3C,YAAM,OACD,MAAM,OAAO,KAAK,KAAK,QAAQ;AAAA,QAC5B;AAAA,QACA,OAAO;AAAA,QACP,SAAS,EAAE,UAAU,KAAK;AAAA,MAC9B,CAAC,KAAM,CAAC;AACZ,iBAAW,OAAO,MAAM;AACpB,cAAM,KAAM,IAAyB;AAGrC,YAAI,MAAM,MAAM;AACZ,cAAI,QAAQ,IAAI,EAAE,EAAG;AACrB,kBAAQ,IAAI,EAAE;AAAA,QAClB;AAIA,cAAM,WAAW,MAAM,OAAO,iBAAiB,QAAQ,IAAI,KAAK,IAAI,OAAO,EAAE,CAAC,KAAK;AACnF,gBAAQ,KAAK,EAAE,QAAQ,KAAK,SAAS,CAAC;AACtC,YAAI,QAAQ,UAAU,WAAY;AAAA,MACtC;AAAA,IACJ;AAEA,QAAI,QAAQ,UAAU,YAAY;AAC9B,WAAK,OAAO;AAAA,QACR,yBAAyB,QAAQ,mBAAmB,UAAU;AAAA,MAElE;AAAA,IACJ;AAEA,QAAI,WAAW;AACf,QAAI,SAAS;AACb,QAAI,UAAU;AACd,eAAW,EAAE,QAAQ,SAAS,KAAK,SAAS;AAKxC,UAAI,YAAY,QAAQ,CAAE,MAAM,KAAK,cAAc,UAAU,QAAQ,GAAI;AACrE;AACA;AAAA,MACJ;AACA,UAAI;AACA,cAAM,MAAyB;AAAA,UAC3B;AAAA,UACA,QAAQ,KAAK;AAAA,UACb,OAAO;AAAA;AAAA;AAAA;AAAA,UAIP,QAAQ;AAAA,QACZ;AACA,cAAM,SAAS,GAAG;AAClB;AAAA,MACJ,SAAS,KAAK;AACV;AAIA,cAAM,MAAM,KAAK,OAAO,OAAO,KAAK,KAAK,MAAM,KAAK,KAAK,OAAO,KAAK,KAAK,KAAK,MAAM;AACrF;AAAA,UACI,yBAAyB,QAAQ,wBAAwB,OAAQ,OAA4B,MAAM,GAAG,CAAC,MAAM,WAAW,GAAG,CAAC;AAAA,QAChI;AAAA,MACJ;AAAA,IACJ;AAEA,SAAK,OAAO;AAAA,MACR,yBAAyB,QAAQ,YAAY,KAAK,MAAM,MAAM,QAAQ,MAAM,aAAa,QAAQ,cAAc,OAAO,wBAAwB,MAAM;AAAA,IACxJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAc,cAAc,UAAkB,KAA+B;AACzE,UAAM,UAAU,KAAK,gBAAgB;AACrC,QAAI,WAAW,OAAO,QAAQ,UAAU,YAAY;AAChD,UAAI;AACA,eAAO,MAAM,QAAQ,MAAM,GAAG;AAAA,MAClC,SAAS,KAAK;AACV,aAAK,OAAO;AAAA,UACR,yBAAyB,QAAQ,oCAAoC,GAAG,4HAC4B,WAAW,GAAG,CAAC;AAAA,QACvH;AACA,eAAO;AAAA,MACX;AAAA,IACJ;AACA,QAAI,CAAC,KAAK,wBAAwB;AAC9B,WAAK,yBAAyB;AAC9B,WAAK,OAAO;AAAA,QACR;AAAA,MAGJ;AAAA,IACJ;AACA,UAAM,MAAM,KAAK,IAAI,EAAE,QAAQ;AAC/B,UAAM,SAAS,MAAM;AACrB,eAAW,CAAC,GAAG,CAAC,KAAK,KAAK,aAAa;AACnC,UAAI,IAAI,OAAQ,MAAK,YAAY,OAAO,CAAC;AAAA,IAC7C;AACA,QAAI,KAAK,YAAY,IAAI,GAAG,EAAG,QAAO;AACtC,SAAK,YAAY,IAAI,KAAK,GAAG;AAC7B,WAAO;AAAA,EACX;AAAA,EAEA,KAAK,UAAwB;AACzB,UAAM,UAAU,KAAK,MAAM,IAAI,QAAQ;AACvC,QAAI,CAAC,QAAS;AACd,SAAK,MAAM,OAAO,QAAQ;AAC1B,UAAM,aAAa,KAAK,cAAc;AACtC,QAAI,CAAC,cAAc,OAAO,WAAW,WAAW,WAAY;AAC5D,SAAK,QAAQ,QAAQ,WAAW,OAAO,OAAO,CAAC,EAC1C,KAAK,MAAM,KAAK,OAAO,QAAQ,iCAAiC,QAAQ,GAAG,CAAC,EAC5E,MAAM,CAAC,QAAQ;AACZ,WAAK,OAAO;AAAA,QACR,0CAA0C,QAAQ,MAAM,WAAW,GAAG,CAAC;AAAA,MAC3E;AAAA,IACJ,CAAC;AAAA,EACT;AACJ;;;ACrbO,IAAM,4BAAN,MAAkD;AAAA,EAAlD;AACH,gBAAO;AACP,gBAAO;AACP,mBAAU;AACV,wBAAe,CAAC,+BAA+B,iCAAiC;AAAA;AAAA,EAEhF,MAAM,KAAK,KAAmC;AAC1C,QAAI,OAAO,KAAK,0CAA0C;AAAA,EAC9D;AAAA,EAEA,MAAM,MAAM,KAAmC;AAK3C,QAAI,KAAK,gBAAgB,YAAY;AACjC,YAAM,aAAa,KAAK,eAA0C,KAAK,YAAY;AACnF,UAAI,CAAC,cAAc,OAAO,WAAW,oBAAoB,YAAY;AACjE,YAAI,OAAO;AAAA,UACP;AAAA,QACJ;AACA;AAAA,MACJ;AAKA,UAAI,CAAC,KAAK,eAAkC,KAAK,KAAK,GAAG;AACrD,YAAI,OAAO;AAAA,UACP;AAAA,QACJ;AAAA,MACJ;AACA,UAAI,CAAC,KAAK,kBAAkB,GAAG,GAAG;AAC9B,YAAI,OAAO;AAAA,UACP;AAAA,QACJ;AAAA,MACJ;AAEA,YAAM,UAAU,IAAI;AAAA,QAChB,MAAM,KAAK,eAAkC,KAAK,KAAK;AAAA,QACvD,MAAM,KAAK,kBAAkB,GAAG;AAAA,QAChC,IAAI;AAAA,QACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,MAAM;AACF,gBAAM,MAAM,KAAK,eAAkD,KAAK,YAAY;AACpF,iBAAO,OAAO,OAAO,IAAI,UAAU,aAAc,MAAmC;AAAA,QACxF;AAAA,MACJ;AACA,iBAAW,gBAAgB,OAAO;AAClC,UAAI,OAAO,KAAK,6DAA6D;AAAA,IACjF,CAAC;AAAA,EACL;AAAA,EAEQ,eAAkB,KAAoB,MAAwB;AAClE,QAAI;AACA,aAAO,IAAI,WAAc,IAAI,KAAK;AAAA,IACtC,QAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEQ,kBAAkB,KAAmD;AAGzE,WACI,KAAK,eAAuC,KAAK,UAAU,KAC3D,KAAK,eAAuC,KAAK,MAAM;AAAA,EAE/D;AACJ;","names":["JOB_PREFIX","window"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/schedule-trigger.ts","../src/plugin.ts","../src/time-relative-trigger.ts","../src/time-relative-plugin.ts"],"mappings":"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","names":["JOB_PREFIX","window"]}
|