Files
FlociClone/docs/services/scheduler.md
2026-09-22 08:57:00 -04:00

8.2 KiB

EventBridge Scheduler

Protocol: REST JSON Endpoint: http://localhost:4566/

Supported Actions

Action Method Path Description
CreateScheduleGroup POST /schedule-groups/{Name} Create a schedule group
GetScheduleGroup GET /schedule-groups/{Name} Get schedule group details
DeleteScheduleGroup DELETE /schedule-groups/{Name} Delete a schedule group and its schedules
ListScheduleGroups GET /schedule-groups List schedule groups
CreateSchedule POST /schedules/{Name} Create a schedule
GetSchedule GET /schedules/{Name} Get schedule details
UpdateSchedule PUT /schedules/{Name} Update a schedule
DeleteSchedule DELETE /schedules/{Name} Delete a schedule
ListSchedules GET /schedules List schedules
TagResource POST /tags/{ResourceArn} Add tags to a schedule group
UntagResource DELETE /tags/{ResourceArn}?TagKeys=... Remove tags from a schedule group
ListTagsForResource GET /tags/{ResourceArn} List tags on a schedule group

Schedule Invocation

When floci.services.scheduler.invocation-enabled is true (the default), a background dispatcher fires schedule targets on time. Supported expressions:

  • at(YYYY-MM-DDTHH:mm:ss) — one-time fire; honors ScheduleExpressionTimezone (default UTC) and ActionAfterCompletion=DELETE.
  • rate(N unit) — repeating fire (minutes, hours, days, weeks).
  • cron(minute hour day-of-month month day-of-week year) — AWS 6-field cron; honors ScheduleExpressionTimezone. Day-of-week is 1-7 or SUN-SAT, so 2 is Monday and cron(30 2 ? * 2#1 *) is the first Monday of the month.

State=DISABLED schedules and schedules outside their StartDate/EndDate window are skipped. The dispatcher ticks every floci.services.scheduler.tick-interval-seconds (default 10).

Supported target types: SQS, Lambda, SNS, ECS RunTask, EventBridge PutEvents, and unqualified Step Functions state machine ARNs. Templated targets receive the schedule target's Input. When Input is absent, Floci delivers the default notification AWS sends: an EventBridge-style event with detail-type Scheduled Event, source aws.scheduler, the schedule's account, region, and ARN (in resources), the occurrence time, and detail set to the string "{}". The event id is stable per occurrence, so retries and the dead-letter body carry the same event. A Step Functions target starts an asynchronous execution with that payload as its input. Scheduler delivery succeeds when StartExecution is accepted; a later workflow failure does not trigger Scheduler retries.

CreateSchedule and UpdateSchedule reject a non-JSON Input for Lambda, Step Functions, and EventBridge targets with a ValidationException, as AWS does. A blank Input, or one with text after the JSON value such as {} garbage, is rejected the same way. SQS and SNS targets accept any text, and the Input of a universal (aws-sdk) target is only checked when the schedule is invoked.

Retries and dead-letter queues

A failed invocation is retried after a deterministic capped exponential delay until the target's RetryPolicy is exhausted. The delay starts at 60 seconds and is capped at 86400 seconds. Missing fields use the AWS defaults: MaximumEventAgeInSeconds=86400 and MaximumRetryAttempts=185. Retries run when due, without undocumented AWS jitter. Each occurrence retries independently, so a failing occurrence does not delay later rate or cron fires. Pending retries are in memory and are dropped when the process restarts, or when a schedule is disabled, updated, or deleted. Targets Floci cannot deliver to count as failed invocations. Lambda targets are invoked asynchronously, so function errors are not retried by the scheduler.

When an occurrence is exhausted and DeadLetterConfig.Arn names a standard SQS queue, Floci sends the fully materialized target request as a JSON body to that queue with the message attributes ERROR_CODE, ERROR_MESSAGE, EXECUTION_ID, EXHAUSTED_RETRY_CONDITION, IS_PAYLOAD_TRUNCATED, RETRY_ATTEMPTS, SCHEDULED_TIME, SCHEDULE_ARN, and TARGET_ARN. FIFO queues and non-SQS ARNs are logged and skipped. An at schedule with ActionAfterCompletion=DELETE is deleted once its occurrence is delivered or exhausted. The body uses the request fields of the target service's API: SQS MessageBody and QueueUrl (plus MessageGroupId for FIFO queues), Lambda FunctionName, InvocationType, and Payload, SNS TopicArn and Message, Step Functions stateMachineArn and input, EventBridge Entries, and ECS cluster, taskDefinition, and count with the configured launch type, group, and network configuration. Non-JSON input of a universal target is encoded as a JSON string field.

Configuration

Variable Default Description
FLOCI_SERVICES_SCHEDULER_ENABLED true Enable or disable the service
FLOCI_SERVICES_SCHEDULER_INVOCATION_ENABLED true Run the background dispatcher that fires scheduled targets (false = CRUD-only)
FLOCI_SERVICES_SCHEDULER_TICK_INTERVAL_SECONDS 10 How often the dispatcher scans for due schedules (seconds)

Not Yet Supported

  • FlexibleTimeWindow jitter (fires deterministically at the scheduled time)
  • NextToken-based pagination for List operations

Examples

export AWS_ENDPOINT_URL=http://localhost:4566

# Create a schedule group
aws scheduler create-schedule-group \
  --name my-group \
  --endpoint-url $AWS_ENDPOINT_URL

# List schedule groups
aws scheduler list-schedule-groups \
  --endpoint-url $AWS_ENDPOINT_URL

# Create a schedule in the default group
aws scheduler create-schedule \
  --name my-schedule \
  --schedule-expression "rate(1 hour)" \
  --flexible-time-window '{"Mode":"OFF"}' \
  --target '{
    "Arn": "arn:aws:lambda:us-east-1:000000000000:function:my-func",
    "RoleArn": "arn:aws:iam::000000000000:role/scheduler-role"
  }' \
  --endpoint-url $AWS_ENDPOINT_URL

