# EventBridge schedules. # # Every schedule is an EST/EDT pair firing the same function one hour apart in # UTC: EventBridge cron has no timezone. Both fire year-round and the handlers # are idempotent, so the run that lands in the wrong offset is a harmless no-op. # Do not "deduplicate" a pair. # # Rule names are stable and hand-chosen (the retired SAM stack used generated # physical IDs). They are load-bearing: each aws_lambda_permission grants # events.amazonaws.com on the matching rule ARN. locals { schedules = { "close-form-est" = { description = "Close form Thursday 11:59pm EST (04:59 UTC Friday)" schedule = "cron(59 4 ? * FRI *)" function_arn = aws_lambda_function.close_form.arn function_name = aws_lambda_function.close_form.function_name input = null } "close-form-edt" = { description = "Close form Thursday 11:59pm EDT (03:59 UTC Friday)" schedule = "cron(59 3 ? * FRI *)" function_arn = aws_lambda_function.close_form.arn function_name = aws_lambda_function.close_form.function_name input = null } "reminder-est" = { description = "DM reminders Thursday 10am EST (15:00 UTC)" schedule = "cron(0 15 ? * THU *)" function_arn = aws_lambda_function.slack_notifier.arn function_name = aws_lambda_function.slack_notifier.function_name input = "{\"event\": \"reminder\"}" } "reminder-edt" = { description = "DM reminders Thursday 10am EDT (14:00 UTC)" schedule = "cron(0 14 ? * THU *)" function_arn = aws_lambda_function.slack_notifier.arn function_name = aws_lambda_function.slack_notifier.function_name input = "{\"event\": \"reminder\"}" } "sync-roster-est" = { description = "Sync roster Monday 6:55am EST (11:55 UTC), before menu publish" schedule = "cron(55 11 ? * MON *)" function_arn = aws_lambda_function.sync_roster.arn function_name = aws_lambda_function.sync_roster.function_name input = null } "sync-roster-edt" = { description = "Sync roster Monday 6:55am EDT (10:55 UTC), before menu publish" schedule = "cron(55 10 ? * MON *)" function_arn = aws_lambda_function.sync_roster.arn function_name = aws_lambda_function.sync_roster.function_name input = null } } } resource "aws_cloudwatch_event_rule" "schedule" { for_each = local.schedules name = "${local.project}-${each.key}" description = each.value.description schedule_expression = each.value.schedule state = "ENABLED" } resource "aws_cloudwatch_event_target" "schedule" { for_each = local.schedules rule = aws_cloudwatch_event_rule.schedule[each.key].name target_id = "${local.project}-${each.key}" arn = each.value.function_arn input = each.value.input } resource "aws_lambda_permission" "schedule" { for_each = local.schedules statement_id = "AllowEventBridgeInvoke-${each.key}" action = "lambda:InvokeFunction" function_name = each.value.function_name principal = "events.amazonaws.com" source_arn = aws_cloudwatch_event_rule.schedule[each.key].arn }