Delay job execution with schedule_in or schedule_at. Scheduled jobs start in the :scheduled state until the scheduler promotes them to :available.
schedule_in — relative delay
Run a job N seconds from now:
{:ok, job} =
Kathikon.insert(MyApp.Workers.SendDigest, %{"user_id" => "42"},
schedule_in: 3600 # one hour
)
job.state # :scheduled
job.scheduled_at # ~1 hour from insert timeschedule_at — absolute time
Run at a specific DateTime (UTC):
send_at = DateTime.utc_now() |> DateTime.add(1, :day)
{:ok, job} =
Kathikon.insert(MyApp.Workers.SendReminder, %{"user_id" => "42"},
schedule_at: send_at
)If schedule_at is in the past, the job is inserted as :available immediately.
How promotion works
Kathikon.Scheduler ticks every scheduler_interval ms (default 1000). On each tick it runs Storage.promote_scheduled/1, which in a single Mnesia transaction:
- Finds all
:scheduledjobs wherescheduled_at <= now - Sets
state: :availableandavailable_at: now - Returns the count promoted
Batch promotion prevents sibling scheduled jobs from becoming claimable one-by-one in priority order before their peers are ready.
Inspecting scheduled jobs
{:ok, job} = Kathikon.fetch(job_id)
job.state # :scheduled until promotion
# After scheduler tick:
{:ok, job} = Kathikon.fetch(job_id)
job.state # :availableScheduling + priority
# VIP digest runs before standard digest when both become due together
Kathikon.insert(VipDigestWorker, %{}, schedule_in: 60, priority: 10, queue: :email)
Kathikon.insert(DigestWorker, %{}, schedule_in: 60, priority: 1, queue: :email)Cancelling scheduled jobs
Scheduled jobs can be cancelled before they run:
{:ok, _} = Kathikon.cancel(job.id)See Cancellation.
Configuration
config :kathikon, scheduler_interval: 1_000 # ms between promotion ticksLower values reduce scheduling latency; higher values reduce Mnesia load.
Not yet available
Cron (Kathikon.Cron) — recurring schedules — is planned for Phase 3. Until then, re-enqueue from perform/1 or use an external scheduler to call Kathikon.insert/3.