Skip to content

Roadmap: portable durable scheduling #37

Description

@cardmagic

PRD: portable durable scheduling

Status: Proposed
Owner: Solid Objects maintainers

Problem and users

Actor authors need work to happen after a delay or on a recurring cadence even when no request is active. Each adapter currently exposes different scheduling primitives and edge cases. Users are application developers building expiry, renewal, retry, and maintenance workflows.

Outcome and success measures

An actor author can schedule, inspect, reschedule, and cancel durable work without knowing whether the adapter uses alarms, a scheduler process, or a database. Every production adapter passes the same conformance suite for idempotency, missed runs, cancellation, and recovery. Scheduled work has no silent loss and exposes its current status.

Non-goals

  • Exposing provider-specific alarm APIs.
  • Guaranteeing exactly-once execution; delivery remains at least once.
  • Replacing general-purpose queues or cron systems.

Requirements

  • SCHED-001: The API shall create a named schedule owned by one actor with an operation, JSON arguments, and a first-run time.
  • SCHED-002: A name shall identify at most one active schedule per actor; rescheduling shall replace its next occurrence atomically.
  • SCHED-003: The API shall cancel a schedule idempotently and report whether a schedule was removed.
  • SCHED-004: The API shall support one-shot and recurring schedules with an explicit interval or recurrence policy.
  • SCHED-005: The API shall define missed-run policies (run_once, skip, or catch_up) and persist the selected policy.
  • SCHED-006: Schedule execution shall use normal actor mailbox, authorization, retry, dead-letter, and idempotency semantics.
  • SCHED-007: Inspection shall return status, next run, last run, attempt, and failure information without mutating actor state.
  • SCHED-008: Adapters shall recover scheduled work after process, object, or host restart.

Acceptance criteria

  • Conformance tests cover create, replace, cancel, recurring execution, each missed-run policy, restart recovery, authorization failure, and duplicate delivery.
  • A schedule can never execute after a successful cancellation that preceded its claim.
  • Documentation includes time-zone, clock-skew, retention, and retry behavior.

Risks and rollout

The first release should extend reminders rather than add a second scheduler model. Ship behind capability detection, migrate one adapter at a time, and publish timing guarantees before enabling recurring schedules by default.

Actor-centric API shape

The exact method names are illustrative; the actor reference is the primary object.

const cart = ShoppingCart.ref('demo-cart')

const schedule = await cart.schedule('clear-cart', {
  operation: 'clear',
  arguments: {},
  runAt: new Date(Date.now() + 5_000),
  missedRun: 'run_once',
})

await cart.reschedule(schedule, { runAt: new Date(Date.now() + 60_000) })
await cart.cancelSchedule('clear-cart')
const status = await cart.scheduleStatus('clear-cart')

The adapter may use an alarm, database scheduler, or worker process behind this actor-owned API.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions