Scheduled Tables
Scheduled tables are private by default and reserve scheduledId and
scheduledAt. A scheduled endpoint receives { data: table.row }.
import * as Effect from "effect/Effect"import * as Stdb from "effect-spacetimedb"
const reminderSchedule = Stdb.scheduledTable("reminderSchedule", { columns: { note: Stdb.string(), },})
const Reminders = Stdb.StdbGroup.make("Reminders").add( Stdb.StdbFn.scheduledProcedure("reminderFire", { table: reminderSchedule, }),)
const Module = Stdb.StdbModule.make("app") .addTables(reminderSchedule) .add(Reminders)
const RemindersLive = Stdb.StdbBuilder.group(Module, "Reminders", { reminderFire: Effect.fn(function* ({ data }) { yield* Effect.log(`reminder: ${data.note}`) }),})To seed schedule rows inside a reducer or transaction body, use the generated
.schedule(...) helper. It fills the auto-increment sentinel for you.
yield* db.reminderSchedule.schedule({ scheduledAt: Stdb.ScheduleAt.interval("5 minutes"), note: "wake up",})| Schedule form | Host behavior |
|---|---|
Stdb.ScheduleAt.at(...) or after(...) | One-shot row. Reducers consume it after execution; procedures consume it before execution. |
Stdb.ScheduleAt.interval(...) | Row persists and re-fires until deleted. |
For fixed wall-clock or tick alignment, prefer self-rescheduling one-shot rows:
handle a Time row, insert the next Time row, then return. Use Interval
when simple persistent re-fire spacing is enough.
Stdb.scheduledTable(...) creates the reserved
scheduled_id/scheduled_at columns and StdbFn.scheduledReducer(...) or
StdbFn.scheduledProcedure(...) binds exactly one typed handler to the table.
Not affiliated with SpacetimeDB (Clockwork Laboratories) or Effect (Effectful Technologies).