1import type * as autoscaling from "@distilled.cloud/aws/auto-scaling";
2import type * as Effect from "effect/Effect";
3import * as Binding from "../../Binding.ts";
4import type { AutoScalingGroup } from "./AutoScalingGroup.ts";
5
6/**
7 * Signal the result of a paused lifecycle action. The Auto Scaling group name is
8 * injected by the binding; supply the hook name, the action token (from the
9 * lifecycle event) or instance id, and the result.
10 */
11export interface CompleteLifecycleActionRequest extends Omit<
12 autoscaling.CompleteLifecycleActionType,
13 "AutoScalingGroupName"
14> {}
15
16/**
17 * Extend the heartbeat timeout on a paused lifecycle action. The Auto Scaling
18 * group name is injected by the binding.
19 */
20export interface RecordLifecycleActionHeartbeatRequest extends Omit<
21 autoscaling.RecordLifecycleActionHeartbeatType,
22 "AutoScalingGroupName"
23> {}
24
25export interface CompleteLifecycleActionClient {
26 /**
27 * Signal `CONTINUE` or `ABANDON` on a paused lifecycle action so the instance
28 * transition proceeds instead of waiting for the heartbeat timeout.
29 */
30 complete: (
31 request: CompleteLifecycleActionRequest,
32 ) => Effect.Effect<
33 autoscaling.CompleteLifecycleActionAnswer,
34 autoscaling.CompleteLifecycleActionError
35 >;
36 /**
37 * Extend the wait state by resetting the heartbeat timeout, buying more time
38 * before the hook's `defaultResult` is applied.
39 */
40 heartbeat: (
41 request: RecordLifecycleActionHeartbeatRequest,
42 ) => Effect.Effect<
43 autoscaling.RecordLifecycleActionHeartbeatAnswer,
44 autoscaling.RecordLifecycleActionHeartbeatError
45 >;
46}
47
48/**
49 * A write binding that lets a Function/Instance complete or heartbeat paused
50 * lifecycle actions on an Auto Scaling Group. Grants
51 * `autoscaling:CompleteLifecycleAction` and
52 * `autoscaling:RecordLifecycleActionHeartbeat` scoped to the group ARN.
53 *
54 * ### Completing Lifecycle Actions
55 * **Example:** Signal CONTINUE from a lifecycle handler
56 * ```typescript
57 * const lifecycle = yield* CompleteLifecycleAction(group);
58 * yield* lifecycle.complete({
59 * LifecycleHookName: event.detail.LifecycleHookName,
60 * LifecycleActionToken: event.detail.LifecycleActionToken,
61 * LifecycleActionResult: "CONTINUE",
62 * });
63 * ```
64 *
65 * **Example:** Drain launching instances from a Lambda Function
66 * ```typescript
67 * import * as AWS from "alchemy/AWS";
68 * import {
69 * CompleteLifecycleAction,
70 * CompleteLifecycleActionHttp,
71 * consumeLifecycleActions,
72 * } from "alchemy/AWS/AutoScaling";
73 *
74 * export class LifecycleFunction extends AWS.Lambda.Function<AWS.Lambda.Function>()(
75 * "LifecycleFunction",
76 * ) {}
77 *
78 * export default LifecycleFunction.make(
79 * { main: import.meta.url },
80 * Effect.gen(function* () {
81 * const lifecycle = yield* CompleteLifecycleAction(group);
82 *
83 * yield* consumeLifecycleActions(
84 * group,
85 * { lifecycleTransition: "LAUNCHING", heartbeatTimeout: "300 seconds" },
86 * (events) =>
87 * Stream.runForEach(events, (event) =>
88 * lifecycle
89 * .complete({
90 * LifecycleHookName: event.detail.LifecycleHookName,
91 * LifecycleActionToken: event.detail.LifecycleActionToken,
92 * LifecycleActionResult: "CONTINUE",
93 * })
94 * .pipe(Effect.orDie),
95 * ),
96 * );
97 *
98 * return {};
99 * }).pipe(
100 * Effect.provide(
101 * Layer.mergeAll(AWS.Lambda.EventSource, CompleteLifecycleActionHttp),
102 * ),
103 * ),
104 * );
105 * ```
106 *
107 * **Example:** Buy more time with a heartbeat
108 * ```typescript
109 * // reset the heartbeat timeout while a long drain is still in progress
110 * yield* lifecycle.heartbeat({
111 * LifecycleHookName: event.detail.LifecycleHookName,
112 * LifecycleActionToken: event.detail.LifecycleActionToken,
113 * });
114 * ```
115 *
116 * @binding
117 */
118export interface CompleteLifecycleAction extends Binding.Service<
119 CompleteLifecycleAction,
120 "AWS.AutoScaling.CompleteLifecycleAction",
121 (group: AutoScalingGroup) => Effect.Effect<CompleteLifecycleActionClient>
122> {}
123
124export const CompleteLifecycleAction = Binding.Service<CompleteLifecycleAction>(
125 "AWS.AutoScaling.CompleteLifecycleAction",
126);