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 Translate delivers to EventBridge when a
11 * batch translation job changes state
12 * (`Translate TextTranslationJob State Change`).
13 */
14export interface TranslationJobEventDetail {
15 /** Id of the batch translation job. */
16 jobId?: string;
17 /** The job's new status, e.g. `COMPLETED`, `FAILED`, `STOPPED`. */
18 jobStatus?: string;
19 /** Additional event fields (the schema grows over time). */
20 [key: string]: unknown;
21}
22
23/** A Translate batch-translation-job EventBridge event delivered to the handler. */
24export type TranslationJobEvent = EventRecord<TranslationJobEventDetail>;
25
26export interface TranslationJobEventSourceProps extends EventRouteProps {
27 /**
28 * Logical id for the backing EventBridge rule.
29 * @default "TranslateTranslationJobEvents"
30 */
31 id?: string;
32 /**
33 * Only deliver events with these `detail.jobStatus` values (e.g.
34 * `["COMPLETED", "FAILED"]`).
35 * @default all statuses
36 */
37 statuses?: readonly string[];
38}
39
40/**
41 * Event source connecting Amazon Translate batch translation job state
42 * changes to the hosting compute. Translate publishes every job state
43 * transition (`Translate TextTranslationJob State Change`, source
44 * `aws.translate`) to the account's default EventBridge bus; this
45 * subscribes the host Function to those events so it can chain
46 * post-translation automation or alert on `FAILED` jobs.
47 *
48 * Translate publishes to EventBridge automatically — no additional resource
49 * is created besides the EventBridge rule targeting the host. Provide the
50 * host-specific implementation layer (e.g. `AWS.Lambda.EventSource`) on the
51 * Function effect.
52 *
53 * ### Consuming Job Events
54 * **Example:** React to finished batch translation jobs
55 * ```typescript
56 * import * as AWS from "alchemy/AWS";
57 *
58 * export default TranslationReactor.make(
59 * { main: import.meta.url },
60 * Effect.gen(function* () {
61 * yield* AWS.Translate.consumeTranslationJobEvents(
62 * { statuses: ["COMPLETED", "FAILED"] },
63 * (events) =>
64 * Stream.runForEach(events, (event) =>
65 * Effect.log(`job ${event.detail.jobId}: ${event.detail.jobStatus}`),
66 * ),
67 * );
68 * return {};
69 * }).pipe(Effect.provide(AWS.Lambda.EventSource)),
70 * );
71 * ```
72 */
73export const consumeTranslationJobEvents = <StreamReq = never, Req = never>(
74 props: TranslationJobEventSourceProps,
75 process: (
76 events: Stream.Stream<TranslationJobEvent, never, StreamReq>,
77 ) => Effect.Effect<void, never, Req>,
78) =>
79 consumeBusEvents(
80 props.id ?? "TranslateTranslationJobEvents",
81 {
82 source: ["aws.translate"],
83 "detail-type": ["Translate TextTranslationJob State Change"],
84 ...(props.statuses ? { detail: { jobStatus: [...props.statuses] } } : {}),
85 },
86 { description: props.description, state: props.state },
87 process,
88 );