1import type * as aas from "@distilled.cloud/aws/application-auto-scaling";
2import * as Effect from "effect/Effect";
3import * as Schedule from "effect/Schedule";
4
5/**
6 * Known Application Auto Scaling service namespaces, used by `list()` to
7 * enumerate account-wide state. `DescribeScalableTargets` (and the policy /
8 * scheduled-action describes) require a `ServiceNamespace` filter, so an
9 * account-wide enumeration is the union of the per-namespace enumerations.
10 * The wire type is open (`string & {}`) but AWS only ever returns members of
11 * this set; new namespaces are appended when AWS ships them.
12 */
13export const SERVICE_NAMESPACES: readonly aas.ServiceNamespace[] = [
14 "ecs",
15 "elasticmapreduce",
16 "ec2",
17 "appstream",
18 "dynamodb",
19 "rds",
20 "sagemaker",
21 "custom-resource",
22 "comprehend",
23 "lambda",
24 "cassandra",
25 "kafka",
26 "elasticache",
27 "neptune",
28 "workspaces",
29];
30
31/**
32 * `RegisterScalableTarget` is eventually consistent: a `PutScalingPolicy` /
33 * `PutScheduledAction` issued immediately after registration can fail with
34 * `ObjectNotFoundException` until the target propagates. Retry that typed tag
35 * on a short bounded schedule (~20s total).
36 *
37 * NOTE: the explicit `Effect.Effect<A, E, R>` return annotation is
38 * load-bearing — an inlined `Effect.retry` leaks `Retry.Return`'s conditional
39 * type into declaration emit and widens the provider layer to
40 * `Layer<..., never, unknown>` for downstream consumers.
41 */
42export const retryWhileTargetPropagates = <A, E extends { _tag: string }, R>(
43 self: Effect.Effect<A, E, R>,
44): Effect.Effect<A, E, R> =>
45 Effect.retry(self, {
46 while: (e) => e._tag === "ObjectNotFoundException",
47 schedule: Schedule.max([Schedule.fixed("2 seconds"), Schedule.recurs(10)]),
48 });