1import type * as Effect from "effect/Effect";
2import type * as Stream from "effect/Stream";
3import {
4 consumeBusEvents,
5 type EventRecord,
6 type EventRouteProps,
7} from "../EventBridge/EventSource.ts";
8
9/**
10 * The `detail` payload Amazon HealthOmics delivers to EventBridge when a
11 * workflow run changes state (`Run Status Change`, source `aws.omics`). Which
12 * fields are present depends on the event, so everything run-specific is
13 * optional.
14 */
15export interface OmicsRunEventDetail {
16 /** The run's id. */
17 id?: string;
18 /** ARN of the run. */
19 arn?: string;
20 /** The run status: `PENDING`, `STARTING`, `RUNNING`, `STOPPING`, `COMPLETED`, `DELETED`, `CANCELLED`, or `FAILED`. */
21 status?: string;
22 /** The id of the workflow the run executes. */
23 workflowId?: string;
24 /** The id of the run group the run belongs to, if any. */
25 runGroupId?: string;
26 /** A human-readable status message (populated on `FAILED`). */
27 statusMessage?: string;
28 /** Additional event fields (the schema grows over time). */
29 [key: string]: unknown;
30}
31
32/** A HealthOmics run EventBridge event delivered to the handler. */
33export type OmicsRunEvent = EventRecord<OmicsRunEventDetail>;
34
35export interface RunStatusEventSourceProps extends EventRouteProps {
36 /**
37 * Logical id for the backing EventBridge rule.
38 * @default "OmicsRunStatusEvents"
39 */
40 id?: string;
41 /**
42 * Only deliver events with these `detail.status` values (e.g.
43 * `["COMPLETED", "FAILED"]`).
44 * @default all statuses
45 */
46 statuses?: readonly string[];
47}
48
49/**
50 * Event source connecting Amazon HealthOmics run state changes to the hosting
51 * compute. HealthOmics publishes every run state transition (`Run Status
52 * Change`, source `aws.omics`) to the account's default EventBridge bus; this
53 * subscribes the host Function to those events so it can chain post-run
54 * automation (fetch outputs, kick off downstream analysis) or alert on
55 * `FAILED` runs.
56 *
57 * HealthOmics publishes to EventBridge automatically — no additional resource
58 * is created besides the EventBridge rule targeting the host. Provide the
59 * host-specific implementation layer (e.g. `AWS.Lambda.EventSource`) on the
60 * Function effect.
61 *
62 * ### Consuming Run Events
63 * **Example:** React To Finished Runs
64 * ```typescript
65 * import * as AWS from "alchemy/AWS";
66 *
67 * export default RunReactor.make(
68 * { main: import.meta.url },
69 * Effect.gen(function* () {
70 * yield* AWS.Omics.consumeRunEvents(
71 * { statuses: ["COMPLETED", "FAILED"] },
72 * (events) =>
73 * Stream.runForEach(events, (event) =>
74 * event.detail.status === "FAILED"
75 * ? Effect.log(`run ${event.detail.id} failed: ${event.detail.statusMessage}`)
76 * : Effect.log(`run ${event.detail.id} complete`),
77 * ),
78 * );
79 * return {};
80 * }).pipe(Effect.provide(AWS.Lambda.EventSource)),
81 * );
82 * ```
83 */
84export const consumeRunEvents = <StreamReq = never, Req = never>(
85 props: RunStatusEventSourceProps,
86 process: (
87 events: Stream.Stream<OmicsRunEvent, never, StreamReq>,
88 ) => Effect.Effect<void, never, Req>,
89) =>
90 consumeBusEvents(
91 props.id ?? "OmicsRunStatusEvents",
92 {
93 source: ["aws.omics"],
94 "detail-type": ["Run Status Change"],
95 ...(props.statuses ? { detail: { status: [...props.statuses] } } : {}),
96 },
97 { description: props.description, state: props.state },
98 process,
99 );