85453da49f
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
Docs / Validate docs (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Sync skills to ClawHub / Publish changed skills (push) Waiting to run
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
504 lines
20 KiB
YAML
504 lines
20 KiB
YAML
AWSTemplateFormatVersion: "2010-09-09"
|
||
Transform: AWS::Serverless-2016-10-31
|
||
Description: >-
|
||
HyperFrames distributed rendering — Step Functions standard workflow with
|
||
one Lambda function handling Plan, RenderChunk (fan-out via Map state),
|
||
and Assemble. One S3 bucket, alarms for runaway concurrency, Lambda
|
||
errors, and Step Functions execution failures.
|
||
|
||
Built from the handler ZIP at packages/aws-lambda/dist/handler.zip.
|
||
|
||
See:
|
||
- packages/aws-lambda/README.md (handler architecture)
|
||
- examples/aws-lambda/README.md (this directory's deploy guide)
|
||
|
||
Parameters:
|
||
ProjectName:
|
||
Type: String
|
||
Default: hyperframes
|
||
Description: Name prefix applied to all created resources.
|
||
|
||
LambdaMemoryMb:
|
||
Type: Number
|
||
Default: 10240
|
||
AllowedValues: [2048, 3072, 4096, 5120, 6144, 7168, 8192, 9216, 10240]
|
||
Description: >-
|
||
Lambda memory in MB. Render workloads are CPU-bound; bumping memory
|
||
proportionally bumps the CPU share Lambda gives the function. 10 GB
|
||
(the max) is recommended for 1080p renders.
|
||
|
||
LambdaTimeoutSec:
|
||
Type: Number
|
||
Default: 900
|
||
MinValue: 60
|
||
MaxValue: 900
|
||
Description: >-
|
||
Per-invocation Lambda timeout. Render chunks at the default
|
||
chunkSize=240 frames complete in seconds; 15 minutes is the Lambda
|
||
hard ceiling and the default here to absorb cold-start variance.
|
||
|
||
ReservedConcurrency:
|
||
Type: Number
|
||
Default: -1
|
||
Description: >-
|
||
Lambda reserved concurrency cap. Set to a positive integer to bound
|
||
simultaneous chunk renders (e.g. 50 to limit cost). -1 means
|
||
unreserved (account default).
|
||
|
||
ChromeSource:
|
||
Type: String
|
||
Default: sparticuz
|
||
AllowedValues: [sparticuz, chrome-headless-shell]
|
||
Description: >-
|
||
Which Chrome runtime the bundled ZIP was built with. Must match the
|
||
`--source=` flag passed to `build-zip.ts`. The handler reads this
|
||
via the HYPERFRAMES_LAMBDA_CHROME_SOURCE env var at boot.
|
||
|
||
ChunkInvocationAlarmThreshold:
|
||
Type: Number
|
||
Default: 1000
|
||
Description: >-
|
||
CloudWatch alarm threshold for total RenderChunk invocations per
|
||
hour. The runaway-Map state pathology would fan out far more
|
||
chunks than expected; an alarm at 10× the typical workload
|
||
protects against billing surprises.
|
||
|
||
Conditions:
|
||
HasReservedConcurrency: !Not [!Equals [!Ref ReservedConcurrency, -1]]
|
||
|
||
Globals:
|
||
Function:
|
||
Runtime: nodejs22.x
|
||
MemorySize: !Ref LambdaMemoryMb
|
||
Timeout: !Ref LambdaTimeoutSec
|
||
# x86_64 is required for @sparticuz/chromium — its prebuilt
|
||
# Chromium ships x86_64-only. Adopters who switch to a custom
|
||
# ARM-built chrome-headless-shell can change this to `arm64`, but
|
||
# the default ZIP build will fail to launch on Graviton.
|
||
Architectures: [x86_64]
|
||
# Lambda function-level X-Ray tracing. The state machine already
|
||
# has Tracing.Enabled: true; without this, X-Ray traces would
|
||
# terminate at the Step Functions → Lambda boundary instead of
|
||
# following into per-function spans.
|
||
Tracing: Active
|
||
# Cost-allocation tags. Setting these at the Globals level applies
|
||
# to every AWS::Serverless::Function in the template — there's
|
||
# only one today, but the contract is portable to multi-function
|
||
# variants. Bucket + state-machine carry the same tags resource-
|
||
# locally because Globals only covers functions.
|
||
Tags:
|
||
Project: !Ref ProjectName
|
||
HyperFramesComponent: lambda-renderer
|
||
Environment:
|
||
Variables:
|
||
NODE_OPTIONS: "--enable-source-maps"
|
||
HYPERFRAMES_LAMBDA_CHROME_SOURCE: !Ref ChromeSource
|
||
|
||
Resources:
|
||
# ── S3 bucket for plan tarballs, chunk outputs, and final renders ───────
|
||
RenderBucket:
|
||
Type: AWS::S3::Bucket
|
||
DeletionPolicy: Retain
|
||
UpdateReplacePolicy: Retain
|
||
Properties:
|
||
# BucketName omitted — CloudFormation generates a unique name like
|
||
# "<stack-name>-renderbucket-<random>". S3 bucket names are capped at
|
||
# 63 chars; a static !Sub expression including ProjectName +
|
||
# AWS::AccountId + AWS::Region trips that limit when ProjectName
|
||
# carries a timestamp (e.g. the smoke script's per-run stack name).
|
||
PublicAccessBlockConfiguration:
|
||
BlockPublicAcls: true
|
||
BlockPublicPolicy: true
|
||
IgnorePublicAcls: true
|
||
RestrictPublicBuckets: true
|
||
VersioningConfiguration:
|
||
# `Suspended` keeps storage costs flat — versions are not
|
||
# retained on overwrites. Tradeoff: if an adopter writes their
|
||
# final rendered mp4 to this bucket and a re-render overwrites
|
||
# the same key, the prior version is gone. Adopters who treat
|
||
# the final mp4 as user-keepable should set this to `Enabled`
|
||
# (intermediates under `renders/` still expire via the
|
||
# lifecycle rule below regardless).
|
||
Status: Suspended
|
||
LifecycleConfiguration:
|
||
Rules:
|
||
- Id: ExpireIntermediates
|
||
Status: Enabled
|
||
Prefix: renders/
|
||
# Plan tarballs and chunk outputs are intermediate artifacts.
|
||
# Users keep the final mp4 (different key prefix); the rest
|
||
# can age out after a week to keep storage costs flat.
|
||
ExpirationInDays: 7
|
||
Tags:
|
||
- Key: Project
|
||
Value: !Ref ProjectName
|
||
- Key: HyperFramesComponent
|
||
Value: lambda-renderer
|
||
|
||
# ── Single Lambda function handling all three roles ──────────────────────
|
||
RenderFunction:
|
||
Type: AWS::Serverless::Function
|
||
Properties:
|
||
FunctionName: !Sub "${ProjectName}-render"
|
||
Description: >-
|
||
HyperFrames distributed render handler. Dispatches on event.Action.
|
||
Handler: handler.handler
|
||
# Local path is resolved by `sam build` + `sam deploy --resolve-s3`
|
||
# (or `--s3-bucket`); the resulting CodeUri rewrites to s3://.
|
||
CodeUri: ../../packages/aws-lambda/dist/handler.zip
|
||
PackageType: Zip
|
||
ReservedConcurrentExecutions: !If
|
||
- HasReservedConcurrency
|
||
- !Ref ReservedConcurrency
|
||
- !Ref AWS::NoValue
|
||
EphemeralStorage:
|
||
Size: 10240
|
||
Environment:
|
||
Variables:
|
||
# Lambda's Node 22 runtime sets these by default; explicit for
|
||
# clarity + so users can override during local SAM invoke.
|
||
TMPDIR: /tmp
|
||
Policies:
|
||
- S3CrudPolicy:
|
||
BucketName: !Ref RenderBucket
|
||
# CloudWatch Logs perms are covered by SAM's default
|
||
# AWSLambdaBasicExecutionRole — explicit `CloudWatchLogsFullAccess`
|
||
# would be overscope (`logs:*` on `*`, including DeleteLogGroup +
|
||
# CreateExportTask). Reference templates shouldn't leak overbroad
|
||
# IAM into adopters' accounts.
|
||
|
||
# ── CloudWatch log group for the state machine ──────────────────────────
|
||
# SAM doesn't auto-create one when `LoggingConfiguration` is set, so we
|
||
# define it explicitly — that way the IAM grant on the state-machine
|
||
# role has a destination to write to.
|
||
RenderStateMachineLogGroup:
|
||
Type: AWS::Logs::LogGroup
|
||
Properties:
|
||
LogGroupName: !Sub "/aws/states/${ProjectName}-render"
|
||
RetentionInDays: 30
|
||
|
||
# ── Step Functions state machine: Plan → Map(N) RenderChunk → Assemble ──
|
||
RenderStateMachine:
|
||
Type: AWS::Serverless::StateMachine
|
||
Properties:
|
||
Name: !Sub "${ProjectName}-render"
|
||
Type: STANDARD
|
||
Tracing:
|
||
Enabled: true
|
||
Logging:
|
||
# Without this, the `WriteCloudwatchLogs` grant on the state
|
||
# machine role would be unused — operators would see zero
|
||
# execution history outside the Step Functions console.
|
||
# `Level: ERROR` keeps log volume low; bump to `ALL` for
|
||
# heavy debugging.
|
||
Level: ERROR
|
||
IncludeExecutionData: false
|
||
Destinations:
|
||
- CloudWatchLogsLogGroup:
|
||
LogGroupArn: !GetAtt RenderStateMachineLogGroup.Arn
|
||
Definition:
|
||
Comment: >-
|
||
HyperFrames distributed render orchestration: Plan → Map(N)
|
||
RenderChunk → Assemble.
|
||
# Defensive 1-hour ceiling on the whole choreography. The
|
||
# individual states already have retries + per-task timeouts;
|
||
# this catches pathological runaways (Plan-retry storm,
|
||
# stuck-state-machine bugs) at the top before per-task budgets
|
||
# compound into a multi-hour execution. The longest legitimate
|
||
# render observed in PR 880's eval was ~3 minutes.
|
||
TimeoutSeconds: 3600
|
||
StartAt: Plan
|
||
States:
|
||
Plan:
|
||
Type: Task
|
||
Resource: arn:aws:states:::lambda:invoke
|
||
Parameters:
|
||
FunctionName: !GetAtt RenderFunction.Arn
|
||
Payload:
|
||
Action: plan
|
||
ProjectS3Uri.$: "$.ProjectS3Uri"
|
||
PlanOutputS3Prefix.$: "$.PlanOutputS3Prefix"
|
||
Config.$: "$.Config"
|
||
ResultSelector:
|
||
PlanS3Uri.$: "$.Payload.PlanS3Uri"
|
||
PlanHash.$: "$.Payload.PlanHash"
|
||
ChunkCount.$: "$.Payload.ChunkCount"
|
||
Format.$: "$.Payload.Format"
|
||
HasAudio.$: "$.Payload.HasAudio"
|
||
AudioS3Uri.$: "$.Payload.AudioS3Uri"
|
||
ResultPath: $.Plan
|
||
Retry:
|
||
- ErrorEquals:
|
||
# These error names are thrown by the producer's plan
|
||
# stage when retrying can never help — version skew,
|
||
# determinism violations, GPU misconfiguration, font
|
||
# fetch failures, plan-size cap, unsupported format.
|
||
# Fail fast rather than burning ~120s of retry budget.
|
||
- FFMPEG_VERSION_MISMATCH
|
||
- PLAN_HASH_MISMATCH
|
||
- BROWSER_GPU_NOT_SOFTWARE
|
||
- FONT_FETCH_FAILED
|
||
- PLAN_TOO_LARGE
|
||
- FORMAT_NOT_SUPPORTED_IN_DISTRIBUTED
|
||
MaxAttempts: 0
|
||
- ErrorEquals: [States.ALL]
|
||
IntervalSeconds: 2
|
||
MaxAttempts: 4
|
||
BackoffRate: 2
|
||
MaxDelaySeconds: 60
|
||
Next: BuildChunkList
|
||
|
||
BuildChunkList:
|
||
# Translate ChunkCount into an array `[0, 1, ..., N-1]` so the
|
||
# Map state below has something to iterate. Range is the
|
||
# idiomatic Step Functions intrinsic for this; no Lambda call
|
||
# required.
|
||
Type: Pass
|
||
Parameters:
|
||
ChunkIndexes.$: "States.ArrayRange(0, States.MathAdd($.Plan.ChunkCount, -1), 1)"
|
||
ResultPath: $.Iterator
|
||
Next: AssertChunkCount
|
||
|
||
AssertChunkCount:
|
||
# Defensive gate: `resolveChunkPlan` guarantees ChunkCount ≥ 1,
|
||
# but if some future regression let a zero-chunk plan through,
|
||
# `RenderChunks` (Map state) would iterate zero times and
|
||
# `Assemble` would receive an empty `ChunkS3Uris` array — silently
|
||
# producing an empty output. Fail fast instead.
|
||
Type: Choice
|
||
Choices:
|
||
- Variable: $.Plan.ChunkCount
|
||
NumericGreaterThan: 0
|
||
Next: RenderChunks
|
||
Default: PlanProducedZeroChunks
|
||
|
||
PlanProducedZeroChunks:
|
||
Type: Fail
|
||
Error: PLAN_TOO_LARGE
|
||
Cause: Plan returned ChunkCount=0 — non-retryable producer-side invariant violation.
|
||
|
||
RenderChunks:
|
||
Type: Map
|
||
ItemsPath: $.Iterator.ChunkIndexes
|
||
ItemSelector:
|
||
ChunkIndex.$: "$$.Map.Item.Value"
|
||
PlanS3Uri.$: "$.Plan.PlanS3Uri"
|
||
PlanHash.$: "$.Plan.PlanHash"
|
||
ChunkOutputS3Prefix.$: "$.PlanOutputS3Prefix"
|
||
Format.$: "$.Plan.Format"
|
||
# Map fan-out cap derives from the Plan's chunkCount so
|
||
# caller-supplied `Config.maxParallelChunks` (which
|
||
# `plan()` honours when sizing the chunk list) is the
|
||
# single source of truth. A hardcoded value here would
|
||
# silently throttle adopters who scale up the chunk count
|
||
# in their event payload.
|
||
MaxConcurrencyPath: $.Plan.ChunkCount
|
||
ResultPath: $.Chunks
|
||
ItemProcessor:
|
||
ProcessorConfig:
|
||
Mode: INLINE
|
||
StartAt: RenderChunk
|
||
States:
|
||
RenderChunk:
|
||
Type: Task
|
||
Resource: arn:aws:states:::lambda:invoke
|
||
Parameters:
|
||
FunctionName: !GetAtt RenderFunction.Arn
|
||
Payload:
|
||
Action: renderChunk
|
||
ChunkIndex.$: "$.ChunkIndex"
|
||
PlanS3Uri.$: "$.PlanS3Uri"
|
||
PlanHash.$: "$.PlanHash"
|
||
ChunkOutputS3Prefix.$: "$.ChunkOutputS3Prefix"
|
||
Format.$: "$.Format"
|
||
ResultSelector:
|
||
ChunkS3Uri.$: "$.Payload.ChunkS3Uri"
|
||
ChunkIndex.$: "$.Payload.ChunkIndex"
|
||
Sha256.$: "$.Payload.Sha256"
|
||
Retry:
|
||
- ErrorEquals:
|
||
- FFMPEG_VERSION_MISMATCH
|
||
- PLAN_HASH_MISMATCH
|
||
- BROWSER_GPU_NOT_SOFTWARE
|
||
MaxAttempts: 0
|
||
- ErrorEquals: [States.ALL]
|
||
IntervalSeconds: 2
|
||
MaxAttempts: 4
|
||
BackoffRate: 2
|
||
MaxDelaySeconds: 60
|
||
End: true
|
||
Next: Assemble
|
||
|
||
Assemble:
|
||
Type: Task
|
||
Resource: arn:aws:states:::lambda:invoke
|
||
Parameters:
|
||
FunctionName: !GetAtt RenderFunction.Arn
|
||
Payload:
|
||
Action: assemble
|
||
PlanS3Uri.$: "$.Plan.PlanS3Uri"
|
||
ChunkS3Uris.$: "$.Chunks[*].ChunkS3Uri"
|
||
AudioS3Uri.$: "$.Plan.AudioS3Uri"
|
||
OutputS3Uri.$: "$.OutputS3Uri"
|
||
Format.$: "$.Plan.Format"
|
||
ResultSelector:
|
||
OutputS3Uri.$: "$.Payload.OutputS3Uri"
|
||
FramesEncoded.$: "$.Payload.FramesEncoded"
|
||
FileSize.$: "$.Payload.FileSize"
|
||
ResultPath: $.Output
|
||
Retry:
|
||
- ErrorEquals:
|
||
# Same non-retryable error names as the Plan state's
|
||
# gate — these surface at assemble time too because
|
||
# ffmpeg-driven concat picks up version drift and we
|
||
# re-verify plan hash + format at assemble. Skip the
|
||
# retry storm; fail fast.
|
||
- FFMPEG_VERSION_MISMATCH
|
||
- PLAN_HASH_MISMATCH
|
||
- FORMAT_NOT_SUPPORTED_IN_DISTRIBUTED
|
||
MaxAttempts: 0
|
||
- ErrorEquals: [States.ALL]
|
||
IntervalSeconds: 2
|
||
MaxAttempts: 4
|
||
BackoffRate: 2
|
||
MaxDelaySeconds: 60
|
||
End: true
|
||
Role: !GetAtt RenderStateMachineRole.Arn
|
||
|
||
RenderStateMachineRole:
|
||
Type: AWS::IAM::Role
|
||
Properties:
|
||
AssumeRolePolicyDocument:
|
||
Version: "2012-10-17"
|
||
Statement:
|
||
- Effect: Allow
|
||
Principal:
|
||
Service: states.amazonaws.com
|
||
Action: sts:AssumeRole
|
||
Policies:
|
||
- PolicyName: InvokeRenderFunction
|
||
PolicyDocument:
|
||
Version: "2012-10-17"
|
||
Statement:
|
||
- Effect: Allow
|
||
Action: lambda:InvokeFunction
|
||
Resource: !GetAtt RenderFunction.Arn
|
||
- PolicyName: WriteCloudwatchLogs
|
||
PolicyDocument:
|
||
Version: "2012-10-17"
|
||
Statement:
|
||
- Effect: Allow
|
||
Action:
|
||
- logs:CreateLogDelivery
|
||
- logs:GetLogDelivery
|
||
- logs:UpdateLogDelivery
|
||
- logs:DeleteLogDelivery
|
||
- logs:ListLogDeliveries
|
||
- logs:PutResourcePolicy
|
||
- logs:DescribeResourcePolicies
|
||
- logs:DescribeLogGroups
|
||
Resource: "*"
|
||
- PolicyName: XRayTracing
|
||
PolicyDocument:
|
||
Version: "2012-10-17"
|
||
Statement:
|
||
- Effect: Allow
|
||
Action:
|
||
- xray:PutTraceSegments
|
||
- xray:PutTelemetryRecords
|
||
Resource: "*"
|
||
|
||
# ── CloudWatch alarm: runaway chunk invocations ─────────────────────────
|
||
RenderChunkInvocationAlarm:
|
||
Type: AWS::CloudWatch::Alarm
|
||
Properties:
|
||
AlarmName: !Sub "${ProjectName}-runaway-chunk-invocations"
|
||
AlarmDescription: >-
|
||
Fires if RenderChunk Lambda invocations exceed the configured
|
||
threshold in a 1-hour window. The Map state's MaxConcurrency cap
|
||
protects against simultaneous fan-out, but a runaway state
|
||
machine that triggers many sequential renders would still rack
|
||
up cost; this alarm catches that pattern.
|
||
Namespace: AWS/Lambda
|
||
MetricName: Invocations
|
||
Dimensions:
|
||
- Name: FunctionName
|
||
Value: !Ref RenderFunction
|
||
Statistic: Sum
|
||
Period: 3600
|
||
EvaluationPeriods: 1
|
||
Threshold: !Ref ChunkInvocationAlarmThreshold
|
||
ComparisonOperator: GreaterThanThreshold
|
||
TreatMissingData: notBreaching
|
||
|
||
# ── CloudWatch alarm: Lambda function errors ────────────────────────────
|
||
# Fires on any non-zero error rate. The invocation alarm above catches
|
||
# *too many calls*; this catches *calls that failed*. Without it,
|
||
# silent per-chunk failures (a non-retryable error inside the
|
||
# producer) would only surface by reading Step Functions execution
|
||
# history.
|
||
RenderFunctionErrorsAlarm:
|
||
Type: AWS::CloudWatch::Alarm
|
||
Properties:
|
||
AlarmName: !Sub "${ProjectName}-render-function-errors"
|
||
AlarmDescription: >-
|
||
Fires if the render Lambda reports any errors in a 5-minute
|
||
window. Set EvaluationPeriods=1 so a single failure pages.
|
||
Namespace: AWS/Lambda
|
||
MetricName: Errors
|
||
Dimensions:
|
||
- Name: FunctionName
|
||
Value: !Ref RenderFunction
|
||
Statistic: Sum
|
||
Period: 300
|
||
EvaluationPeriods: 1
|
||
Threshold: 1
|
||
ComparisonOperator: GreaterThanOrEqualToThreshold
|
||
TreatMissingData: notBreaching
|
||
|
||
# ── CloudWatch alarm: Step Functions execution failures ─────────────────
|
||
# Fires when a state-machine execution reaches a terminal failure
|
||
# state (typed non-retryable, retry-exhausted, or top-level timeout).
|
||
# Complementary to the Lambda Errors alarm: SFN failures include
|
||
# Choice-state Fail branches (PlanProducedZeroChunks) that bypass
|
||
# Lambda entirely, plus retry-exhaustion of transient errors that
|
||
# individual Lambda invocations counted as successful "retries".
|
||
RenderStateMachineFailedAlarm:
|
||
Type: AWS::CloudWatch::Alarm
|
||
Properties:
|
||
AlarmName: !Sub "${ProjectName}-render-state-machine-failed"
|
||
AlarmDescription: >-
|
||
Fires when the render state machine reports a failed
|
||
execution. Catches retry-exhaustion + typed non-retryable +
|
||
TimeoutSeconds cases that the Lambda Errors metric misses.
|
||
Namespace: AWS/States
|
||
MetricName: ExecutionsFailed
|
||
Dimensions:
|
||
- Name: StateMachineArn
|
||
Value: !Ref RenderStateMachine
|
||
Statistic: Sum
|
||
Period: 300
|
||
EvaluationPeriods: 1
|
||
Threshold: 1
|
||
ComparisonOperator: GreaterThanOrEqualToThreshold
|
||
TreatMissingData: notBreaching
|
||
|
||
Outputs:
|
||
RenderBucketName:
|
||
Description: S3 bucket for plan tarballs, chunk outputs, and final renders.
|
||
Value: !Ref RenderBucket
|
||
Export:
|
||
Name: !Sub "${AWS::StackName}-RenderBucket"
|
||
|
||
RenderFunctionArn:
|
||
Description: ARN of the Lambda function. Pass to `aws lambda invoke` for local testing.
|
||
Value: !GetAtt RenderFunction.Arn
|
||
Export:
|
||
Name: !Sub "${AWS::StackName}-RenderFunctionArn"
|
||
|
||
RenderStateMachineArn:
|
||
Description: ARN of the Step Functions state machine. Pass to `aws stepfunctions start-execution`.
|
||
Value: !Ref RenderStateMachine
|
||
Export:
|
||
Name: !Sub "${AWS::StackName}-RenderStateMachineArn"
|