@shipfox/api-triggers 2.0.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/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-type$colon$emit.log +1 -0
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +224 -0
- package/LICENSE +21 -0
- package/README.md +300 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +42 -0
- package/dist/config.js.map +1 -0
- package/dist/core/compute-next-fire-at.d.ts +9 -0
- package/dist/core/compute-next-fire-at.d.ts.map +1 -0
- package/dist/core/compute-next-fire-at.js +28 -0
- package/dist/core/compute-next-fire-at.js.map +1 -0
- package/dist/core/config.d.ts +26 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +68 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/dispatch-integration-event.d.ts +14 -0
- package/dist/core/dispatch-integration-event.d.ts.map +1 -0
- package/dist/core/dispatch-integration-event.js +136 -0
- package/dist/core/dispatch-integration-event.js.map +1 -0
- package/dist/core/drain-cron-schedules.d.ts +30 -0
- package/dist/core/drain-cron-schedules.d.ts.map +1 -0
- package/dist/core/drain-cron-schedules.js +76 -0
- package/dist/core/drain-cron-schedules.js.map +1 -0
- package/dist/core/entities/cron-schedule.d.ts +11 -0
- package/dist/core/entities/cron-schedule.d.ts.map +1 -0
- package/dist/core/entities/cron-schedule.js +3 -0
- package/dist/core/entities/cron-schedule.js.map +1 -0
- package/dist/core/entities/decision.d.ts +23 -0
- package/dist/core/entities/decision.d.ts.map +1 -0
- package/dist/core/entities/decision.js +7 -0
- package/dist/core/entities/decision.js.map +1 -0
- package/dist/core/entities/index.d.ts +3 -0
- package/dist/core/entities/index.d.ts.map +1 -0
- package/dist/core/entities/index.js +3 -0
- package/dist/core/entities/index.js.map +1 -0
- package/dist/core/entities/job-listener-subscription.d.ts +14 -0
- package/dist/core/entities/job-listener-subscription.d.ts.map +1 -0
- package/dist/core/entities/job-listener-subscription.js +3 -0
- package/dist/core/entities/job-listener-subscription.js.map +1 -0
- package/dist/core/entities/received-event.d.ts +28 -0
- package/dist/core/entities/received-event.d.ts.map +1 -0
- package/dist/core/entities/received-event.js +14 -0
- package/dist/core/entities/received-event.js.map +1 -0
- package/dist/core/entities/subscription.d.ts +13 -0
- package/dist/core/entities/subscription.d.ts.map +1 -0
- package/dist/core/entities/subscription.js +3 -0
- package/dist/core/entities/subscription.js.map +1 -0
- package/dist/core/errors.d.ts +25 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +41 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/fire-cron.d.ts +28 -0
- package/dist/core/fire-cron.d.ts.map +1 -0
- package/dist/core/fire-cron.js +85 -0
- package/dist/core/fire-cron.js.map +1 -0
- package/dist/core/fire-manual.d.ts +9 -0
- package/dist/core/fire-manual.d.ts.map +1 -0
- package/dist/core/fire-manual.js +87 -0
- package/dist/core/fire-manual.js.map +1 -0
- package/dist/core/index.d.ts +11 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +10 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/record-trigger-history.d.ts +35 -0
- package/dist/core/record-trigger-history.d.ts.map +1 -0
- package/dist/core/record-trigger-history.js +75 -0
- package/dist/core/record-trigger-history.js.map +1 -0
- package/dist/core/route-event-to-job-listeners.d.ts +31 -0
- package/dist/core/route-event-to-job-listeners.d.ts.map +1 -0
- package/dist/core/route-event-to-job-listeners.js +140 -0
- package/dist/core/route-event-to-job-listeners.js.map +1 -0
- package/dist/db/cron-schedules.d.ts +36 -0
- package/dist/db/cron-schedules.d.ts.map +1 -0
- package/dist/db/cron-schedules.js +104 -0
- package/dist/db/cron-schedules.js.map +1 -0
- package/dist/db/db.d.ts +2515 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +28 -0
- package/dist/db/db.js.map +1 -0
- package/dist/db/event-history.d.ts +50 -0
- package/dist/db/event-history.d.ts.map +1 -0
- package/dist/db/event-history.js +207 -0
- package/dist/db/event-history.js.map +1 -0
- package/dist/db/event-queries.d.ts +38 -0
- package/dist/db/event-queries.d.ts.map +1 -0
- package/dist/db/event-queries.js +78 -0
- package/dist/db/event-queries.js.map +1 -0
- package/dist/db/index.d.ts +11 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +14 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/job-listener-subscriptions.d.ts +24 -0
- package/dist/db/job-listener-subscriptions.d.ts.map +1 -0
- package/dist/db/job-listener-subscriptions.js +69 -0
- package/dist/db/job-listener-subscriptions.js.map +1 -0
- package/dist/db/received-events.d.ts +7 -0
- package/dist/db/received-events.d.ts.map +1 -0
- package/dist/db/received-events.js +11 -0
- package/dist/db/received-events.js.map +1 -0
- package/dist/db/schema/common.d.ts +2 -0
- package/dist/db/schema/common.d.ts.map +1 -0
- package/dist/db/schema/common.js +4 -0
- package/dist/db/schema/common.js.map +1 -0
- package/dist/db/schema/cron-schedules.d.ts +148 -0
- package/dist/db/schema/cron-schedules.d.ts.map +1 -0
- package/dist/db/schema/cron-schedules.js +39 -0
- package/dist/db/schema/cron-schedules.js.map +1 -0
- package/dist/db/schema/decisions.d.ts +284 -0
- package/dist/db/schema/decisions.d.ts.map +1 -0
- package/dist/db/schema/decisions.js +70 -0
- package/dist/db/schema/decisions.js.map +1 -0
- package/dist/db/schema/job-listener-subscriptions.d.ts +185 -0
- package/dist/db/schema/job-listener-subscriptions.d.ts.map +1 -0
- package/dist/db/schema/job-listener-subscriptions.js +41 -0
- package/dist/db/schema/job-listener-subscriptions.js.map +1 -0
- package/dist/db/schema/outbox.d.ts +195 -0
- package/dist/db/schema/outbox.d.ts.map +1 -0
- package/dist/db/schema/outbox.js +5 -0
- package/dist/db/schema/outbox.js.map +1 -0
- package/dist/db/schema/received-events.d.ts +544 -0
- package/dist/db/schema/received-events.d.ts.map +1 -0
- package/dist/db/schema/received-events.js +86 -0
- package/dist/db/schema/received-events.js.map +1 -0
- package/dist/db/schema/subscriptions.d.ts +182 -0
- package/dist/db/schema/subscriptions.d.ts.map +1 -0
- package/dist/db/schema/subscriptions.js +39 -0
- package/dist/db/schema/subscriptions.js.map +1 -0
- package/dist/db/subscriptions.d.ts +26 -0
- package/dist/db/subscriptions.d.ts.map +1 -0
- package/dist/db/subscriptions.js +103 -0
- package/dist/db/subscriptions.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/metrics/index.d.ts +3 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +4 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/instance.d.ts +15 -0
- package/dist/metrics/instance.d.ts.map +1 -0
- package/dist/metrics/instance.js +32 -0
- package/dist/metrics/instance.js.map +1 -0
- package/dist/metrics/service.d.ts +2 -0
- package/dist/metrics/service.d.ts.map +1 -0
- package/dist/metrics/service.js +15 -0
- package/dist/metrics/service.js.map +1 -0
- package/dist/presentation/dto/trigger-events.d.ts +7 -0
- package/dist/presentation/dto/trigger-events.d.ts.map +1 -0
- package/dist/presentation/dto/trigger-events.js +47 -0
- package/dist/presentation/dto/trigger-events.js.map +1 -0
- package/dist/presentation/index.d.ts +3 -0
- package/dist/presentation/index.d.ts.map +1 -0
- package/dist/presentation/index.js +4 -0
- package/dist/presentation/index.js.map +1 -0
- package/dist/presentation/routes/fire-manual.d.ts +2 -0
- package/dist/presentation/routes/fire-manual.d.ts.map +1 -0
- package/dist/presentation/routes/fire-manual.js +71 -0
- package/dist/presentation/routes/fire-manual.js.map +1 -0
- package/dist/presentation/routes/get-trigger-event.d.ts +2 -0
- package/dist/presentation/routes/get-trigger-event.d.ts.map +1 -0
- package/dist/presentation/routes/get-trigger-event.js +37 -0
- package/dist/presentation/routes/get-trigger-event.js.map +1 -0
- package/dist/presentation/routes/index.d.ts +3 -0
- package/dist/presentation/routes/index.d.ts.map +1 -0
- package/dist/presentation/routes/index.js +27 -0
- package/dist/presentation/routes/index.js.map +1 -0
- package/dist/presentation/routes/list-trigger-event-facets.d.ts +2 -0
- package/dist/presentation/routes/list-trigger-event-facets.d.ts.map +1 -0
- package/dist/presentation/routes/list-trigger-event-facets.js +29 -0
- package/dist/presentation/routes/list-trigger-event-facets.js.map +1 -0
- package/dist/presentation/routes/list-trigger-events.d.ts +2 -0
- package/dist/presentation/routes/list-trigger-events.d.ts.map +1 -0
- package/dist/presentation/routes/list-trigger-events.js +56 -0
- package/dist/presentation/routes/list-trigger-events.js.map +1 -0
- package/dist/presentation/subscribers/index.d.ts +6 -0
- package/dist/presentation/subscribers/index.d.ts.map +1 -0
- package/dist/presentation/subscribers/index.js +7 -0
- package/dist/presentation/subscribers/index.js.map +1 -0
- package/dist/presentation/subscribers/on-definition-deleted.d.ts +3 -0
- package/dist/presentation/subscribers/on-definition-deleted.d.ts.map +1 -0
- package/dist/presentation/subscribers/on-definition-deleted.js +8 -0
- package/dist/presentation/subscribers/on-definition-deleted.js.map +1 -0
- package/dist/presentation/subscribers/on-definition-resolved.d.ts +3 -0
- package/dist/presentation/subscribers/on-definition-resolved.d.ts.map +1 -0
- package/dist/presentation/subscribers/on-definition-resolved.js +11 -0
- package/dist/presentation/subscribers/on-definition-resolved.js.map +1 -0
- package/dist/presentation/subscribers/on-integration-event-received.d.ts +4 -0
- package/dist/presentation/subscribers/on-integration-event-received.d.ts.map +1 -0
- package/dist/presentation/subscribers/on-integration-event-received.js +17 -0
- package/dist/presentation/subscribers/on-integration-event-received.js.map +1 -0
- package/dist/presentation/subscribers/on-job-activated.d.ts +3 -0
- package/dist/presentation/subscribers/on-job-activated.d.ts.map +1 -0
- package/dist/presentation/subscribers/on-job-activated.js +13 -0
- package/dist/presentation/subscribers/on-job-activated.js.map +1 -0
- package/dist/presentation/subscribers/on-job-terminated.d.ts +3 -0
- package/dist/presentation/subscribers/on-job-terminated.d.ts.map +1 -0
- package/dist/presentation/subscribers/on-job-terminated.js +6 -0
- package/dist/presentation/subscribers/on-job-terminated.js.map +1 -0
- package/dist/temporal/activities/drain-cron-batch.d.ts +4 -0
- package/dist/temporal/activities/drain-cron-batch.d.ts.map +1 -0
- package/dist/temporal/activities/drain-cron-batch.js +20 -0
- package/dist/temporal/activities/drain-cron-batch.js.map +1 -0
- package/dist/temporal/activities/index.d.ts +10 -0
- package/dist/temporal/activities/index.d.ts.map +1 -0
- package/dist/temporal/activities/index.js +15 -0
- package/dist/temporal/activities/index.js.map +1 -0
- package/dist/temporal/activities/prune-trigger-events.d.ts +4 -0
- package/dist/temporal/activities/prune-trigger-events.d.ts.map +1 -0
- package/dist/temporal/activities/prune-trigger-events.js +11 -0
- package/dist/temporal/activities/prune-trigger-events.js.map +1 -0
- package/dist/temporal/constants.d.ts +7 -0
- package/dist/temporal/constants.d.ts.map +1 -0
- package/dist/temporal/constants.js +7 -0
- package/dist/temporal/constants.js.map +1 -0
- package/dist/temporal/workflows/cron-tick-cron.d.ts +9 -0
- package/dist/temporal/workflows/cron-tick-cron.d.ts.map +1 -0
- package/dist/temporal/workflows/cron-tick-cron.js +54 -0
- package/dist/temporal/workflows/cron-tick-cron.js.map +1 -0
- package/dist/temporal/workflows/index.d.ts +3 -0
- package/dist/temporal/workflows/index.d.ts.map +1 -0
- package/dist/temporal/workflows/index.js +4 -0
- package/dist/temporal/workflows/index.js.map +1 -0
- package/dist/temporal/workflows/prune-trigger-events-cron.d.ts +2 -0
- package/dist/temporal/workflows/prune-trigger-events-cron.d.ts.map +1 -0
- package/dist/temporal/workflows/prune-trigger-events-cron.js +18 -0
- package/dist/temporal/workflows/prune-trigger-events-cron.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -0
- package/drizzle/0000_initial.sql +109 -0
- package/drizzle/meta/0000_snapshot.json +905 -0
- package/drizzle/meta/_journal.json +13 -0
- package/drizzle.config.ts +14 -0
- package/package.json +83 -0
- package/src/config.test.ts +33 -0
- package/src/config.ts +53 -0
- package/src/core/compute-next-fire-at.test.ts +69 -0
- package/src/core/compute-next-fire-at.ts +37 -0
- package/src/core/config.test.ts +213 -0
- package/src/core/config.ts +86 -0
- package/src/core/dispatch-integration-event.history-failure.test.ts +66 -0
- package/src/core/dispatch-integration-event.test.ts +1006 -0
- package/src/core/dispatch-integration-event.ts +150 -0
- package/src/core/drain-cron-schedules.test.ts +265 -0
- package/src/core/drain-cron-schedules.ts +90 -0
- package/src/core/entities/cron-schedule.ts +10 -0
- package/src/core/entities/decision.ts +24 -0
- package/src/core/entities/index.ts +5 -0
- package/src/core/entities/job-listener-subscription.ts +14 -0
- package/src/core/entities/received-event.ts +36 -0
- package/src/core/entities/subscription.ts +12 -0
- package/src/core/errors.ts +63 -0
- package/src/core/fire-cron.test.ts +146 -0
- package/src/core/fire-cron.ts +98 -0
- package/src/core/fire-manual.test.ts +157 -0
- package/src/core/fire-manual.ts +92 -0
- package/src/core/index.ts +34 -0
- package/src/core/record-trigger-history.test.ts +159 -0
- package/src/core/record-trigger-history.ts +145 -0
- package/src/core/route-event-to-job-listeners.test.ts +369 -0
- package/src/core/route-event-to-job-listeners.ts +184 -0
- package/src/db/cron-schedules.test.ts +358 -0
- package/src/db/cron-schedules.ts +163 -0
- package/src/db/db.ts +31 -0
- package/src/db/event-history.test.ts +421 -0
- package/src/db/event-history.ts +279 -0
- package/src/db/event-queries.ts +140 -0
- package/src/db/index.ts +51 -0
- package/src/db/job-listener-subscriptions.test.ts +270 -0
- package/src/db/job-listener-subscriptions.ts +133 -0
- package/src/db/received-events.ts +16 -0
- package/src/db/schema/common.ts +3 -0
- package/src/db/schema/cron-schedules.ts +37 -0
- package/src/db/schema/decisions.test.ts +279 -0
- package/src/db/schema/decisions.ts +77 -0
- package/src/db/schema/job-listener-subscriptions.ts +65 -0
- package/src/db/schema/outbox.ts +4 -0
- package/src/db/schema/received-events.test.ts +135 -0
- package/src/db/schema/received-events.ts +93 -0
- package/src/db/schema/subscriptions.ts +46 -0
- package/src/db/subscriptions.test.ts +340 -0
- package/src/db/subscriptions.ts +179 -0
- package/src/index.ts +108 -0
- package/src/metrics/index.ts +8 -0
- package/src/metrics/instance.ts +33 -0
- package/src/metrics/service.ts +18 -0
- package/src/presentation/dto/trigger-events.test.ts +144 -0
- package/src/presentation/dto/trigger-events.ts +60 -0
- package/src/presentation/index.ts +6 -0
- package/src/presentation/routes/fire-manual.test.ts +118 -0
- package/src/presentation/routes/fire-manual.ts +70 -0
- package/src/presentation/routes/get-trigger-event.test.ts +184 -0
- package/src/presentation/routes/get-trigger-event.ts +37 -0
- package/src/presentation/routes/index.ts +21 -0
- package/src/presentation/routes/list-trigger-event-facets.test.ts +116 -0
- package/src/presentation/routes/list-trigger-event-facets.ts +29 -0
- package/src/presentation/routes/list-trigger-events.test.ts +379 -0
- package/src/presentation/routes/list-trigger-events.ts +68 -0
- package/src/presentation/subscribers/index.ts +5 -0
- package/src/presentation/subscribers/on-definition-deleted.test.ts +42 -0
- package/src/presentation/subscribers/on-definition-deleted.ts +6 -0
- package/src/presentation/subscribers/on-definition-resolved.test.ts +67 -0
- package/src/presentation/subscribers/on-definition-resolved.ts +11 -0
- package/src/presentation/subscribers/on-integration-event-received.test.ts +53 -0
- package/src/presentation/subscribers/on-integration-event-received.ts +21 -0
- package/src/presentation/subscribers/on-job-activated.ts +14 -0
- package/src/presentation/subscribers/on-job-terminated.ts +6 -0
- package/src/temporal/activities/drain-cron-batch.ts +20 -0
- package/src/temporal/activities/index.ts +15 -0
- package/src/temporal/activities/prune-trigger-events.test.ts +78 -0
- package/src/temporal/activities/prune-trigger-events.ts +9 -0
- package/src/temporal/constants.ts +7 -0
- package/src/temporal/workflows/cron-tick-cron.ts +56 -0
- package/src/temporal/workflows/index.ts +2 -0
- package/src/temporal/workflows/prune-trigger-events-cron.ts +17 -0
- package/test/env.ts +8 -0
- package/test/factories/cron-schedule.ts +34 -0
- package/test/factories/decision.ts +49 -0
- package/test/factories/job-listener-subscription.ts +42 -0
- package/test/factories/received-event.ts +49 -0
- package/test/factories/subscription.ts +38 -0
- package/test/globalSetup.ts +20 -0
- package/test/index.ts +5 -0
- package/test/setup.ts +17 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +3 -0
- package/tsconfig.test.json +8 -0
- package/vitest.config.ts +11 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare class TriggerSubscriptionNotFoundError extends Error {
|
|
2
|
+
readonly subscriptionId: string;
|
|
3
|
+
constructor(subscriptionId: string);
|
|
4
|
+
}
|
|
5
|
+
export declare class ManualTriggerNotFoundError extends Error {
|
|
6
|
+
readonly workflowDefinitionId: string;
|
|
7
|
+
constructor(workflowDefinitionId: string);
|
|
8
|
+
}
|
|
9
|
+
export declare class TriggerSubscriptionNotManualError extends Error {
|
|
10
|
+
readonly subscriptionId: string;
|
|
11
|
+
readonly source: string;
|
|
12
|
+
constructor(subscriptionId: string, source: string);
|
|
13
|
+
}
|
|
14
|
+
export declare class TriggerSubscriptionNotCronError extends Error {
|
|
15
|
+
readonly subscriptionId: string;
|
|
16
|
+
readonly source: string;
|
|
17
|
+
constructor(subscriptionId: string, source: string);
|
|
18
|
+
}
|
|
19
|
+
export declare class TriggerWorkspaceMismatchError extends Error {
|
|
20
|
+
readonly subscriptionId: string;
|
|
21
|
+
readonly subscriptionWorkspaceId: string;
|
|
22
|
+
readonly callerWorkspaceId: string;
|
|
23
|
+
constructor(subscriptionId: string, subscriptionWorkspaceId: string, callerWorkspaceId: string);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,gCAAiC,SAAQ,KAAK;IACzD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;gBAEpB,cAAc,EAAE,MAAM;CAKnC;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;gBAE1B,oBAAoB,EAAE,MAAM;CAKzC;AAED,qBAAa,iCAAkC,SAAQ,KAAK;IAC1D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAQnD;AAED,qBAAa,+BAAgC,SAAQ,KAAK;IACxD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAQnD;AAED,qBAAa,6BAA8B,SAAQ,KAAK;IACtD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IACzC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;gBAEvB,cAAc,EAAE,MAAM,EAAE,uBAAuB,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM;CAS/F"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export class TriggerSubscriptionNotFoundError extends Error {
|
|
2
|
+
constructor(subscriptionId){
|
|
3
|
+
super(`Trigger subscription not found: ${subscriptionId}`);
|
|
4
|
+
this.name = 'TriggerSubscriptionNotFoundError';
|
|
5
|
+
this.subscriptionId = subscriptionId;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export class ManualTriggerNotFoundError extends Error {
|
|
9
|
+
constructor(workflowDefinitionId){
|
|
10
|
+
super(`Workflow definition ${workflowDefinitionId} has no manual trigger`);
|
|
11
|
+
this.name = 'ManualTriggerNotFoundError';
|
|
12
|
+
this.workflowDefinitionId = workflowDefinitionId;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export class TriggerSubscriptionNotManualError extends Error {
|
|
16
|
+
constructor(subscriptionId, source){
|
|
17
|
+
super(`Trigger subscription ${subscriptionId} has source '${source}', expected 'manual' for manual fire`);
|
|
18
|
+
this.name = 'TriggerSubscriptionNotManualError';
|
|
19
|
+
this.subscriptionId = subscriptionId;
|
|
20
|
+
this.source = source;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export class TriggerSubscriptionNotCronError extends Error {
|
|
24
|
+
constructor(subscriptionId, source){
|
|
25
|
+
super(`Trigger subscription ${subscriptionId} has source '${source}', expected 'cron' for cron fire`);
|
|
26
|
+
this.name = 'TriggerSubscriptionNotCronError';
|
|
27
|
+
this.subscriptionId = subscriptionId;
|
|
28
|
+
this.source = source;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export class TriggerWorkspaceMismatchError extends Error {
|
|
32
|
+
constructor(subscriptionId, subscriptionWorkspaceId, callerWorkspaceId){
|
|
33
|
+
super(`Trigger subscription ${subscriptionId} belongs to workspace ${subscriptionWorkspaceId}, not ${callerWorkspaceId}`);
|
|
34
|
+
this.name = 'TriggerWorkspaceMismatchError';
|
|
35
|
+
this.subscriptionId = subscriptionId;
|
|
36
|
+
this.subscriptionWorkspaceId = subscriptionWorkspaceId;
|
|
37
|
+
this.callerWorkspaceId = callerWorkspaceId;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/errors.ts"],"sourcesContent":["export class TriggerSubscriptionNotFoundError extends Error {\n readonly subscriptionId: string;\n\n constructor(subscriptionId: string) {\n super(`Trigger subscription not found: ${subscriptionId}`);\n this.name = 'TriggerSubscriptionNotFoundError';\n this.subscriptionId = subscriptionId;\n }\n}\n\nexport class ManualTriggerNotFoundError extends Error {\n readonly workflowDefinitionId: string;\n\n constructor(workflowDefinitionId: string) {\n super(`Workflow definition ${workflowDefinitionId} has no manual trigger`);\n this.name = 'ManualTriggerNotFoundError';\n this.workflowDefinitionId = workflowDefinitionId;\n }\n}\n\nexport class TriggerSubscriptionNotManualError extends Error {\n readonly subscriptionId: string;\n readonly source: string;\n\n constructor(subscriptionId: string, source: string) {\n super(\n `Trigger subscription ${subscriptionId} has source '${source}', expected 'manual' for manual fire`,\n );\n this.name = 'TriggerSubscriptionNotManualError';\n this.subscriptionId = subscriptionId;\n this.source = source;\n }\n}\n\nexport class TriggerSubscriptionNotCronError extends Error {\n readonly subscriptionId: string;\n readonly source: string;\n\n constructor(subscriptionId: string, source: string) {\n super(\n `Trigger subscription ${subscriptionId} has source '${source}', expected 'cron' for cron fire`,\n );\n this.name = 'TriggerSubscriptionNotCronError';\n this.subscriptionId = subscriptionId;\n this.source = source;\n }\n}\n\nexport class TriggerWorkspaceMismatchError extends Error {\n readonly subscriptionId: string;\n readonly subscriptionWorkspaceId: string;\n readonly callerWorkspaceId: string;\n\n constructor(subscriptionId: string, subscriptionWorkspaceId: string, callerWorkspaceId: string) {\n super(\n `Trigger subscription ${subscriptionId} belongs to workspace ${subscriptionWorkspaceId}, not ${callerWorkspaceId}`,\n );\n this.name = 'TriggerWorkspaceMismatchError';\n this.subscriptionId = subscriptionId;\n this.subscriptionWorkspaceId = subscriptionWorkspaceId;\n this.callerWorkspaceId = callerWorkspaceId;\n }\n}\n"],"names":["TriggerSubscriptionNotFoundError","Error","subscriptionId","name","ManualTriggerNotFoundError","workflowDefinitionId","TriggerSubscriptionNotManualError","source","TriggerSubscriptionNotCronError","TriggerWorkspaceMismatchError","subscriptionWorkspaceId","callerWorkspaceId"],"mappings":"AAAA,OAAO,MAAMA,yCAAyCC;IAGpD,YAAYC,cAAsB,CAAE;QAClC,KAAK,CAAC,CAAC,gCAAgC,EAAEA,gBAAgB;QACzD,IAAI,CAACC,IAAI,GAAG;QACZ,IAAI,CAACD,cAAc,GAAGA;IACxB;AACF;AAEA,OAAO,MAAME,mCAAmCH;IAG9C,YAAYI,oBAA4B,CAAE;QACxC,KAAK,CAAC,CAAC,oBAAoB,EAAEA,qBAAqB,sBAAsB,CAAC;QACzE,IAAI,CAACF,IAAI,GAAG;QACZ,IAAI,CAACE,oBAAoB,GAAGA;IAC9B;AACF;AAEA,OAAO,MAAMC,0CAA0CL;IAIrD,YAAYC,cAAsB,EAAEK,MAAc,CAAE;QAClD,KAAK,CACH,CAAC,qBAAqB,EAAEL,eAAe,aAAa,EAAEK,OAAO,oCAAoC,CAAC;QAEpG,IAAI,CAACJ,IAAI,GAAG;QACZ,IAAI,CAACD,cAAc,GAAGA;QACtB,IAAI,CAACK,MAAM,GAAGA;IAChB;AACF;AAEA,OAAO,MAAMC,wCAAwCP;IAInD,YAAYC,cAAsB,EAAEK,MAAc,CAAE;QAClD,KAAK,CACH,CAAC,qBAAqB,EAAEL,eAAe,aAAa,EAAEK,OAAO,gCAAgC,CAAC;QAEhG,IAAI,CAACJ,IAAI,GAAG;QACZ,IAAI,CAACD,cAAc,GAAGA;QACtB,IAAI,CAACK,MAAM,GAAGA;IAChB;AACF;AAEA,OAAO,MAAME,sCAAsCR;IAKjD,YAAYC,cAAsB,EAAEQ,uBAA+B,EAAEC,iBAAyB,CAAE;QAC9F,KAAK,CACH,CAAC,qBAAqB,EAAET,eAAe,sBAAsB,EAAEQ,wBAAwB,MAAM,EAAEC,mBAAmB;QAEpH,IAAI,CAACR,IAAI,GAAG;QACZ,IAAI,CAACD,cAAc,GAAGA;QACtB,IAAI,CAACQ,uBAAuB,GAAGA;QAC/B,IAAI,CAACC,iBAAiB,GAAGA;IAC3B;AACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type WorkflowRun } from '@shipfox/api-workflows';
|
|
2
|
+
export interface FireCronSubscriptionParams {
|
|
3
|
+
subscriptionId: string;
|
|
4
|
+
/**
|
|
5
|
+
* The `next_fire_at` value the schedule held when it was claimed. Anchoring the
|
|
6
|
+
* idempotency key and history `event_ref` on this slot, rather than wall-clock
|
|
7
|
+
* time, makes a retry of the same occurrence a deterministic no-op.
|
|
8
|
+
*/
|
|
9
|
+
scheduledSlot: Date;
|
|
10
|
+
}
|
|
11
|
+
export type FireCronSubscriptionResult = {
|
|
12
|
+
outcome: 'fired';
|
|
13
|
+
run: WorkflowRun;
|
|
14
|
+
} | {
|
|
15
|
+
outcome: 'errored';
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Fires one cron schedule occurrence. Mirrors `fireManualSubscription`, but is driven
|
|
19
|
+
* by the drain activity rather than an HTTP route, and reports the outcome instead of
|
|
20
|
+
* throwing on a permanent failure so the caller can advance the schedule past a
|
|
21
|
+
* permanently broken definition:
|
|
22
|
+
*
|
|
23
|
+
* - `{outcome: 'fired'}` on success (or an idempotent replay of an already-created run),
|
|
24
|
+
* - `{outcome: 'errored'}` on a permanent `runWorkflow` failure (recorded, schedule advances),
|
|
25
|
+
* - throws on a transient failure so the caller rolls back the advance and retries.
|
|
26
|
+
*/
|
|
27
|
+
export declare function fireCronSubscription(params: FireCronSubscriptionParams): Promise<FireCronSubscriptionResult>;
|
|
28
|
+
//# sourceMappingURL=fire-cron.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fire-cron.d.ts","sourceRoot":"","sources":["../../src/core/fire-cron.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,KAAK,WAAW,EAAC,MAAM,wBAAwB,CAAC;AAOlG,MAAM,WAAW,0BAA0B;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,aAAa,EAAE,IAAI,CAAC;CACrB;AAED,MAAM,MAAM,0BAA0B,GAClC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,WAAW,CAAA;CAAC,GACpC;IAAC,OAAO,EAAE,SAAS,CAAA;CAAC,CAAC;AAEzB;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC,0BAA0B,CAAC,CA2DrC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { isPermanentRunWorkflowError, runWorkflow } from '@shipfox/api-workflows';
|
|
2
|
+
import { getTriggerSubscriptionById } from '#db/subscriptions.js';
|
|
3
|
+
import { cronFiredCount, cronFireLag } from '#metrics/instance.js';
|
|
4
|
+
import { readConfigInputs } from './config.js';
|
|
5
|
+
import { TriggerSubscriptionNotCronError, TriggerSubscriptionNotFoundError } from './errors.js';
|
|
6
|
+
import { beginTriggerHistory, toReason } from './record-trigger-history.js';
|
|
7
|
+
/**
|
|
8
|
+
* Fires one cron schedule occurrence. Mirrors `fireManualSubscription`, but is driven
|
|
9
|
+
* by the drain activity rather than an HTTP route, and reports the outcome instead of
|
|
10
|
+
* throwing on a permanent failure so the caller can advance the schedule past a
|
|
11
|
+
* permanently broken definition:
|
|
12
|
+
*
|
|
13
|
+
* - `{outcome: 'fired'}` on success (or an idempotent replay of an already-created run),
|
|
14
|
+
* - `{outcome: 'errored'}` on a permanent `runWorkflow` failure (recorded, schedule advances),
|
|
15
|
+
* - throws on a transient failure so the caller rolls back the advance and retries.
|
|
16
|
+
*/ export async function fireCronSubscription(params) {
|
|
17
|
+
const subscription = await getTriggerSubscriptionById(params.subscriptionId);
|
|
18
|
+
if (!subscription) throw new TriggerSubscriptionNotFoundError(params.subscriptionId);
|
|
19
|
+
if (subscription.source !== 'cron') {
|
|
20
|
+
throw new TriggerSubscriptionNotCronError(params.subscriptionId, subscription.source);
|
|
21
|
+
}
|
|
22
|
+
// Deterministic per-occurrence identity: unique across (subscription, slot), stable
|
|
23
|
+
// across retries. Used for both the run idempotency key and the received-event ref.
|
|
24
|
+
const eventRef = `${subscription.id}:${params.scheduledSlot.toISOString()}`;
|
|
25
|
+
const historyBase = {
|
|
26
|
+
origin: 'cron',
|
|
27
|
+
workspaceId: subscription.workspaceId,
|
|
28
|
+
provider: null,
|
|
29
|
+
source: subscription.source,
|
|
30
|
+
event: subscription.event,
|
|
31
|
+
deliveryId: null,
|
|
32
|
+
connectionId: null,
|
|
33
|
+
connectionName: null,
|
|
34
|
+
payload: null,
|
|
35
|
+
// The scheduled occurrence is the logical arrival time of the tick event.
|
|
36
|
+
receivedAt: params.scheduledSlot,
|
|
37
|
+
eventRef
|
|
38
|
+
};
|
|
39
|
+
let run;
|
|
40
|
+
try {
|
|
41
|
+
run = await runWorkflow({
|
|
42
|
+
workspaceId: subscription.workspaceId,
|
|
43
|
+
projectId: subscription.projectId,
|
|
44
|
+
definitionId: subscription.workflowDefinitionId,
|
|
45
|
+
triggerPayload: {
|
|
46
|
+
provider: 'cron',
|
|
47
|
+
source: 'cron',
|
|
48
|
+
event: 'tick',
|
|
49
|
+
scheduleId: subscription.id
|
|
50
|
+
},
|
|
51
|
+
inputs: readConfigInputs(subscription),
|
|
52
|
+
triggerIdempotencyKey: eventRef
|
|
53
|
+
});
|
|
54
|
+
} catch (error) {
|
|
55
|
+
const failure = await beginTriggerHistory(historyBase);
|
|
56
|
+
await failure.dispatchErrored(subscription, toReason(error));
|
|
57
|
+
if (isPermanentRunWorkflowError(error)) {
|
|
58
|
+
recordFire('errored', params.scheduledSlot);
|
|
59
|
+
await failure.allErrored(1);
|
|
60
|
+
return {
|
|
61
|
+
outcome: 'errored'
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// Transient: leave the event non-terminal and re-throw so the caller rolls back
|
|
65
|
+
// the advance and the schedule stays due for the next tick.
|
|
66
|
+
await failure.failed(1);
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
const history = await beginTriggerHistory(historyBase);
|
|
70
|
+
await history.triggered(subscription, run);
|
|
71
|
+
recordFire('fired', params.scheduledSlot);
|
|
72
|
+
await history.routed(1);
|
|
73
|
+
return {
|
|
74
|
+
outcome: 'fired',
|
|
75
|
+
run
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function recordFire(outcome, scheduledSlot) {
|
|
79
|
+
cronFiredCount.add(1, {
|
|
80
|
+
outcome
|
|
81
|
+
});
|
|
82
|
+
cronFireLag.record(Math.max(0, Date.now() - scheduledSlot.getTime()));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
//# sourceMappingURL=fire-cron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/fire-cron.ts"],"sourcesContent":["import {isPermanentRunWorkflowError, runWorkflow, type WorkflowRun} from '@shipfox/api-workflows';\nimport {getTriggerSubscriptionById} from '#db/subscriptions.js';\nimport {cronFiredCount, cronFireLag} from '#metrics/instance.js';\nimport {readConfigInputs} from './config.js';\nimport {TriggerSubscriptionNotCronError, TriggerSubscriptionNotFoundError} from './errors.js';\nimport {beginTriggerHistory, toReason} from './record-trigger-history.js';\n\nexport interface FireCronSubscriptionParams {\n subscriptionId: string;\n /**\n * The `next_fire_at` value the schedule held when it was claimed. Anchoring the\n * idempotency key and history `event_ref` on this slot, rather than wall-clock\n * time, makes a retry of the same occurrence a deterministic no-op.\n */\n scheduledSlot: Date;\n}\n\nexport type FireCronSubscriptionResult =\n | {outcome: 'fired'; run: WorkflowRun}\n | {outcome: 'errored'};\n\n/**\n * Fires one cron schedule occurrence. Mirrors `fireManualSubscription`, but is driven\n * by the drain activity rather than an HTTP route, and reports the outcome instead of\n * throwing on a permanent failure so the caller can advance the schedule past a\n * permanently broken definition:\n *\n * - `{outcome: 'fired'}` on success (or an idempotent replay of an already-created run),\n * - `{outcome: 'errored'}` on a permanent `runWorkflow` failure (recorded, schedule advances),\n * - throws on a transient failure so the caller rolls back the advance and retries.\n */\nexport async function fireCronSubscription(\n params: FireCronSubscriptionParams,\n): Promise<FireCronSubscriptionResult> {\n const subscription = await getTriggerSubscriptionById(params.subscriptionId);\n if (!subscription) throw new TriggerSubscriptionNotFoundError(params.subscriptionId);\n if (subscription.source !== 'cron') {\n throw new TriggerSubscriptionNotCronError(params.subscriptionId, subscription.source);\n }\n\n // Deterministic per-occurrence identity: unique across (subscription, slot), stable\n // across retries. Used for both the run idempotency key and the received-event ref.\n const eventRef = `${subscription.id}:${params.scheduledSlot.toISOString()}`;\n const historyBase = {\n origin: 'cron' as const,\n workspaceId: subscription.workspaceId,\n provider: null,\n source: subscription.source,\n event: subscription.event,\n deliveryId: null,\n connectionId: null,\n connectionName: null,\n payload: null,\n // The scheduled occurrence is the logical arrival time of the tick event.\n receivedAt: params.scheduledSlot,\n eventRef,\n };\n\n let run: WorkflowRun;\n try {\n run = await runWorkflow({\n workspaceId: subscription.workspaceId,\n projectId: subscription.projectId,\n definitionId: subscription.workflowDefinitionId,\n triggerPayload: {\n provider: 'cron',\n source: 'cron',\n event: 'tick',\n scheduleId: subscription.id,\n },\n inputs: readConfigInputs(subscription),\n triggerIdempotencyKey: eventRef,\n });\n } catch (error) {\n const failure = await beginTriggerHistory(historyBase);\n await failure.dispatchErrored(subscription, toReason(error));\n if (isPermanentRunWorkflowError(error)) {\n recordFire('errored', params.scheduledSlot);\n await failure.allErrored(1);\n return {outcome: 'errored'};\n }\n // Transient: leave the event non-terminal and re-throw so the caller rolls back\n // the advance and the schedule stays due for the next tick.\n await failure.failed(1);\n throw error;\n }\n\n const history = await beginTriggerHistory(historyBase);\n await history.triggered(subscription, run);\n recordFire('fired', params.scheduledSlot);\n await history.routed(1);\n return {outcome: 'fired', run};\n}\n\nfunction recordFire(outcome: 'fired' | 'errored', scheduledSlot: Date): void {\n cronFiredCount.add(1, {outcome});\n cronFireLag.record(Math.max(0, Date.now() - scheduledSlot.getTime()));\n}\n"],"names":["isPermanentRunWorkflowError","runWorkflow","getTriggerSubscriptionById","cronFiredCount","cronFireLag","readConfigInputs","TriggerSubscriptionNotCronError","TriggerSubscriptionNotFoundError","beginTriggerHistory","toReason","fireCronSubscription","params","subscription","subscriptionId","source","eventRef","id","scheduledSlot","toISOString","historyBase","origin","workspaceId","provider","event","deliveryId","connectionId","connectionName","payload","receivedAt","run","projectId","definitionId","workflowDefinitionId","triggerPayload","scheduleId","inputs","triggerIdempotencyKey","error","failure","dispatchErrored","recordFire","allErrored","outcome","failed","history","triggered","routed","add","record","Math","max","Date","now","getTime"],"mappings":"AAAA,SAAQA,2BAA2B,EAAEC,WAAW,QAAyB,yBAAyB;AAClG,SAAQC,0BAA0B,QAAO,uBAAuB;AAChE,SAAQC,cAAc,EAAEC,WAAW,QAAO,uBAAuB;AACjE,SAAQC,gBAAgB,QAAO,cAAc;AAC7C,SAAQC,+BAA+B,EAAEC,gCAAgC,QAAO,cAAc;AAC9F,SAAQC,mBAAmB,EAAEC,QAAQ,QAAO,8BAA8B;AAgB1E;;;;;;;;;CASC,GACD,OAAO,eAAeC,qBACpBC,MAAkC;IAElC,MAAMC,eAAe,MAAMV,2BAA2BS,OAAOE,cAAc;IAC3E,IAAI,CAACD,cAAc,MAAM,IAAIL,iCAAiCI,OAAOE,cAAc;IACnF,IAAID,aAAaE,MAAM,KAAK,QAAQ;QAClC,MAAM,IAAIR,gCAAgCK,OAAOE,cAAc,EAAED,aAAaE,MAAM;IACtF;IAEA,oFAAoF;IACpF,oFAAoF;IACpF,MAAMC,WAAW,GAAGH,aAAaI,EAAE,CAAC,CAAC,EAAEL,OAAOM,aAAa,CAACC,WAAW,IAAI;IAC3E,MAAMC,cAAc;QAClBC,QAAQ;QACRC,aAAaT,aAAaS,WAAW;QACrCC,UAAU;QACVR,QAAQF,aAAaE,MAAM;QAC3BS,OAAOX,aAAaW,KAAK;QACzBC,YAAY;QACZC,cAAc;QACdC,gBAAgB;QAChBC,SAAS;QACT,0EAA0E;QAC1EC,YAAYjB,OAAOM,aAAa;QAChCF;IACF;IAEA,IAAIc;IACJ,IAAI;QACFA,MAAM,MAAM5B,YAAY;YACtBoB,aAAaT,aAAaS,WAAW;YACrCS,WAAWlB,aAAakB,SAAS;YACjCC,cAAcnB,aAAaoB,oBAAoB;YAC/CC,gBAAgB;gBACdX,UAAU;gBACVR,QAAQ;gBACRS,OAAO;gBACPW,YAAYtB,aAAaI,EAAE;YAC7B;YACAmB,QAAQ9B,iBAAiBO;YACzBwB,uBAAuBrB;QACzB;IACF,EAAE,OAAOsB,OAAO;QACd,MAAMC,UAAU,MAAM9B,oBAAoBW;QAC1C,MAAMmB,QAAQC,eAAe,CAAC3B,cAAcH,SAAS4B;QACrD,IAAIrC,4BAA4BqC,QAAQ;YACtCG,WAAW,WAAW7B,OAAOM,aAAa;YAC1C,MAAMqB,QAAQG,UAAU,CAAC;YACzB,OAAO;gBAACC,SAAS;YAAS;QAC5B;QACA,gFAAgF;QAChF,4DAA4D;QAC5D,MAAMJ,QAAQK,MAAM,CAAC;QACrB,MAAMN;IACR;IAEA,MAAMO,UAAU,MAAMpC,oBAAoBW;IAC1C,MAAMyB,QAAQC,SAAS,CAACjC,cAAciB;IACtCW,WAAW,SAAS7B,OAAOM,aAAa;IACxC,MAAM2B,QAAQE,MAAM,CAAC;IACrB,OAAO;QAACJ,SAAS;QAASb;IAAG;AAC/B;AAEA,SAASW,WAAWE,OAA4B,EAAEzB,aAAmB;IACnEd,eAAe4C,GAAG,CAAC,GAAG;QAACL;IAAO;IAC9BtC,YAAY4C,MAAM,CAACC,KAAKC,GAAG,CAAC,GAAGC,KAAKC,GAAG,KAAKnC,cAAcoC,OAAO;AACnE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type WorkflowRun } from '@shipfox/api-workflows';
|
|
2
|
+
export interface FireManualSubscriptionParams {
|
|
3
|
+
subscriptionId: string;
|
|
4
|
+
callerWorkspaceId: string;
|
|
5
|
+
userId: string;
|
|
6
|
+
inputs?: Record<string, unknown> | undefined;
|
|
7
|
+
}
|
|
8
|
+
export declare function fireManualSubscription(params: FireManualSubscriptionParams): Promise<WorkflowRun>;
|
|
9
|
+
//# sourceMappingURL=fire-manual.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fire-manual.d.ts","sourceRoot":"","sources":["../../src/core/fire-manual.ts"],"names":[],"mappings":"AACA,OAAO,EAA2C,KAAK,WAAW,EAAC,MAAM,wBAAwB,CAAC;AAelG,MAAM,WAAW,4BAA4B;IAC3C,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CAC9C;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC,WAAW,CAAC,CAkEtB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { isPermanentRunWorkflowError, runWorkflow } from '@shipfox/api-workflows';
|
|
3
|
+
import { getTriggerSubscriptionById } from '#db/subscriptions.js';
|
|
4
|
+
import { eventOutcomeCount, eventReceivedCount, subscriptionTriggeredCount } from '#metrics/instance.js';
|
|
5
|
+
import { readConfigInputs } from './config.js';
|
|
6
|
+
import { TriggerSubscriptionNotFoundError, TriggerSubscriptionNotManualError, TriggerWorkspaceMismatchError } from './errors.js';
|
|
7
|
+
import { beginTriggerHistory, toReason } from './record-trigger-history.js';
|
|
8
|
+
export async function fireManualSubscription(params) {
|
|
9
|
+
const subscription = await getTriggerSubscriptionById(params.subscriptionId);
|
|
10
|
+
if (!subscription) throw new TriggerSubscriptionNotFoundError(params.subscriptionId);
|
|
11
|
+
if (subscription.source !== 'manual') {
|
|
12
|
+
throw new TriggerSubscriptionNotManualError(params.subscriptionId, subscription.source);
|
|
13
|
+
}
|
|
14
|
+
// Defence in depth: unreachable from the HTTP route, but required for any direct caller.
|
|
15
|
+
if (subscription.workspaceId !== params.callerWorkspaceId) {
|
|
16
|
+
throw new TriggerWorkspaceMismatchError(params.subscriptionId, subscription.workspaceId, params.callerWorkspaceId);
|
|
17
|
+
}
|
|
18
|
+
// Manual fires have no upstream event id. Use the run id after success; failed
|
|
19
|
+
// attempts need a synthesized ref because there is no run to key on.
|
|
20
|
+
const historyBase = {
|
|
21
|
+
origin: 'manual',
|
|
22
|
+
workspaceId: subscription.workspaceId,
|
|
23
|
+
provider: null,
|
|
24
|
+
source: subscription.source,
|
|
25
|
+
event: subscription.event,
|
|
26
|
+
deliveryId: null,
|
|
27
|
+
connectionId: null,
|
|
28
|
+
connectionName: null,
|
|
29
|
+
payload: null,
|
|
30
|
+
receivedAt: new Date()
|
|
31
|
+
};
|
|
32
|
+
eventReceivedCount.add(1, {
|
|
33
|
+
provider: 'manual'
|
|
34
|
+
});
|
|
35
|
+
let run;
|
|
36
|
+
try {
|
|
37
|
+
run = await runWorkflow({
|
|
38
|
+
workspaceId: subscription.workspaceId,
|
|
39
|
+
projectId: subscription.projectId,
|
|
40
|
+
definitionId: subscription.workflowDefinitionId,
|
|
41
|
+
triggerPayload: {
|
|
42
|
+
provider: 'manual',
|
|
43
|
+
source: 'manual',
|
|
44
|
+
event: 'fire',
|
|
45
|
+
subscriptionId: subscription.id,
|
|
46
|
+
userId: params.userId
|
|
47
|
+
},
|
|
48
|
+
inputs: params.inputs ?? readConfigInputs(subscription)
|
|
49
|
+
});
|
|
50
|
+
} catch (error) {
|
|
51
|
+
const failure = await beginTriggerHistory({
|
|
52
|
+
...historyBase,
|
|
53
|
+
eventRef: randomUUID()
|
|
54
|
+
});
|
|
55
|
+
await failure.dispatchErrored(subscription, toReason(error));
|
|
56
|
+
if (isPermanentRunWorkflowError(error)) {
|
|
57
|
+
eventOutcomeCount.add(1, {
|
|
58
|
+
provider: 'manual',
|
|
59
|
+
outcome: 'errored'
|
|
60
|
+
});
|
|
61
|
+
await failure.allErrored(1);
|
|
62
|
+
} else {
|
|
63
|
+
eventOutcomeCount.add(1, {
|
|
64
|
+
provider: 'manual',
|
|
65
|
+
outcome: 'failed'
|
|
66
|
+
});
|
|
67
|
+
await failure.failed(1);
|
|
68
|
+
}
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
const history = await beginTriggerHistory({
|
|
72
|
+
...historyBase,
|
|
73
|
+
eventRef: run.id
|
|
74
|
+
});
|
|
75
|
+
await history.triggered(subscription, run);
|
|
76
|
+
subscriptionTriggeredCount.add(1, {
|
|
77
|
+
provider: 'manual'
|
|
78
|
+
});
|
|
79
|
+
eventOutcomeCount.add(1, {
|
|
80
|
+
provider: 'manual',
|
|
81
|
+
outcome: 'routed'
|
|
82
|
+
});
|
|
83
|
+
await history.routed(1);
|
|
84
|
+
return run;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=fire-manual.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/fire-manual.ts"],"sourcesContent":["import {randomUUID} from 'node:crypto';\nimport {isPermanentRunWorkflowError, runWorkflow, type WorkflowRun} from '@shipfox/api-workflows';\nimport {getTriggerSubscriptionById} from '#db/subscriptions.js';\nimport {\n eventOutcomeCount,\n eventReceivedCount,\n subscriptionTriggeredCount,\n} from '#metrics/instance.js';\nimport {readConfigInputs} from './config.js';\nimport {\n TriggerSubscriptionNotFoundError,\n TriggerSubscriptionNotManualError,\n TriggerWorkspaceMismatchError,\n} from './errors.js';\nimport {beginTriggerHistory, toReason} from './record-trigger-history.js';\n\nexport interface FireManualSubscriptionParams {\n subscriptionId: string;\n callerWorkspaceId: string;\n userId: string;\n inputs?: Record<string, unknown> | undefined;\n}\n\nexport async function fireManualSubscription(\n params: FireManualSubscriptionParams,\n): Promise<WorkflowRun> {\n const subscription = await getTriggerSubscriptionById(params.subscriptionId);\n if (!subscription) throw new TriggerSubscriptionNotFoundError(params.subscriptionId);\n if (subscription.source !== 'manual') {\n throw new TriggerSubscriptionNotManualError(params.subscriptionId, subscription.source);\n }\n // Defence in depth: unreachable from the HTTP route, but required for any direct caller.\n if (subscription.workspaceId !== params.callerWorkspaceId) {\n throw new TriggerWorkspaceMismatchError(\n params.subscriptionId,\n subscription.workspaceId,\n params.callerWorkspaceId,\n );\n }\n\n // Manual fires have no upstream event id. Use the run id after success; failed\n // attempts need a synthesized ref because there is no run to key on.\n const historyBase = {\n origin: 'manual' as const,\n workspaceId: subscription.workspaceId,\n provider: null,\n source: subscription.source,\n event: subscription.event,\n deliveryId: null,\n connectionId: null,\n connectionName: null,\n payload: null,\n receivedAt: new Date(),\n };\n\n eventReceivedCount.add(1, {provider: 'manual'});\n\n let run: WorkflowRun;\n try {\n run = await runWorkflow({\n workspaceId: subscription.workspaceId,\n projectId: subscription.projectId,\n definitionId: subscription.workflowDefinitionId,\n triggerPayload: {\n provider: 'manual',\n source: 'manual',\n event: 'fire',\n subscriptionId: subscription.id,\n userId: params.userId,\n },\n inputs: params.inputs ?? readConfigInputs(subscription),\n });\n } catch (error) {\n const failure = await beginTriggerHistory({...historyBase, eventRef: randomUUID()});\n await failure.dispatchErrored(subscription, toReason(error));\n if (isPermanentRunWorkflowError(error)) {\n eventOutcomeCount.add(1, {provider: 'manual', outcome: 'errored'});\n await failure.allErrored(1);\n } else {\n eventOutcomeCount.add(1, {provider: 'manual', outcome: 'failed'});\n await failure.failed(1);\n }\n throw error;\n }\n\n const history = await beginTriggerHistory({...historyBase, eventRef: run.id});\n await history.triggered(subscription, run);\n subscriptionTriggeredCount.add(1, {provider: 'manual'});\n eventOutcomeCount.add(1, {provider: 'manual', outcome: 'routed'});\n await history.routed(1);\n return run;\n}\n"],"names":["randomUUID","isPermanentRunWorkflowError","runWorkflow","getTriggerSubscriptionById","eventOutcomeCount","eventReceivedCount","subscriptionTriggeredCount","readConfigInputs","TriggerSubscriptionNotFoundError","TriggerSubscriptionNotManualError","TriggerWorkspaceMismatchError","beginTriggerHistory","toReason","fireManualSubscription","params","subscription","subscriptionId","source","workspaceId","callerWorkspaceId","historyBase","origin","provider","event","deliveryId","connectionId","connectionName","payload","receivedAt","Date","add","run","projectId","definitionId","workflowDefinitionId","triggerPayload","id","userId","inputs","error","failure","eventRef","dispatchErrored","outcome","allErrored","failed","history","triggered","routed"],"mappings":"AAAA,SAAQA,UAAU,QAAO,cAAc;AACvC,SAAQC,2BAA2B,EAAEC,WAAW,QAAyB,yBAAyB;AAClG,SAAQC,0BAA0B,QAAO,uBAAuB;AAChE,SACEC,iBAAiB,EACjBC,kBAAkB,EAClBC,0BAA0B,QACrB,uBAAuB;AAC9B,SAAQC,gBAAgB,QAAO,cAAc;AAC7C,SACEC,gCAAgC,EAChCC,iCAAiC,EACjCC,6BAA6B,QACxB,cAAc;AACrB,SAAQC,mBAAmB,EAAEC,QAAQ,QAAO,8BAA8B;AAS1E,OAAO,eAAeC,uBACpBC,MAAoC;IAEpC,MAAMC,eAAe,MAAMZ,2BAA2BW,OAAOE,cAAc;IAC3E,IAAI,CAACD,cAAc,MAAM,IAAIP,iCAAiCM,OAAOE,cAAc;IACnF,IAAID,aAAaE,MAAM,KAAK,UAAU;QACpC,MAAM,IAAIR,kCAAkCK,OAAOE,cAAc,EAAED,aAAaE,MAAM;IACxF;IACA,yFAAyF;IACzF,IAAIF,aAAaG,WAAW,KAAKJ,OAAOK,iBAAiB,EAAE;QACzD,MAAM,IAAIT,8BACRI,OAAOE,cAAc,EACrBD,aAAaG,WAAW,EACxBJ,OAAOK,iBAAiB;IAE5B;IAEA,+EAA+E;IAC/E,qEAAqE;IACrE,MAAMC,cAAc;QAClBC,QAAQ;QACRH,aAAaH,aAAaG,WAAW;QACrCI,UAAU;QACVL,QAAQF,aAAaE,MAAM;QAC3BM,OAAOR,aAAaQ,KAAK;QACzBC,YAAY;QACZC,cAAc;QACdC,gBAAgB;QAChBC,SAAS;QACTC,YAAY,IAAIC;IAClB;IAEAxB,mBAAmByB,GAAG,CAAC,GAAG;QAACR,UAAU;IAAQ;IAE7C,IAAIS;IACJ,IAAI;QACFA,MAAM,MAAM7B,YAAY;YACtBgB,aAAaH,aAAaG,WAAW;YACrCc,WAAWjB,aAAaiB,SAAS;YACjCC,cAAclB,aAAamB,oBAAoB;YAC/CC,gBAAgB;gBACdb,UAAU;gBACVL,QAAQ;gBACRM,OAAO;gBACPP,gBAAgBD,aAAaqB,EAAE;gBAC/BC,QAAQvB,OAAOuB,MAAM;YACvB;YACAC,QAAQxB,OAAOwB,MAAM,IAAI/B,iBAAiBQ;QAC5C;IACF,EAAE,OAAOwB,OAAO;QACd,MAAMC,UAAU,MAAM7B,oBAAoB;YAAC,GAAGS,WAAW;YAAEqB,UAAUzC;QAAY;QACjF,MAAMwC,QAAQE,eAAe,CAAC3B,cAAcH,SAAS2B;QACrD,IAAItC,4BAA4BsC,QAAQ;YACtCnC,kBAAkB0B,GAAG,CAAC,GAAG;gBAACR,UAAU;gBAAUqB,SAAS;YAAS;YAChE,MAAMH,QAAQI,UAAU,CAAC;QAC3B,OAAO;YACLxC,kBAAkB0B,GAAG,CAAC,GAAG;gBAACR,UAAU;gBAAUqB,SAAS;YAAQ;YAC/D,MAAMH,QAAQK,MAAM,CAAC;QACvB;QACA,MAAMN;IACR;IAEA,MAAMO,UAAU,MAAMnC,oBAAoB;QAAC,GAAGS,WAAW;QAAEqB,UAAUV,IAAIK,EAAE;IAAA;IAC3E,MAAMU,QAAQC,SAAS,CAAChC,cAAcgB;IACtCzB,2BAA2BwB,GAAG,CAAC,GAAG;QAACR,UAAU;IAAQ;IACrDlB,kBAAkB0B,GAAG,CAAC,GAAG;QAACR,UAAU;QAAUqB,SAAS;IAAQ;IAC/D,MAAMG,QAAQE,MAAM,CAAC;IACrB,OAAOjB;AACT"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { type ComputeNextFireAtParams, computeNextFireAt, } from './compute-next-fire-at.js';
|
|
2
|
+
export { readConfigInputs } from './config.js';
|
|
3
|
+
export { type DispatchIntegrationEventParams, dispatchIntegrationEvent, } from './dispatch-integration-event.js';
|
|
4
|
+
export { type CronDrainSummary, type DrainDueCronSchedulesParams, drainDueCronSchedules, } from './drain-cron-schedules.js';
|
|
5
|
+
export type { CronSchedule } from './entities/cron-schedule.js';
|
|
6
|
+
export type { TriggerSubscription } from './entities/subscription.js';
|
|
7
|
+
export { ManualTriggerNotFoundError, TriggerSubscriptionNotCronError, TriggerSubscriptionNotFoundError, TriggerSubscriptionNotManualError, TriggerWorkspaceMismatchError, } from './errors.js';
|
|
8
|
+
export { type FireCronSubscriptionParams, type FireCronSubscriptionResult, fireCronSubscription, } from './fire-cron.js';
|
|
9
|
+
export { type FireManualSubscriptionParams, fireManualSubscription } from './fire-manual.js';
|
|
10
|
+
export { type RouteEventToJobListenersParams, type RouteEventToJobListenersResult, routeEventToJobListeners, } from './route-event-to-job-listeners.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,uBAAuB,EAC5B,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAC,gBAAgB,EAAC,MAAM,aAAa,CAAC;AAC7C,OAAO,EACL,KAAK,8BAA8B,EACnC,wBAAwB,GACzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,2BAA2B,EAChC,qBAAqB,GACtB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAC,YAAY,EAAC,MAAM,6BAA6B,CAAC;AAC9D,YAAY,EAAC,mBAAmB,EAAC,MAAM,4BAA4B,CAAC;AACpE,OAAO,EACL,0BAA0B,EAC1B,+BAA+B,EAC/B,gCAAgC,EAChC,iCAAiC,EACjC,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,0BAA0B,EAC/B,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAC,KAAK,4BAA4B,EAAE,sBAAsB,EAAC,MAAM,kBAAkB,CAAC;AAC3F,OAAO,EACL,KAAK,8BAA8B,EACnC,KAAK,8BAA8B,EACnC,wBAAwB,GACzB,MAAM,mCAAmC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { computeNextFireAt } from './compute-next-fire-at.js';
|
|
2
|
+
export { readConfigInputs } from './config.js';
|
|
3
|
+
export { dispatchIntegrationEvent } from './dispatch-integration-event.js';
|
|
4
|
+
export { drainDueCronSchedules } from './drain-cron-schedules.js';
|
|
5
|
+
export { ManualTriggerNotFoundError, TriggerSubscriptionNotCronError, TriggerSubscriptionNotFoundError, TriggerSubscriptionNotManualError, TriggerWorkspaceMismatchError } from './errors.js';
|
|
6
|
+
export { fireCronSubscription } from './fire-cron.js';
|
|
7
|
+
export { fireManualSubscription } from './fire-manual.js';
|
|
8
|
+
export { routeEventToJobListeners } from './route-event-to-job-listeners.js';
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/index.ts"],"sourcesContent":["export {\n type ComputeNextFireAtParams,\n computeNextFireAt,\n} from './compute-next-fire-at.js';\nexport {readConfigInputs} from './config.js';\nexport {\n type DispatchIntegrationEventParams,\n dispatchIntegrationEvent,\n} from './dispatch-integration-event.js';\nexport {\n type CronDrainSummary,\n type DrainDueCronSchedulesParams,\n drainDueCronSchedules,\n} from './drain-cron-schedules.js';\nexport type {CronSchedule} from './entities/cron-schedule.js';\nexport type {TriggerSubscription} from './entities/subscription.js';\nexport {\n ManualTriggerNotFoundError,\n TriggerSubscriptionNotCronError,\n TriggerSubscriptionNotFoundError,\n TriggerSubscriptionNotManualError,\n TriggerWorkspaceMismatchError,\n} from './errors.js';\nexport {\n type FireCronSubscriptionParams,\n type FireCronSubscriptionResult,\n fireCronSubscription,\n} from './fire-cron.js';\nexport {type FireManualSubscriptionParams, fireManualSubscription} from './fire-manual.js';\nexport {\n type RouteEventToJobListenersParams,\n type RouteEventToJobListenersResult,\n routeEventToJobListeners,\n} from './route-event-to-job-listeners.js';\n"],"names":["computeNextFireAt","readConfigInputs","dispatchIntegrationEvent","drainDueCronSchedules","ManualTriggerNotFoundError","TriggerSubscriptionNotCronError","TriggerSubscriptionNotFoundError","TriggerSubscriptionNotManualError","TriggerWorkspaceMismatchError","fireCronSubscription","fireManualSubscription","routeEventToJobListeners"],"mappings":"AAAA,SAEEA,iBAAiB,QACZ,4BAA4B;AACnC,SAAQC,gBAAgB,QAAO,cAAc;AAC7C,SAEEC,wBAAwB,QACnB,kCAAkC;AACzC,SAGEC,qBAAqB,QAChB,4BAA4B;AAGnC,SACEC,0BAA0B,EAC1BC,+BAA+B,EAC/BC,gCAAgC,EAChCC,iCAAiC,EACjCC,6BAA6B,QACxB,cAAc;AACrB,SAGEC,oBAAoB,QACf,iBAAiB;AACxB,SAA2CC,sBAAsB,QAAO,mBAAmB;AAC3F,SAGEC,wBAAwB,QACnB,oCAAoC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { JobListenerSubscription } from '#core/entities/job-listener-subscription.js';
|
|
2
|
+
import type { TriggerEventOrigin } from '#core/entities/received-event.js';
|
|
3
|
+
import type { TriggerSubscription } from '#core/entities/subscription.js';
|
|
4
|
+
export declare function toReason(error: unknown): string;
|
|
5
|
+
export interface TriggerRun {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
}
|
|
9
|
+
export interface TriggerHistoryRecorder {
|
|
10
|
+
triggered(subscription: TriggerSubscription, run: TriggerRun): Promise<void>;
|
|
11
|
+
filterErrored(subscription: TriggerSubscription, reason: string): Promise<void>;
|
|
12
|
+
dispatchErrored(subscription: TriggerSubscription, reason: string): Promise<void>;
|
|
13
|
+
listenerTriggered(subscription: JobListenerSubscription): Promise<void>;
|
|
14
|
+
listenerFilterErrored(subscription: JobListenerSubscription, reason: string): Promise<void>;
|
|
15
|
+
listenerDispatchErrored(subscription: JobListenerSubscription, reason: string): Promise<void>;
|
|
16
|
+
discarded(): Promise<void>;
|
|
17
|
+
routed(matchedCount: number): Promise<void>;
|
|
18
|
+
failed(matchedCount: number): Promise<void>;
|
|
19
|
+
allErrored(matchedCount: number): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
export interface BeginTriggerHistoryParams {
|
|
22
|
+
eventRef: string;
|
|
23
|
+
origin: TriggerEventOrigin;
|
|
24
|
+
workspaceId: string;
|
|
25
|
+
provider: string | null;
|
|
26
|
+
source: string;
|
|
27
|
+
event: string;
|
|
28
|
+
deliveryId: string | null;
|
|
29
|
+
connectionId: string | null;
|
|
30
|
+
connectionName: string | null;
|
|
31
|
+
payload: Record<string, unknown> | null;
|
|
32
|
+
receivedAt: Date;
|
|
33
|
+
}
|
|
34
|
+
export declare function beginTriggerHistory(params: BeginTriggerHistoryParams): Promise<TriggerHistoryRecorder>;
|
|
35
|
+
//# sourceMappingURL=record-trigger-history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-trigger-history.d.ts","sourceRoot":"","sources":["../../src/core/record-trigger-history.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,6CAA6C,CAAC;AACzF,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,kCAAkC,CAAC;AACzE,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AAmBxE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQ/C;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,YAAY,EAAE,mBAAmB,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,aAAa,CAAC,YAAY,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF,eAAe,CAAC,YAAY,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClF,iBAAiB,CAAC,YAAY,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,qBAAqB,CAAC,YAAY,EAAE,uBAAuB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5F,uBAAuB,CAAC,YAAY,EAAE,uBAAuB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9F,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,UAAU,EAAE,IAAI,CAAC;CAClB;AAID,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAAC,sBAAsB,CAAC,CA2DjC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { logger } from '@shipfox/node-opentelemetry';
|
|
2
|
+
import { insertReceivedEvent, markReceivedEventDiscarded, markReceivedEventErrored, markReceivedEventFailed, markReceivedEventRouted, upsertDispatchErrorDecision, upsertFilterErrorDecision, upsertListenerDispatchErrorDecision, upsertListenerFilterErrorDecision, upsertListenerTriggeredDecision, upsertTriggeredDecision } from '#db/event-history.js';
|
|
3
|
+
const MAX_REASON_LENGTH = 2000;
|
|
4
|
+
// A bounded, deterministic reason string safe to persist: error messages can be
|
|
5
|
+
// long or carry untrusted data, so cap the length and never serialize the object.
|
|
6
|
+
export function toReason(error) {
|
|
7
|
+
let message;
|
|
8
|
+
try {
|
|
9
|
+
message = error instanceof Error ? error.message : String(error);
|
|
10
|
+
} catch {
|
|
11
|
+
message = '[unprintable thrown value]';
|
|
12
|
+
}
|
|
13
|
+
return message.slice(0, MAX_REASON_LENGTH);
|
|
14
|
+
}
|
|
15
|
+
// History writes are best-effort and log stable ids only, never payloads or tokens.
|
|
16
|
+
// If the parent insert fails there is no row to attach to, so later calls no-op.
|
|
17
|
+
export async function beginTriggerHistory(params) {
|
|
18
|
+
const receivedEventId = await safe(params.eventRef, 'insert-received-event', ()=>insertReceivedEvent(params));
|
|
19
|
+
const record = async (label, write, subscriptionId)=>{
|
|
20
|
+
if (receivedEventId === undefined) return;
|
|
21
|
+
await safe(params.eventRef, label, ()=>write(receivedEventId), subscriptionId);
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
triggered: (subscription, run)=>record('triggered-decision', (id)=>upsertTriggeredDecision({
|
|
25
|
+
receivedEventId: id,
|
|
26
|
+
subscription,
|
|
27
|
+
run
|
|
28
|
+
}), subscription.id),
|
|
29
|
+
filterErrored: (subscription, reason)=>record('filter-error-decision', (id)=>upsertFilterErrorDecision({
|
|
30
|
+
receivedEventId: id,
|
|
31
|
+
subscription,
|
|
32
|
+
reason
|
|
33
|
+
}), subscription.id),
|
|
34
|
+
dispatchErrored: (subscription, reason)=>record('dispatch-error-decision', (id)=>upsertDispatchErrorDecision({
|
|
35
|
+
receivedEventId: id,
|
|
36
|
+
subscription,
|
|
37
|
+
reason
|
|
38
|
+
}), subscription.id),
|
|
39
|
+
listenerTriggered: (subscription)=>record('listener-triggered-decision', (id)=>upsertListenerTriggeredDecision({
|
|
40
|
+
receivedEventId: id,
|
|
41
|
+
subscription
|
|
42
|
+
}), subscription.id),
|
|
43
|
+
listenerFilterErrored: (subscription, reason)=>record('listener-filter-error-decision', (id)=>upsertListenerFilterErrorDecision({
|
|
44
|
+
receivedEventId: id,
|
|
45
|
+
subscription,
|
|
46
|
+
reason
|
|
47
|
+
}), subscription.id),
|
|
48
|
+
listenerDispatchErrored: (subscription, reason)=>record('listener-dispatch-error-decision', (id)=>upsertListenerDispatchErrorDecision({
|
|
49
|
+
receivedEventId: id,
|
|
50
|
+
subscription,
|
|
51
|
+
reason
|
|
52
|
+
}), subscription.id),
|
|
53
|
+
discarded: ()=>record('discard-event', (id)=>markReceivedEventDiscarded(id)),
|
|
54
|
+
routed: (matchedCount)=>record('route-event', (id)=>markReceivedEventRouted(id, matchedCount)),
|
|
55
|
+
failed: (matchedCount)=>record('fail-event', (id)=>markReceivedEventFailed(id, matchedCount)),
|
|
56
|
+
allErrored: (matchedCount)=>record('all-errored-event', (id)=>markReceivedEventErrored(id, matchedCount))
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
async function safe(eventRef, label, fn, subscriptionId) {
|
|
60
|
+
try {
|
|
61
|
+
return await fn();
|
|
62
|
+
} catch (error) {
|
|
63
|
+
logger().warn({
|
|
64
|
+
err: error,
|
|
65
|
+
label,
|
|
66
|
+
eventRef,
|
|
67
|
+
...subscriptionId ? {
|
|
68
|
+
subscriptionId
|
|
69
|
+
} : {}
|
|
70
|
+
}, 'trigger history write failed; ignored (best-effort)');
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=record-trigger-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/record-trigger-history.ts"],"sourcesContent":["import {logger} from '@shipfox/node-opentelemetry';\nimport type {JobListenerSubscription} from '#core/entities/job-listener-subscription.js';\nimport type {TriggerEventOrigin} from '#core/entities/received-event.js';\nimport type {TriggerSubscription} from '#core/entities/subscription.js';\nimport {\n insertReceivedEvent,\n markReceivedEventDiscarded,\n markReceivedEventErrored,\n markReceivedEventFailed,\n markReceivedEventRouted,\n upsertDispatchErrorDecision,\n upsertFilterErrorDecision,\n upsertListenerDispatchErrorDecision,\n upsertListenerFilterErrorDecision,\n upsertListenerTriggeredDecision,\n upsertTriggeredDecision,\n} from '#db/event-history.js';\n\nconst MAX_REASON_LENGTH = 2000;\n\n// A bounded, deterministic reason string safe to persist: error messages can be\n// long or carry untrusted data, so cap the length and never serialize the object.\nexport function toReason(error: unknown): string {\n let message: string;\n try {\n message = error instanceof Error ? error.message : String(error);\n } catch {\n message = '[unprintable thrown value]';\n }\n return message.slice(0, MAX_REASON_LENGTH);\n}\n\nexport interface TriggerRun {\n id: string;\n name: string;\n}\n\nexport interface TriggerHistoryRecorder {\n triggered(subscription: TriggerSubscription, run: TriggerRun): Promise<void>;\n filterErrored(subscription: TriggerSubscription, reason: string): Promise<void>;\n dispatchErrored(subscription: TriggerSubscription, reason: string): Promise<void>;\n listenerTriggered(subscription: JobListenerSubscription): Promise<void>;\n listenerFilterErrored(subscription: JobListenerSubscription, reason: string): Promise<void>;\n listenerDispatchErrored(subscription: JobListenerSubscription, reason: string): Promise<void>;\n discarded(): Promise<void>;\n routed(matchedCount: number): Promise<void>;\n failed(matchedCount: number): Promise<void>;\n allErrored(matchedCount: number): Promise<void>;\n}\n\nexport interface BeginTriggerHistoryParams {\n eventRef: string;\n origin: TriggerEventOrigin;\n workspaceId: string;\n provider: string | null;\n source: string;\n event: string;\n deliveryId: string | null;\n connectionId: string | null;\n connectionName: string | null;\n payload: Record<string, unknown> | null;\n receivedAt: Date;\n}\n\n// History writes are best-effort and log stable ids only, never payloads or tokens.\n// If the parent insert fails there is no row to attach to, so later calls no-op.\nexport async function beginTriggerHistory(\n params: BeginTriggerHistoryParams,\n): Promise<TriggerHistoryRecorder> {\n const receivedEventId = await safe(params.eventRef, 'insert-received-event', () =>\n insertReceivedEvent(params),\n );\n\n const record = async (\n label: string,\n write: (receivedEventId: string) => Promise<unknown>,\n subscriptionId?: string,\n ): Promise<void> => {\n if (receivedEventId === undefined) return;\n await safe(params.eventRef, label, () => write(receivedEventId), subscriptionId);\n };\n\n return {\n triggered: (subscription, run) =>\n record(\n 'triggered-decision',\n (id) => upsertTriggeredDecision({receivedEventId: id, subscription, run}),\n subscription.id,\n ),\n filterErrored: (subscription, reason) =>\n record(\n 'filter-error-decision',\n (id) => upsertFilterErrorDecision({receivedEventId: id, subscription, reason}),\n subscription.id,\n ),\n dispatchErrored: (subscription, reason) =>\n record(\n 'dispatch-error-decision',\n (id) => upsertDispatchErrorDecision({receivedEventId: id, subscription, reason}),\n subscription.id,\n ),\n listenerTriggered: (subscription) =>\n record(\n 'listener-triggered-decision',\n (id) => upsertListenerTriggeredDecision({receivedEventId: id, subscription}),\n subscription.id,\n ),\n listenerFilterErrored: (subscription, reason) =>\n record(\n 'listener-filter-error-decision',\n (id) => upsertListenerFilterErrorDecision({receivedEventId: id, subscription, reason}),\n subscription.id,\n ),\n listenerDispatchErrored: (subscription, reason) =>\n record(\n 'listener-dispatch-error-decision',\n (id) => upsertListenerDispatchErrorDecision({receivedEventId: id, subscription, reason}),\n subscription.id,\n ),\n discarded: () => record('discard-event', (id) => markReceivedEventDiscarded(id)),\n routed: (matchedCount) =>\n record('route-event', (id) => markReceivedEventRouted(id, matchedCount)),\n failed: (matchedCount) =>\n record('fail-event', (id) => markReceivedEventFailed(id, matchedCount)),\n allErrored: (matchedCount) =>\n record('all-errored-event', (id) => markReceivedEventErrored(id, matchedCount)),\n };\n}\n\nasync function safe<T>(\n eventRef: string,\n label: string,\n fn: () => Promise<T>,\n subscriptionId?: string,\n): Promise<T | undefined> {\n try {\n return await fn();\n } catch (error) {\n logger().warn(\n {err: error, label, eventRef, ...(subscriptionId ? {subscriptionId} : {})},\n 'trigger history write failed; ignored (best-effort)',\n );\n return undefined;\n }\n}\n"],"names":["logger","insertReceivedEvent","markReceivedEventDiscarded","markReceivedEventErrored","markReceivedEventFailed","markReceivedEventRouted","upsertDispatchErrorDecision","upsertFilterErrorDecision","upsertListenerDispatchErrorDecision","upsertListenerFilterErrorDecision","upsertListenerTriggeredDecision","upsertTriggeredDecision","MAX_REASON_LENGTH","toReason","error","message","Error","String","slice","beginTriggerHistory","params","receivedEventId","safe","eventRef","record","label","write","subscriptionId","undefined","triggered","subscription","run","id","filterErrored","reason","dispatchErrored","listenerTriggered","listenerFilterErrored","listenerDispatchErrored","discarded","routed","matchedCount","failed","allErrored","fn","warn","err"],"mappings":"AAAA,SAAQA,MAAM,QAAO,8BAA8B;AAInD,SACEC,mBAAmB,EACnBC,0BAA0B,EAC1BC,wBAAwB,EACxBC,uBAAuB,EACvBC,uBAAuB,EACvBC,2BAA2B,EAC3BC,yBAAyB,EACzBC,mCAAmC,EACnCC,iCAAiC,EACjCC,+BAA+B,EAC/BC,uBAAuB,QAClB,uBAAuB;AAE9B,MAAMC,oBAAoB;AAE1B,gFAAgF;AAChF,kFAAkF;AAClF,OAAO,SAASC,SAASC,KAAc;IACrC,IAAIC;IACJ,IAAI;QACFA,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;IAC5D,EAAE,OAAM;QACNC,UAAU;IACZ;IACA,OAAOA,QAAQG,KAAK,CAAC,GAAGN;AAC1B;AAkCA,oFAAoF;AACpF,iFAAiF;AACjF,OAAO,eAAeO,oBACpBC,MAAiC;IAEjC,MAAMC,kBAAkB,MAAMC,KAAKF,OAAOG,QAAQ,EAAE,yBAAyB,IAC3EtB,oBAAoBmB;IAGtB,MAAMI,SAAS,OACbC,OACAC,OACAC;QAEA,IAAIN,oBAAoBO,WAAW;QACnC,MAAMN,KAAKF,OAAOG,QAAQ,EAAEE,OAAO,IAAMC,MAAML,kBAAkBM;IACnE;IAEA,OAAO;QACLE,WAAW,CAACC,cAAcC,MACxBP,OACE,sBACA,CAACQ,KAAOrB,wBAAwB;oBAACU,iBAAiBW;oBAAIF;oBAAcC;gBAAG,IACvED,aAAaE,EAAE;QAEnBC,eAAe,CAACH,cAAcI,SAC5BV,OACE,yBACA,CAACQ,KAAOzB,0BAA0B;oBAACc,iBAAiBW;oBAAIF;oBAAcI;gBAAM,IAC5EJ,aAAaE,EAAE;QAEnBG,iBAAiB,CAACL,cAAcI,SAC9BV,OACE,2BACA,CAACQ,KAAO1B,4BAA4B;oBAACe,iBAAiBW;oBAAIF;oBAAcI;gBAAM,IAC9EJ,aAAaE,EAAE;QAEnBI,mBAAmB,CAACN,eAClBN,OACE,+BACA,CAACQ,KAAOtB,gCAAgC;oBAACW,iBAAiBW;oBAAIF;gBAAY,IAC1EA,aAAaE,EAAE;QAEnBK,uBAAuB,CAACP,cAAcI,SACpCV,OACE,kCACA,CAACQ,KAAOvB,kCAAkC;oBAACY,iBAAiBW;oBAAIF;oBAAcI;gBAAM,IACpFJ,aAAaE,EAAE;QAEnBM,yBAAyB,CAACR,cAAcI,SACtCV,OACE,oCACA,CAACQ,KAAOxB,oCAAoC;oBAACa,iBAAiBW;oBAAIF;oBAAcI;gBAAM,IACtFJ,aAAaE,EAAE;QAEnBO,WAAW,IAAMf,OAAO,iBAAiB,CAACQ,KAAO9B,2BAA2B8B;QAC5EQ,QAAQ,CAACC,eACPjB,OAAO,eAAe,CAACQ,KAAO3B,wBAAwB2B,IAAIS;QAC5DC,QAAQ,CAACD,eACPjB,OAAO,cAAc,CAACQ,KAAO5B,wBAAwB4B,IAAIS;QAC3DE,YAAY,CAACF,eACXjB,OAAO,qBAAqB,CAACQ,KAAO7B,yBAAyB6B,IAAIS;IACrE;AACF;AAEA,eAAenB,KACbC,QAAgB,EAChBE,KAAa,EACbmB,EAAoB,EACpBjB,cAAuB;IAEvB,IAAI;QACF,OAAO,MAAMiB;IACf,EAAE,OAAO9B,OAAO;QACdd,SAAS6C,IAAI,CACX;YAACC,KAAKhC;YAAOW;YAAOF;YAAU,GAAII,iBAAiB;gBAACA;YAAc,IAAI,CAAC,CAAC;QAAC,GACzE;QAEF,OAAOC;IACT;AACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type TriggerHistoryRecorder } from './record-trigger-history.js';
|
|
2
|
+
export interface RouteEventToJobListenersParams {
|
|
3
|
+
history: TriggerHistoryRecorder;
|
|
4
|
+
eventRef: string;
|
|
5
|
+
workspaceId: string;
|
|
6
|
+
provider: string;
|
|
7
|
+
source: string;
|
|
8
|
+
event: string;
|
|
9
|
+
deliveryId: string;
|
|
10
|
+
payload: unknown;
|
|
11
|
+
receivedAt: Date;
|
|
12
|
+
}
|
|
13
|
+
export interface RouteEventToJobListenersResult {
|
|
14
|
+
/**
|
|
15
|
+
* Listener outcomes that should contribute to received_event.matched_count:
|
|
16
|
+
* filter errors, accepted deliveries, and dispatch errors. Stale skipped jobs
|
|
17
|
+
* are intentionally excluded because they did not produce an auditable decision.
|
|
18
|
+
*/
|
|
19
|
+
engagedCount: number;
|
|
20
|
+
/**
|
|
21
|
+
* Jobs with an effective matcher after source/event/filter checks, including
|
|
22
|
+
* stale skipped jobs.
|
|
23
|
+
*/
|
|
24
|
+
matchedJobCount: number;
|
|
25
|
+
acceptedJobCount: number;
|
|
26
|
+
deliveredCount: number;
|
|
27
|
+
transientErrored: boolean;
|
|
28
|
+
transientError: unknown;
|
|
29
|
+
}
|
|
30
|
+
export declare function routeEventToJobListeners(params: RouteEventToJobListenersParams): Promise<RouteEventToJobListenersResult>;
|
|
31
|
+
//# sourceMappingURL=route-event-to-job-listeners.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-event-to-job-listeners.d.ts","sourceRoot":"","sources":["../../src/core/route-event-to-job-listeners.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,KAAK,sBAAsB,EAAW,MAAM,6BAA6B,CAAC;AAElF,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,sBAAsB,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,8BAA8B;IAC7C;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,8BAA8B,GACrC,OAAO,CAAC,8BAA8B,CAAC,CAmEzC"}
|