@smthrs/triggers 0.0.0-stage → 1.0.0-rc.4
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 +219 -0
- package/LICENSE +21 -0
- package/README.md +109 -2
- package/dist/cjs/CatchUp.d.ts +25 -0
- package/dist/cjs/CatchUp.d.ts.map +1 -0
- package/dist/cjs/CatchUp.js +72 -0
- package/dist/cjs/CatchUp.js.map +7 -0
- package/dist/cjs/Channel.d.ts +108 -0
- package/dist/cjs/Channel.d.ts.map +1 -0
- package/dist/cjs/Channel.js +25 -0
- package/dist/cjs/Channel.js.map +7 -0
- package/dist/cjs/ClaimDecision.d.ts +183 -0
- package/dist/cjs/ClaimDecision.d.ts.map +1 -0
- package/dist/cjs/ClaimDecision.js +144 -0
- package/dist/cjs/ClaimDecision.js.map +7 -0
- package/dist/cjs/Cron.d.ts +91 -0
- package/dist/cjs/Cron.d.ts.map +1 -0
- package/dist/cjs/Cron.js +108 -0
- package/dist/cjs/Cron.js.map +7 -0
- package/dist/cjs/DispatchReader.d.ts +77 -0
- package/dist/cjs/DispatchReader.d.ts.map +1 -0
- package/dist/cjs/DispatchReader.js +121 -0
- package/dist/cjs/DispatchReader.js.map +7 -0
- package/dist/cjs/Overlap.d.ts +40 -0
- package/dist/cjs/Overlap.d.ts.map +1 -0
- package/dist/cjs/Overlap.js +37 -0
- package/dist/cjs/Overlap.js.map +7 -0
- package/dist/cjs/Schedule.d.ts +96 -0
- package/dist/cjs/Schedule.d.ts.map +1 -0
- package/dist/cjs/Schedule.js +61 -0
- package/dist/cjs/Schedule.js.map +7 -0
- package/dist/cjs/Scheduler.d.ts +248 -0
- package/dist/cjs/Scheduler.d.ts.map +1 -0
- package/dist/cjs/Scheduler.js +647 -0
- package/dist/cjs/Scheduler.js.map +7 -0
- package/dist/cjs/SqlTriggerStore.d.ts +29 -0
- package/dist/cjs/SqlTriggerStore.d.ts.map +1 -0
- package/dist/cjs/SqlTriggerStore.js +483 -0
- package/dist/cjs/SqlTriggerStore.js.map +7 -0
- package/dist/cjs/Trigger.d.ts +81 -0
- package/dist/cjs/Trigger.d.ts.map +1 -0
- package/dist/cjs/Trigger.js +54 -0
- package/dist/cjs/Trigger.js.map +7 -0
- package/dist/cjs/TriggerError.d.ts +58 -0
- package/dist/cjs/TriggerError.d.ts.map +1 -0
- package/dist/cjs/TriggerError.js +83 -0
- package/dist/cjs/TriggerError.js.map +7 -0
- package/dist/cjs/TriggerStore.d.ts +411 -0
- package/dist/cjs/TriggerStore.d.ts.map +1 -0
- package/dist/cjs/TriggerStore.js +127 -0
- package/dist/cjs/TriggerStore.js.map +7 -0
- package/dist/cjs/Webhook.d.ts +118 -0
- package/dist/cjs/Webhook.d.ts.map +1 -0
- package/dist/cjs/Webhook.js +153 -0
- package/dist/cjs/Webhook.js.map +7 -0
- package/dist/cjs/index.d.ts +30 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +57 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/internal/ActiveRuns.d.ts +51 -0
- package/dist/cjs/internal/ActiveRuns.d.ts.map +1 -0
- package/dist/cjs/internal/ActiveRuns.js +56 -0
- package/dist/cjs/internal/ActiveRuns.js.map +7 -0
- package/dist/cjs/internal/DueOccurrences.d.ts +32 -0
- package/dist/cjs/internal/DueOccurrences.d.ts.map +1 -0
- package/dist/cjs/internal/DueOccurrences.js +80 -0
- package/dist/cjs/internal/DueOccurrences.js.map +7 -0
- package/dist/cjs/internal/WallClock.d.ts +59 -0
- package/dist/cjs/internal/WallClock.d.ts.map +1 -0
- package/dist/cjs/internal/WallClock.js +132 -0
- package/dist/cjs/internal/WallClock.js.map +7 -0
- package/dist/cjs/migrations/0001_triggers.d.ts +15 -0
- package/dist/cjs/migrations/0001_triggers.d.ts.map +1 -0
- package/dist/cjs/migrations/0001_triggers.js +64 -0
- package/dist/cjs/migrations/0001_triggers.js.map +7 -0
- package/dist/cjs/migrations/0002_reservation_lease.d.ts +15 -0
- package/dist/cjs/migrations/0002_reservation_lease.d.ts.map +1 -0
- package/dist/cjs/migrations/0002_reservation_lease.js +41 -0
- package/dist/cjs/migrations/0002_reservation_lease.js.map +7 -0
- package/dist/cjs/migrations/0003_heartbeat.d.ts +16 -0
- package/dist/cjs/migrations/0003_heartbeat.d.ts.map +1 -0
- package/dist/cjs/migrations/0003_heartbeat.js +44 -0
- package/dist/cjs/migrations/0003_heartbeat.js.map +7 -0
- package/dist/cjs/migrations/0004_fire_run_index.d.ts +17 -0
- package/dist/cjs/migrations/0004_fire_run_index.d.ts.map +1 -0
- package/dist/cjs/migrations/0004_fire_run_index.js +40 -0
- package/dist/cjs/migrations/0004_fire_run_index.js.map +7 -0
- package/dist/cjs/migrations/index.d.ts +33 -0
- package/dist/cjs/migrations/index.d.ts.map +1 -0
- package/dist/cjs/migrations/index.js +50 -0
- package/dist/cjs/migrations/index.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/test/TestTriggers.d.ts +12 -0
- package/dist/cjs/test/TestTriggers.d.ts.map +1 -0
- package/dist/cjs/test/TestTriggers.js +421 -0
- package/dist/cjs/test/TestTriggers.js.map +7 -0
- package/dist/esm/CatchUp.d.ts +25 -0
- package/dist/esm/CatchUp.d.ts.map +1 -0
- package/dist/esm/CatchUp.js +52 -0
- package/dist/esm/CatchUp.js.map +1 -0
- package/dist/esm/Channel.d.ts +108 -0
- package/dist/esm/Channel.d.ts.map +1 -0
- package/dist/esm/Channel.js +19 -0
- package/dist/esm/Channel.js.map +1 -0
- package/dist/esm/ClaimDecision.d.ts +183 -0
- package/dist/esm/ClaimDecision.d.ts.map +1 -0
- package/dist/esm/ClaimDecision.js +172 -0
- package/dist/esm/ClaimDecision.js.map +1 -0
- package/dist/esm/Cron.d.ts +91 -0
- package/dist/esm/Cron.d.ts.map +1 -0
- package/dist/esm/Cron.js +132 -0
- package/dist/esm/Cron.js.map +1 -0
- package/dist/esm/DispatchReader.d.ts +77 -0
- package/dist/esm/DispatchReader.d.ts.map +1 -0
- package/dist/esm/DispatchReader.js +152 -0
- package/dist/esm/DispatchReader.js.map +1 -0
- package/dist/esm/Overlap.d.ts +40 -0
- package/dist/esm/Overlap.d.ts.map +1 -0
- package/dist/esm/Overlap.js +31 -0
- package/dist/esm/Overlap.js.map +1 -0
- package/dist/esm/Schedule.d.ts +96 -0
- package/dist/esm/Schedule.d.ts.map +1 -0
- package/dist/esm/Schedule.js +73 -0
- package/dist/esm/Schedule.js.map +1 -0
- package/dist/esm/Scheduler.d.ts +248 -0
- package/dist/esm/Scheduler.d.ts.map +1 -0
- package/dist/esm/Scheduler.js +734 -0
- package/dist/esm/Scheduler.js.map +1 -0
- package/dist/esm/SqlTriggerStore.d.ts +29 -0
- package/dist/esm/SqlTriggerStore.d.ts.map +1 -0
- package/dist/esm/SqlTriggerStore.js +483 -0
- package/dist/esm/SqlTriggerStore.js.map +1 -0
- package/dist/esm/Trigger.d.ts +81 -0
- package/dist/esm/Trigger.d.ts.map +1 -0
- package/dist/esm/Trigger.js +56 -0
- package/dist/esm/Trigger.js.map +1 -0
- package/dist/esm/TriggerError.d.ts +58 -0
- package/dist/esm/TriggerError.d.ts.map +1 -0
- package/dist/esm/TriggerError.js +110 -0
- package/dist/esm/TriggerError.js.map +1 -0
- package/dist/esm/TriggerStore.d.ts +411 -0
- package/dist/esm/TriggerStore.d.ts.map +1 -0
- package/dist/esm/TriggerStore.js +209 -0
- package/dist/esm/TriggerStore.js.map +1 -0
- package/dist/esm/Webhook.d.ts +118 -0
- package/dist/esm/Webhook.d.ts.map +1 -0
- package/dist/esm/Webhook.js +186 -0
- package/dist/esm/Webhook.js.map +1 -0
- package/dist/esm/index.d.ts +30 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +30 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/ActiveRuns.d.ts +51 -0
- package/dist/esm/internal/ActiveRuns.d.ts.map +1 -0
- package/dist/esm/internal/ActiveRuns.js +34 -0
- package/dist/esm/internal/ActiveRuns.js.map +1 -0
- package/dist/esm/internal/DueOccurrences.d.ts +32 -0
- package/dist/esm/internal/DueOccurrences.d.ts.map +1 -0
- package/dist/esm/internal/DueOccurrences.js +55 -0
- package/dist/esm/internal/DueOccurrences.js.map +1 -0
- package/dist/esm/internal/WallClock.d.ts +59 -0
- package/dist/esm/internal/WallClock.d.ts.map +1 -0
- package/dist/esm/internal/WallClock.js +155 -0
- package/dist/esm/internal/WallClock.js.map +1 -0
- package/dist/esm/migrations/0001_triggers.d.ts +15 -0
- package/dist/esm/migrations/0001_triggers.d.ts.map +1 -0
- package/dist/esm/migrations/0001_triggers.js +42 -0
- package/dist/esm/migrations/0001_triggers.js.map +1 -0
- package/dist/esm/migrations/0002_reservation_lease.d.ts +15 -0
- package/dist/esm/migrations/0002_reservation_lease.d.ts.map +1 -0
- package/dist/esm/migrations/0002_reservation_lease.js +19 -0
- package/dist/esm/migrations/0002_reservation_lease.js.map +1 -0
- package/dist/esm/migrations/0003_heartbeat.d.ts +16 -0
- package/dist/esm/migrations/0003_heartbeat.d.ts.map +1 -0
- package/dist/esm/migrations/0003_heartbeat.js +23 -0
- package/dist/esm/migrations/0003_heartbeat.js.map +1 -0
- package/dist/esm/migrations/0004_fire_run_index.d.ts +17 -0
- package/dist/esm/migrations/0004_fire_run_index.d.ts.map +1 -0
- package/dist/esm/migrations/0004_fire_run_index.js +20 -0
- package/dist/esm/migrations/0004_fire_run_index.js.map +1 -0
- package/dist/esm/migrations/index.d.ts +33 -0
- package/dist/esm/migrations/index.d.ts.map +1 -0
- package/dist/esm/migrations/index.js +37 -0
- package/dist/esm/migrations/index.js.map +1 -0
- package/dist/esm/test/TestTriggers.d.ts +12 -0
- package/dist/esm/test/TestTriggers.d.ts.map +1 -0
- package/dist/esm/test/TestTriggers.js +439 -0
- package/dist/esm/test/TestTriggers.js.map +1 -0
- package/docs/README.md +140 -0
- package/docs/api.md +1186 -0
- package/docs/concepts/channels.md +103 -0
- package/docs/concepts/claim-protocol.md +229 -0
- package/docs/concepts/policies.md +124 -0
- package/docs/concepts/schedules.md +134 -0
- package/docs/guides/choose-a-policy.md +113 -0
- package/docs/guides/declare-a-trigger.md +136 -0
- package/docs/guides/ingest-a-webhook.md +164 -0
- package/docs/guides/run-the-scheduler.md +173 -0
- package/docs/guides/testing.md +157 -0
- package/docs/installation.md +81 -0
- package/docs/quickstart.md +163 -0
- package/docs/troubleshooting.md +281 -0
- package/package.json +241 -3
- package/src/CatchUp.ts +73 -0
- package/src/Channel.ts +121 -0
- package/src/ClaimDecision.ts +303 -0
- package/src/Cron.ts +173 -0
- package/src/DispatchReader.ts +179 -0
- package/src/Overlap.ts +53 -0
- package/src/Schedule.ts +112 -0
- package/src/Scheduler.ts +1154 -0
- package/src/SqlTriggerStore.ts +638 -0
- package/src/Trigger.ts +84 -0
- package/src/TriggerError.ts +129 -0
- package/src/TriggerStore.ts +514 -0
- package/src/Webhook.ts +270 -0
- package/src/index.ts +30 -0
- package/src/internal/ActiveRuns.ts +83 -0
- package/src/internal/DueOccurrences.ts +101 -0
- package/src/internal/WallClock.ts +172 -0
- package/src/migrations/0001_triggers.ts +43 -0
- package/src/migrations/0002_reservation_lease.ts +20 -0
- package/src/migrations/0003_heartbeat.ts +24 -0
- package/src/migrations/0004_fire_run_index.ts +21 -0
- package/src/migrations/index.ts +40 -0
- package/src/test/TestTriggers.ts +563 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `@smthrs/control` `DispatchReader` port served from a `TriggerStore`.
|
|
3
|
+
*
|
|
4
|
+
* `Control.list` answers `{ _tag: "triggers" }` and `{ _tag: "fires" }` through
|
|
5
|
+
* the port declared in `@smthrs/control/DispatchReader`. The port lives there
|
|
6
|
+
* because this package depends on control (the scheduler launches runs through
|
|
7
|
+
* it); the adapter lives here because only this package can read the store.
|
|
8
|
+
* The host composes the two: {@link layer} over the same store the scheduler
|
|
9
|
+
* writes.
|
|
10
|
+
*
|
|
11
|
+
* @see packages/smithers/agent/triggers/docs/api.md
|
|
12
|
+
*
|
|
13
|
+
* @since 1.0.0-rc.0
|
|
14
|
+
*/
|
|
15
|
+
import { type FireSummary, type TriggerSummary } from "@smthrs/control/ControlSchema";
|
|
16
|
+
import * as Port from "@smthrs/control/DispatchReader";
|
|
17
|
+
import * as Effect from "effect/Effect";
|
|
18
|
+
import * as Layer from "effect/Layer";
|
|
19
|
+
import * as Option from "effect/Option";
|
|
20
|
+
import type { TriggerError } from "./TriggerError.ts";
|
|
21
|
+
import { type FireRecord, type Held, type Registered, TriggerStore } from "./TriggerStore.ts";
|
|
22
|
+
/**
|
|
23
|
+
* How many upcoming occurrences a trigger summary carries.
|
|
24
|
+
*
|
|
25
|
+
* @category constants
|
|
26
|
+
* @since 1.0.0-rc.0
|
|
27
|
+
*/
|
|
28
|
+
export declare const nextOccurrenceCount = 5;
|
|
29
|
+
/**
|
|
30
|
+
* The next {@link nextOccurrenceCount} occurrences strictly after `now`, as
|
|
31
|
+
* epoch milliseconds in ascending order.
|
|
32
|
+
*
|
|
33
|
+
* @category getters
|
|
34
|
+
* @since 1.0.0-rc.0
|
|
35
|
+
*/
|
|
36
|
+
export declare const nextOccurrences: (trigger: Pick<Registered, "cron" | "timezone">, now: number) => Effect.Effect<ReadonlyArray<number>, TriggerError>;
|
|
37
|
+
/**
|
|
38
|
+
* Maps one stored trigger and what it holds to the control plane's summary.
|
|
39
|
+
*
|
|
40
|
+
* A launch reservation is not a run the runtime knows about, so it is
|
|
41
|
+
* reported as no active run; the ledger still shows the claimed occurrence.
|
|
42
|
+
*
|
|
43
|
+
* @category constructors
|
|
44
|
+
* @since 1.0.0-rc.0
|
|
45
|
+
*/
|
|
46
|
+
export declare const toTriggerSummary: (trigger: Registered, held: Held, nextOccurrencesMs: ReadonlyArray<number>, schedulerLastTickMs: Option.Option<number>) => TriggerSummary;
|
|
47
|
+
/**
|
|
48
|
+
* Maps one ledger row to the control plane's fire summary.
|
|
49
|
+
*
|
|
50
|
+
* @category constructors
|
|
51
|
+
* @since 1.0.0-rc.0
|
|
52
|
+
*/
|
|
53
|
+
export declare const toFireSummary: (record: FireRecord) => FireSummary;
|
|
54
|
+
/**
|
|
55
|
+
* Builds the port over the ambient {@link TriggerStore}.
|
|
56
|
+
*
|
|
57
|
+
* `list` answers every trigger the store holds, taking each row's held state
|
|
58
|
+
* from the listing itself; `fires` pushes the request's filters into the
|
|
59
|
+
* ledger query and answers the matching rows newest first, reading only as
|
|
60
|
+
* many as the requested page needs.
|
|
61
|
+
* `Control.list` applies the filters again and pages. A store failure is a
|
|
62
|
+
* `PersistenceError` naming the listing that failed.
|
|
63
|
+
*
|
|
64
|
+
* @category constructors
|
|
65
|
+
* @since 1.0.0-rc.0
|
|
66
|
+
*/
|
|
67
|
+
export declare const make: Effect.Effect<Port.Service, never, TriggerStore>;
|
|
68
|
+
/**
|
|
69
|
+
* Provides the control plane's `DispatchReader` from the ambient
|
|
70
|
+
* {@link TriggerStore}, so `Control.list` answers `triggers` and `fires` from
|
|
71
|
+
* the store the scheduler writes.
|
|
72
|
+
*
|
|
73
|
+
* @category layers
|
|
74
|
+
* @since 1.0.0-rc.0
|
|
75
|
+
*/
|
|
76
|
+
export declare const layer: Layer.Layer<Port.DispatchReader, never, TriggerStore>;
|
|
77
|
+
//# sourceMappingURL=DispatchReader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DispatchReader.d.ts","sourceRoot":"","sources":["../../src/DispatchReader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAmB,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,+BAA+B,CAAA;AACtG,OAAO,KAAK,IAAI,MAAM,gCAAgC,CAAA;AAEtD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,IAAI,EAAiB,KAAK,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAE5G;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAA;AAmBpC;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAC1B,SAAS,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAAC,EAC9C,KAAK,MAAM,KACV,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,YAAY,CAUhD,CAAA;AAEJ;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,GAC3B,SAAS,UAAU,EACnB,MAAM,IAAI,EACV,mBAAmB,aAAa,CAAC,MAAM,CAAC,EACxC,qBAAqB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KACzC,cAgBD,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,UAAU,KAAG,WAMjD,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,YAAY,CAkChE,CAAA;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,EAAE,YAAY,CAA2C,CAAA"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var DispatchReader_exports = {};
|
|
30
|
+
__export(DispatchReader_exports, {
|
|
31
|
+
layer: () => layer,
|
|
32
|
+
make: () => make,
|
|
33
|
+
nextOccurrenceCount: () => nextOccurrenceCount,
|
|
34
|
+
nextOccurrences: () => nextOccurrences,
|
|
35
|
+
toFireSummary: () => toFireSummary,
|
|
36
|
+
toTriggerSummary: () => toTriggerSummary
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(DispatchReader_exports);
|
|
39
|
+
var import_ControlError = require("@smthrs/control/ControlError");
|
|
40
|
+
var import_ControlSchema = require("@smthrs/control/ControlSchema");
|
|
41
|
+
var Port = __toESM(require("@smthrs/control/DispatchReader"), 1);
|
|
42
|
+
var Clock = __toESM(require("effect/Clock"), 1);
|
|
43
|
+
var Effect = __toESM(require("effect/Effect"), 1);
|
|
44
|
+
var Layer = __toESM(require("effect/Layer"), 1);
|
|
45
|
+
var Option = __toESM(require("effect/Option"), 1);
|
|
46
|
+
var Result = __toESM(require("effect/Result"), 1);
|
|
47
|
+
var Cron = __toESM(require("./Cron.js"), 1);
|
|
48
|
+
var import_TriggerStore = require("./TriggerStore.js");
|
|
49
|
+
const nextOccurrenceCount = 5;
|
|
50
|
+
const firesNeeded = (request) => {
|
|
51
|
+
const start = request.cursor === void 0 ? 0 : Number(request.cursor);
|
|
52
|
+
const size = request.limit ?? import_ControlSchema.defaultPageSize;
|
|
53
|
+
return Number.isSafeInteger(start) && start >= 0 && Number.isSafeInteger(size) && size >= 1 ? start + size + 1 : void 0;
|
|
54
|
+
};
|
|
55
|
+
const persistence = (operation) => (error) => new import_ControlError.PersistenceError({ operation, message: error.message, cause: error });
|
|
56
|
+
const nextOccurrences = (trigger, now) => Effect.gen(function* () {
|
|
57
|
+
const cron = yield* Cron.parse(trigger.cron, trigger.timezone);
|
|
58
|
+
const occurrences = [];
|
|
59
|
+
let from = new Date(now);
|
|
60
|
+
while (occurrences.length < nextOccurrenceCount) {
|
|
61
|
+
from = yield* Cron.next(cron, from);
|
|
62
|
+
occurrences.push(from.getTime());
|
|
63
|
+
}
|
|
64
|
+
return occurrences;
|
|
65
|
+
});
|
|
66
|
+
const toTriggerSummary = (trigger, held, nextOccurrencesMs, schedulerLastTickMs) => ({
|
|
67
|
+
triggerId: trigger.id,
|
|
68
|
+
flowId: trigger.flowId,
|
|
69
|
+
input: trigger.input,
|
|
70
|
+
cron: trigger.cron,
|
|
71
|
+
...trigger.timezone === void 0 ? {} : { timezone: trigger.timezone },
|
|
72
|
+
overlap: trigger.overlap,
|
|
73
|
+
catchUp: trigger.catchUp,
|
|
74
|
+
maxCatchUp: trigger.maxCatchUp,
|
|
75
|
+
enabled: trigger.enabled,
|
|
76
|
+
revision: trigger.revision,
|
|
77
|
+
...trigger.lastFiredAt === void 0 ? {} : { lastFiredAtMs: trigger.lastFiredAt },
|
|
78
|
+
...held.pendingAt === void 0 ? {} : { pendingAtMs: held.pendingAt },
|
|
79
|
+
...held.activeRunId === void 0 || (0, import_TriggerStore.isReservation)(held.activeRunId) ? {} : { activeRunId: held.activeRunId },
|
|
80
|
+
nextOccurrencesMs,
|
|
81
|
+
...Option.isSome(schedulerLastTickMs) ? { schedulerLastTickMs: schedulerLastTickMs.value } : {}
|
|
82
|
+
});
|
|
83
|
+
const toFireSummary = (record) => ({
|
|
84
|
+
triggerId: record.triggerId,
|
|
85
|
+
occurrenceAtMs: record.occurrence,
|
|
86
|
+
outcome: record.outcome,
|
|
87
|
+
...record.runId === void 0 ? {} : { runId: record.runId },
|
|
88
|
+
...record.error === void 0 ? {} : { error: record.error }
|
|
89
|
+
});
|
|
90
|
+
const make = Effect.gen(function* () {
|
|
91
|
+
const store = yield* import_TriggerStore.TriggerStore;
|
|
92
|
+
return Port.make({
|
|
93
|
+
list: Effect.fn("DispatchReader.list")(
|
|
94
|
+
() => Effect.gen(function* () {
|
|
95
|
+
const now = yield* Clock.currentTimeMillis;
|
|
96
|
+
const heartbeat = yield* store.lastHeartbeat();
|
|
97
|
+
const lastTick = Option.map(heartbeat, (beat) => beat.tickedAt);
|
|
98
|
+
const listing = yield* store.list();
|
|
99
|
+
return yield* Effect.forEach(listing, (row) => Effect.gen(function* () {
|
|
100
|
+
if (Result.isFailure(row.trigger)) return yield* Effect.fail(row.trigger.failure);
|
|
101
|
+
const trigger = row.trigger.success;
|
|
102
|
+
const upcoming = yield* nextOccurrences(trigger, now);
|
|
103
|
+
return toTriggerSummary(trigger, row, upcoming, lastTick);
|
|
104
|
+
}));
|
|
105
|
+
}).pipe(Effect.mapError(persistence("triggers")))
|
|
106
|
+
),
|
|
107
|
+
fires: Effect.fn("DispatchReader.fires")(
|
|
108
|
+
(request) => store.history({
|
|
109
|
+
triggerId: request.filters?.triggerId,
|
|
110
|
+
runId: request.filters?.runId,
|
|
111
|
+
outcome: request.filters?.outcome,
|
|
112
|
+
limit: firesNeeded(request)
|
|
113
|
+
}).pipe(
|
|
114
|
+
Effect.map((page) => page.items.map(toFireSummary)),
|
|
115
|
+
Effect.mapError(persistence("fires"))
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
const layer = Layer.effect(Port.DispatchReader)(make);
|
|
121
|
+
//# sourceMappingURL=DispatchReader.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/DispatchReader.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * The `@smthrs/control` `DispatchReader` port served from a `TriggerStore`.\n *\n * `Control.list` answers `{ _tag: \"triggers\" }` and `{ _tag: \"fires\" }` through\n * the port declared in `@smthrs/control/DispatchReader`. The port lives there\n * because this package depends on control (the scheduler launches runs through\n * it); the adapter lives here because only this package can read the store.\n * The host composes the two: {@link layer} over the same store the scheduler\n * writes.\n *\n * @see packages/smithers/agent/triggers/docs/api.md\n *\n * @since 1.0.0-rc.0\n */\n\nimport type { ControlError } from \"@smthrs/control/ControlError\"\nimport { PersistenceError } from \"@smthrs/control/ControlError\"\nimport { defaultPageSize, type FireSummary, type TriggerSummary } from \"@smthrs/control/ControlSchema\"\nimport * as Port from \"@smthrs/control/DispatchReader\"\nimport * as Clock from \"effect/Clock\"\nimport * as Effect from \"effect/Effect\"\nimport * as Layer from \"effect/Layer\"\nimport * as Option from \"effect/Option\"\nimport * as Result from \"effect/Result\"\nimport * as Cron from \"./Cron.ts\"\nimport type { TriggerError } from \"./TriggerError.ts\"\nimport { type FireRecord, type Held, isReservation, type Registered, TriggerStore } from \"./TriggerStore.ts\"\n\n/**\n * How many upcoming occurrences a trigger summary carries.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const nextOccurrenceCount = 5\n\n/**\n * How many ledger rows one `fires` page needs: every row before the page's\n * offset cursor, the page, and one more so `Control.list` can tell a next page\n * exists. A cursor Control will refuse reads nothing extra: it answers\n * `undefined`, and the refusal comes from Control.\n */\nconst firesNeeded = (request: Port.FiresRequest): number | undefined => {\n const start = request.cursor === undefined ? 0 : Number(request.cursor)\n const size = request.limit ?? defaultPageSize\n return Number.isSafeInteger(start) && start >= 0 && Number.isSafeInteger(size) && size >= 1\n ? start + size + 1\n : undefined\n}\n\nconst persistence = (operation: string) => (error: TriggerError): ControlError =>\n new PersistenceError({ operation, message: error.message, cause: error })\n\n/**\n * The next {@link nextOccurrenceCount} occurrences strictly after `now`, as\n * epoch milliseconds in ascending order.\n *\n * @category getters\n * @since 1.0.0-rc.0\n */\nexport const nextOccurrences = (\n trigger: Pick<Registered, \"cron\" | \"timezone\">,\n now: number\n): Effect.Effect<ReadonlyArray<number>, TriggerError> =>\n Effect.gen(function*() {\n const cron = yield* Cron.parse(trigger.cron, trigger.timezone)\n const occurrences: Array<number> = []\n let from = new Date(now)\n while (occurrences.length < nextOccurrenceCount) {\n from = yield* Cron.next(cron, from)\n occurrences.push(from.getTime())\n }\n return occurrences\n })\n\n/**\n * Maps one stored trigger and what it holds to the control plane's summary.\n *\n * A launch reservation is not a run the runtime knows about, so it is\n * reported as no active run; the ledger still shows the claimed occurrence.\n *\n * @category constructors\n * @since 1.0.0-rc.0\n */\nexport const toTriggerSummary = (\n trigger: Registered,\n held: Held,\n nextOccurrencesMs: ReadonlyArray<number>,\n schedulerLastTickMs: Option.Option<number>\n): TriggerSummary => ({\n triggerId: trigger.id,\n flowId: trigger.flowId,\n input: trigger.input,\n cron: trigger.cron,\n ...(trigger.timezone === undefined ? {} : { timezone: trigger.timezone }),\n overlap: trigger.overlap,\n catchUp: trigger.catchUp,\n maxCatchUp: trigger.maxCatchUp,\n enabled: trigger.enabled,\n revision: trigger.revision,\n ...(trigger.lastFiredAt === undefined ? {} : { lastFiredAtMs: trigger.lastFiredAt }),\n ...(held.pendingAt === undefined ? {} : { pendingAtMs: held.pendingAt }),\n ...(held.activeRunId === undefined || isReservation(held.activeRunId) ? {} : { activeRunId: held.activeRunId }),\n nextOccurrencesMs,\n ...(Option.isSome(schedulerLastTickMs) ? { schedulerLastTickMs: schedulerLastTickMs.value } : {})\n})\n\n/**\n * Maps one ledger row to the control plane's fire summary.\n *\n * @category constructors\n * @since 1.0.0-rc.0\n */\nexport const toFireSummary = (record: FireRecord): FireSummary => ({\n triggerId: record.triggerId,\n occurrenceAtMs: record.occurrence,\n outcome: record.outcome,\n ...(record.runId === undefined ? {} : { runId: record.runId }),\n ...(record.error === undefined ? {} : { error: record.error })\n})\n\n/**\n * Builds the port over the ambient {@link TriggerStore}.\n *\n * `list` answers every trigger the store holds, taking each row's held state\n * from the listing itself; `fires` pushes the request's filters into the\n * ledger query and answers the matching rows newest first, reading only as\n * many as the requested page needs.\n * `Control.list` applies the filters again and pages. A store failure is a\n * `PersistenceError` naming the listing that failed.\n *\n * @category constructors\n * @since 1.0.0-rc.0\n */\nexport const make: Effect.Effect<Port.Service, never, TriggerStore> = Effect.gen(function*() {\n const store = yield* TriggerStore\n return Port.make({\n list: Effect.fn(\"DispatchReader.list\")(() =>\n Effect.gen(function*() {\n const now = yield* Clock.currentTimeMillis\n const heartbeat = yield* store.lastHeartbeat()\n const lastTick = Option.map(heartbeat, (beat) => beat.tickedAt)\n const listing = yield* store.list()\n return yield* Effect.forEach(listing, (row) =>\n Effect.gen(function*() {\n // A row the store could not decode fails the listing rather than\n // being reported as a trigger with invented fields; the failure\n // names the row. The listing already carries what `inspect` reads,\n // so a summary costs no second read per trigger.\n if (Result.isFailure(row.trigger)) return yield* Effect.fail(row.trigger.failure)\n const trigger = row.trigger.success\n const upcoming = yield* nextOccurrences(trigger, now)\n return toTriggerSummary(trigger, row, upcoming, lastTick)\n }))\n }).pipe(Effect.mapError(persistence(\"triggers\")))\n ),\n fires: Effect.fn(\"DispatchReader.fires\")((request) =>\n store.history({\n triggerId: request.filters?.triggerId,\n runId: request.filters?.runId,\n outcome: request.filters?.outcome,\n limit: firesNeeded(request)\n }).pipe(\n Effect.map((page) => page.items.map(toFireSummary)),\n Effect.mapError(persistence(\"fires\"))\n )\n )\n })\n})\n\n/**\n * Provides the control plane's `DispatchReader` from the ambient\n * {@link TriggerStore}, so `Control.list` answers `triggers` and `fires` from\n * the store the scheduler writes.\n *\n * @category layers\n * @since 1.0.0-rc.0\n */\nexport const layer: Layer.Layer<Port.DispatchReader, never, TriggerStore> = Layer.effect(Port.DispatchReader)(make)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure overlap policy decisions.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.1.0
|
|
5
|
+
*/
|
|
6
|
+
import type { Overlap as Policy } from "./Schedule.ts";
|
|
7
|
+
/**
|
|
8
|
+
* What the overlap decision is made from: whether a run is in flight, the
|
|
9
|
+
* buffered occurrence if any, and the occurrence now due.
|
|
10
|
+
*
|
|
11
|
+
* @category models
|
|
12
|
+
* @since 0.1.0
|
|
13
|
+
*/
|
|
14
|
+
export interface State {
|
|
15
|
+
readonly running: boolean;
|
|
16
|
+
readonly pending?: number | undefined;
|
|
17
|
+
readonly due: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* What to do with an occurrence that arrived while a run was in flight.
|
|
21
|
+
*
|
|
22
|
+
* @category models
|
|
23
|
+
* @since 0.1.0
|
|
24
|
+
*/
|
|
25
|
+
export type Action = "fire" | "skip" | "buffer" | "supersede";
|
|
26
|
+
/**
|
|
27
|
+
* Applies the overlap policy to the current state.
|
|
28
|
+
*
|
|
29
|
+
* @category decision
|
|
30
|
+
* @since 0.1.0
|
|
31
|
+
*/
|
|
32
|
+
export declare const decide: (policy: Policy, state: State) => Action;
|
|
33
|
+
/**
|
|
34
|
+
* The occurrence left buffered after this decision.
|
|
35
|
+
*
|
|
36
|
+
* @category decision
|
|
37
|
+
* @since 0.1.0
|
|
38
|
+
*/
|
|
39
|
+
export declare const pendingAfter: (state: State) => number;
|
|
40
|
+
//# sourceMappingURL=Overlap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Overlap.d.ts","sourceRoot":"","sources":["../../src/Overlap.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,eAAe,CAAA;AAEtD;;;;;;GAMG;AACH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AACD;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,CAAA;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GAAI,QAAQ,MAAM,EAAE,OAAO,KAAK,KAAG,MAUrD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,KAAK,KAAG,MAAwE,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var Overlap_exports = {};
|
|
20
|
+
__export(Overlap_exports, {
|
|
21
|
+
decide: () => decide,
|
|
22
|
+
pendingAfter: () => pendingAfter
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(Overlap_exports);
|
|
25
|
+
const decide = (policy, state) => {
|
|
26
|
+
if (!state.running) return "fire";
|
|
27
|
+
switch (policy) {
|
|
28
|
+
case "skip":
|
|
29
|
+
return "skip";
|
|
30
|
+
case "buffer-one":
|
|
31
|
+
return "buffer";
|
|
32
|
+
case "supersede":
|
|
33
|
+
return "supersede";
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const pendingAfter = (state) => Math.max(state.pending ?? Number.NEGATIVE_INFINITY, state.due);
|
|
37
|
+
//# sourceMappingURL=Overlap.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/Overlap.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Pure overlap policy decisions.\n *\n * @since 0.1.0\n */\n\nimport type { Overlap as Policy } from \"./Schedule.ts\"\n\n/**\n * What the overlap decision is made from: whether a run is in flight, the\n * buffered occurrence if any, and the occurrence now due.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface State {\n readonly running: boolean\n readonly pending?: number | undefined\n readonly due: number\n}\n/**\n * What to do with an occurrence that arrived while a run was in flight.\n *\n * @category models\n * @since 0.1.0\n */\nexport type Action = \"fire\" | \"skip\" | \"buffer\" | \"supersede\"\n\n/**\n * Applies the overlap policy to the current state.\n *\n * @category decision\n * @since 0.1.0\n */\nexport const decide = (policy: Policy, state: State): Action => {\n if (!state.running) return \"fire\"\n switch (policy) {\n case \"skip\":\n return \"skip\"\n case \"buffer-one\":\n return \"buffer\"\n case \"supersede\":\n return \"supersede\"\n }\n}\n\n/**\n * The occurrence left buffered after this decision.\n *\n * @category decision\n * @since 0.1.0\n */\nexport const pendingAfter = (state: State): number => Math.max(state.pending ?? Number.NEGATIVE_INFINITY, state.due)\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkCO,MAAM,SAAS,CAAC,QAAgB,UAAyB;AAC9D,MAAI,CAAC,MAAM,QAAS,QAAO;AAC3B,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAQO,MAAM,eAAe,CAAC,UAAyB,KAAK,IAAI,MAAM,WAAW,OAAO,mBAAmB,MAAM,GAAG;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reusable schedule declarations shared by triggers.
|
|
3
|
+
*
|
|
4
|
+
* @see packages/smithers/agent/triggers/docs/api.md
|
|
5
|
+
*
|
|
6
|
+
* @since 0.1.0
|
|
7
|
+
*/
|
|
8
|
+
import * as Effect from "effect/Effect";
|
|
9
|
+
import * as Schema from "effect/Schema";
|
|
10
|
+
import { type TriggerError } from "./TriggerError.ts";
|
|
11
|
+
/**
|
|
12
|
+
* Schedule overlap policies.
|
|
13
|
+
*
|
|
14
|
+
* @category schemas
|
|
15
|
+
* @since 0.1.0
|
|
16
|
+
*/
|
|
17
|
+
export declare const Overlap: Schema.Literals<readonly ["skip", "buffer-one", "supersede"]>;
|
|
18
|
+
/**
|
|
19
|
+
* Schedule overlap policy.
|
|
20
|
+
*
|
|
21
|
+
* @category models
|
|
22
|
+
* @since 0.1.0
|
|
23
|
+
*/
|
|
24
|
+
export type Overlap = typeof Overlap.Type;
|
|
25
|
+
/**
|
|
26
|
+
* Schedule catch-up policies.
|
|
27
|
+
*
|
|
28
|
+
* @category schemas
|
|
29
|
+
* @since 0.1.0
|
|
30
|
+
*/
|
|
31
|
+
export declare const CatchUp: Schema.Literals<readonly ["none", "one", "all"]>;
|
|
32
|
+
/**
|
|
33
|
+
* Schedule catch-up policy.
|
|
34
|
+
*
|
|
35
|
+
* @category models
|
|
36
|
+
* @since 0.1.0
|
|
37
|
+
*/
|
|
38
|
+
export type CatchUp = typeof CatchUp.Type;
|
|
39
|
+
/**
|
|
40
|
+
* The greatest catch-up bound a schedule may declare.
|
|
41
|
+
*
|
|
42
|
+
* A schedule may not owe more occurrences than one occurrence search returns,
|
|
43
|
+
* so the ceiling is the search's own cap.
|
|
44
|
+
*
|
|
45
|
+
* @category constants
|
|
46
|
+
* @since 0.1.0
|
|
47
|
+
*/
|
|
48
|
+
export declare const maxCatchUpLimit = 1000;
|
|
49
|
+
/**
|
|
50
|
+
* A reusable cron schedule and its overlap and catch-up policies.
|
|
51
|
+
*
|
|
52
|
+
* All three policy fields are optional. `maxCatchUp` defaults to `0`, which
|
|
53
|
+
* pairs with the `catchUp` default of `none`: a schedule that states no
|
|
54
|
+
* catch-up intent owes nothing after downtime.
|
|
55
|
+
*
|
|
56
|
+
* @category schemas
|
|
57
|
+
* @since 0.1.0
|
|
58
|
+
*/
|
|
59
|
+
export declare const Schedule: Schema.Struct<{
|
|
60
|
+
readonly cron: Schema.NonEmptyString;
|
|
61
|
+
readonly timezone: Schema.optional<Schema.NonEmptyString>;
|
|
62
|
+
readonly overlap: Schema.withDecodingDefault<Schema.Literals<readonly ["skip", "buffer-one", "supersede"]>, never>;
|
|
63
|
+
readonly catchUp: Schema.withDecodingDefault<Schema.Literals<readonly ["none", "one", "all"]>, never>;
|
|
64
|
+
readonly maxCatchUp: Schema.withDecodingDefault<Schema.Int, never>;
|
|
65
|
+
}>;
|
|
66
|
+
/**
|
|
67
|
+
* A reusable cron schedule.
|
|
68
|
+
*
|
|
69
|
+
* @category models
|
|
70
|
+
* @since 0.1.0
|
|
71
|
+
*/
|
|
72
|
+
export type Schedule = typeof Schedule.Type;
|
|
73
|
+
/**
|
|
74
|
+
* Refuses a declaration whose cron expression is malformed or which the
|
|
75
|
+
* calendar never satisfies.
|
|
76
|
+
*
|
|
77
|
+
* The schema types `cron` as a non-empty string, which is as much as a field
|
|
78
|
+
* schema can say: `0 0 30 2 *` passes every range check and matches no date.
|
|
79
|
+
* Only the occurrence search knows that, so every declaration path runs it
|
|
80
|
+
* here rather than leaving it to the tick that would have fired the trigger.
|
|
81
|
+
*
|
|
82
|
+
* @category constructors
|
|
83
|
+
* @since 0.1.0
|
|
84
|
+
*/
|
|
85
|
+
export declare const validate: <A extends {
|
|
86
|
+
readonly cron: string;
|
|
87
|
+
readonly timezone?: string | undefined;
|
|
88
|
+
}>(declaration: A) => Effect.Effect<A, TriggerError>;
|
|
89
|
+
/**
|
|
90
|
+
* Decodes and validates a schedule declaration.
|
|
91
|
+
*
|
|
92
|
+
* @category constructors
|
|
93
|
+
* @since 0.1.0
|
|
94
|
+
*/
|
|
95
|
+
export declare const make: (input: unknown) => Effect.Effect<Schedule, TriggerError>;
|
|
96
|
+
//# sourceMappingURL=Schedule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Schedule.d.ts","sourceRoot":"","sources":["../../src/Schedule.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,OAAO,+DAAuD,CAAA;AAE3E;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,OAAO,kDAA0C,CAAA;AAE9D;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,OAAsB,CAAA;AAElD;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ;;;;;;EASnB,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAE3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,EAClG,aAAa,CAAC,KACb,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,YAAY,CAA+E,CAAA;AAE/G;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,OAAO,OAAO,KAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAIvE,CAAA"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var Schedule_exports = {};
|
|
30
|
+
__export(Schedule_exports, {
|
|
31
|
+
CatchUp: () => CatchUp,
|
|
32
|
+
Overlap: () => Overlap,
|
|
33
|
+
Schedule: () => Schedule,
|
|
34
|
+
make: () => make,
|
|
35
|
+
maxCatchUpLimit: () => maxCatchUpLimit,
|
|
36
|
+
validate: () => validate
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(Schedule_exports);
|
|
39
|
+
var Effect = __toESM(require("effect/Effect"), 1);
|
|
40
|
+
var Schema = __toESM(require("effect/Schema"), 1);
|
|
41
|
+
var Cron = __toESM(require("./Cron.js"), 1);
|
|
42
|
+
var import_TriggerError = require("./TriggerError.js");
|
|
43
|
+
const Overlap = Schema.Literals(["skip", "buffer-one", "supersede"]);
|
|
44
|
+
const CatchUp = Schema.Literals(["none", "one", "all"]);
|
|
45
|
+
const maxCatchUpLimit = Cron.maxOccurrences;
|
|
46
|
+
const Schedule = Schema.Struct({
|
|
47
|
+
cron: Schema.NonEmptyString,
|
|
48
|
+
timezone: Schema.optional(Schema.NonEmptyString),
|
|
49
|
+
overlap: Overlap.pipe(Schema.withDecodingDefault(Effect.succeed("skip"))),
|
|
50
|
+
catchUp: CatchUp.pipe(Schema.withDecodingDefault(Effect.succeed("none"))),
|
|
51
|
+
maxCatchUp: Schema.Int.check(
|
|
52
|
+
Schema.isGreaterThanOrEqualTo(0),
|
|
53
|
+
Schema.isLessThanOrEqualTo(maxCatchUpLimit)
|
|
54
|
+
).pipe(Schema.withDecodingDefault(Effect.succeed(0)))
|
|
55
|
+
});
|
|
56
|
+
const validate = (declaration) => Effect.as(Cron.parse(declaration.cron, declaration.timezone), declaration);
|
|
57
|
+
const make = (input) => Schema.decodeUnknownEffect(Schedule)(input).pipe(
|
|
58
|
+
Effect.mapError((cause) => (0, import_TriggerError.fromSchemaError)("invalid_schedule", "Schedule declaration is invalid", cause)),
|
|
59
|
+
Effect.flatMap(validate)
|
|
60
|
+
);
|
|
61
|
+
//# sourceMappingURL=Schedule.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/Schedule.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Reusable schedule declarations shared by triggers.\n *\n * @see packages/smithers/agent/triggers/docs/api.md\n *\n * @since 0.1.0\n */\n\nimport * as Effect from \"effect/Effect\"\nimport * as Schema from \"effect/Schema\"\nimport * as Cron from \"./Cron.ts\"\nimport { fromSchemaError, type TriggerError } from \"./TriggerError.ts\"\n\n/**\n * Schedule overlap policies.\n *\n * @category schemas\n * @since 0.1.0\n */\nexport const Overlap = Schema.Literals([\"skip\", \"buffer-one\", \"supersede\"])\n\n/**\n * Schedule overlap policy.\n *\n * @category models\n * @since 0.1.0\n */\nexport type Overlap = typeof Overlap.Type\n\n/**\n * Schedule catch-up policies.\n *\n * @category schemas\n * @since 0.1.0\n */\nexport const CatchUp = Schema.Literals([\"none\", \"one\", \"all\"])\n\n/**\n * Schedule catch-up policy.\n *\n * @category models\n * @since 0.1.0\n */\nexport type CatchUp = typeof CatchUp.Type\n\n/**\n * The greatest catch-up bound a schedule may declare.\n *\n * A schedule may not owe more occurrences than one occurrence search returns,\n * so the ceiling is the search's own cap.\n *\n * @category constants\n * @since 0.1.0\n */\nexport const maxCatchUpLimit = Cron.maxOccurrences\n\n/**\n * A reusable cron schedule and its overlap and catch-up policies.\n *\n * All three policy fields are optional. `maxCatchUp` defaults to `0`, which\n * pairs with the `catchUp` default of `none`: a schedule that states no\n * catch-up intent owes nothing after downtime.\n *\n * @category schemas\n * @since 0.1.0\n */\nexport const Schedule = Schema.Struct({\n cron: Schema.NonEmptyString,\n timezone: Schema.optional(Schema.NonEmptyString),\n overlap: Overlap.pipe(Schema.withDecodingDefault(Effect.succeed(\"skip\" as const))),\n catchUp: CatchUp.pipe(Schema.withDecodingDefault(Effect.succeed(\"none\" as const))),\n maxCatchUp: Schema.Int.check(\n Schema.isGreaterThanOrEqualTo(0),\n Schema.isLessThanOrEqualTo(maxCatchUpLimit)\n ).pipe(Schema.withDecodingDefault(Effect.succeed(0)))\n})\n\n/**\n * A reusable cron schedule.\n *\n * @category models\n * @since 0.1.0\n */\nexport type Schedule = typeof Schedule.Type\n\n/**\n * Refuses a declaration whose cron expression is malformed or which the\n * calendar never satisfies.\n *\n * The schema types `cron` as a non-empty string, which is as much as a field\n * schema can say: `0 0 30 2 *` passes every range check and matches no date.\n * Only the occurrence search knows that, so every declaration path runs it\n * here rather than leaving it to the tick that would have fired the trigger.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const validate = <A extends { readonly cron: string; readonly timezone?: string | undefined }>(\n declaration: A\n): Effect.Effect<A, TriggerError> => Effect.as(Cron.parse(declaration.cron, declaration.timezone), declaration)\n\n/**\n * Decodes and validates a schedule declaration.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const make = (input: unknown): Effect.Effect<Schedule, TriggerError> =>\n Schema.decodeUnknownEffect(Schedule)(input).pipe(\n Effect.mapError((cause) => fromSchemaError(\"invalid_schedule\", \"Schedule declaration is invalid\", cause)),\n Effect.flatMap(validate)\n )\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,aAAwB;AACxB,aAAwB;AACxB,WAAsB;AACtB,0BAAmD;AAQ5C,MAAM,UAAU,OAAO,SAAS,CAAC,QAAQ,cAAc,WAAW,CAAC;AAgBnE,MAAM,UAAU,OAAO,SAAS,CAAC,QAAQ,OAAO,KAAK,CAAC;AAmBtD,MAAM,kBAAkB,KAAK;AAY7B,MAAM,WAAW,OAAO,OAAO;AAAA,EACpC,MAAM,OAAO;AAAA,EACb,UAAU,OAAO,SAAS,OAAO,cAAc;AAAA,EAC/C,SAAS,QAAQ,KAAK,OAAO,oBAAoB,OAAO,QAAQ,MAAe,CAAC,CAAC;AAAA,EACjF,SAAS,QAAQ,KAAK,OAAO,oBAAoB,OAAO,QAAQ,MAAe,CAAC,CAAC;AAAA,EACjF,YAAY,OAAO,IAAI;AAAA,IACrB,OAAO,uBAAuB,CAAC;AAAA,IAC/B,OAAO,oBAAoB,eAAe;AAAA,EAC5C,EAAE,KAAK,OAAO,oBAAoB,OAAO,QAAQ,CAAC,CAAC,CAAC;AACtD,CAAC;AAsBM,MAAM,WAAW,CACtB,gBACmC,OAAO,GAAG,KAAK,MAAM,YAAY,MAAM,YAAY,QAAQ,GAAG,WAAW;AAQvG,MAAM,OAAO,CAAC,UACnB,OAAO,oBAAoB,QAAQ,EAAE,KAAK,EAAE;AAAA,EAC1C,OAAO,SAAS,CAAC,cAAU,qCAAgB,oBAAoB,mCAAmC,KAAK,CAAC;AAAA,EACxG,OAAO,QAAQ,QAAQ;AACzB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|