# Create a schedule with retry policy and dead-letter queue
aws scheduler create-schedule \
  --name my-resilient-schedule \
  --schedule-expression "rate(5 minutes)" \
  --flexible-time-window '{"Mode":"FLEXIBLE","MaximumWindowInMinutes":10}' \
  --target '{
    "Arn": "arn:aws:sqs:us-east-1:000000000000:my-queue",
    "RoleArn": "arn:aws:iam::000000000000:role/scheduler-role",
    "RetryPolicy": {"MaximumEventAgeInSeconds":3600,"MaximumRetryAttempts":5},
    "DeadLetterConfig": {"Arn":"arn:aws:sqs:us-east-1:000000000000:my-dlq"}
  }' \
  --endpoint-url $AWS_ENDPOINT_URL

# Get a schedule
aws scheduler get-schedule \
  --name my-schedule \
  --endpoint-url $AWS_ENDPOINT_URL

# Update a schedule
aws scheduler update-schedule \
  --name my-schedule \
  --schedule-expression "rate(30 minutes)" \
  --flexible-time-window '{"Mode":"OFF"}' \
  --target '{
    "Arn": "arn:aws:lambda:us-east-1:000000000000:function:my-func",
    "RoleArn": "arn:aws:iam::000000000000:role/scheduler-role"
  }' \
  --state DISABLED \
  --endpoint-url $AWS_ENDPOINT_URL

# Delete a schedule
aws scheduler delete-schedule \
  --name my-schedule \
  --endpoint-url $AWS_ENDPOINT_URL

# Delete a schedule group (cascades to all schedules in the group)
aws scheduler delete-schedule-group \
  --name my-group \
  --endpoint-url $AWS_ENDPOINT_URL

# Add tags to a schedule group (tags apply to schedule groups only)
aws scheduler tag-resource \
  --resource-arn arn:aws:scheduler:us-east-1:000000000000:schedule-group/my-group \
  --tags Key=env,Value=prod Key=owner,Value=Alice \
  --endpoint-url $AWS_ENDPOINT_URL

# List tags on a schedule group
aws scheduler list-tags-for-resource \
  --resource-arn arn:aws:scheduler:us-east-1:000000000000:schedule-group/my-group \
  --endpoint-url $AWS_ENDPOINT_URL

# Remove tags from a schedule group
aws scheduler untag-resource \
  --resource-arn arn:aws:scheduler:us-east-1:000000000000:schedule-group/my-group \
  --tag-keys env owner \
  --endpoint-url $AWS_ENDPOINT_URL

Default Schedule Group

A default schedule group is automatically created on first access. Schedules created without specifying a group are placed in the default group. The default group cannot be deleted.