Skip to content

API Jobs

Dory Azar edited this page Nov 15, 2026 · 2 revisions

Jobs, notifications and mail

Caligrafy Quill 2.26.0. Generated from the source by php qa/build-api-reference.php; the guides explain how to use these classes, this reference says exactly what each public method takes and returns. Back to the API reference.

Scheduled jobs, background jobs, web push and email notifications, mail.

Class What it is
Caligrafy\Scheduler An app declares its jobs in application/config/schedule.php: each one calls one capability with fixed inputs on a fixed rhythm (every: 1m...1d, or a five-field cron in a timezone).
Caligrafy\Queue A job is a capability and its input, kept in the caligrafy_jobs table (php caligrafer.php platform install, or the deploy step, creates it).
Caligrafy\Notify Notify::user($userId, ['title' => ..., 'body' => ..., 'url' => ..., 'tag' => ..., 'urgency' => ...]) sends to every channel the user turned on and logs the result (caligrafy_notifications: never the body; kept 30 days): ...
Caligrafy\Mail The Mail class handles all emails sent from the framework

class Caligrafy\Scheduler

namespace Caligrafy;

class Scheduler

Source: framework/core/Scheduler.php:22

Class Scheduler An app declares its jobs in application/config/schedule.php: each one calls one capability with fixed inputs on a fixed rhythm (every: 1m...1d, or a five-field cron in a timezone). The framework validates the file, runs the jobs locally (php caligrafer.php schedule due / work) and prints the listing Caligrafy Cloud runs in production (schedule list --json, version 1).

A run: one at a time per job (a database lock), in a child process stopped at its timeout, with full access like the command line (Context::system: actor type schedule, actor id the job's name), recorded in caligrafy_job_runs (kept 30 days). Exit codes: 0 ok, 1 the capability failed or timed out, 2 the schedule file is invalid, 3 skipped.

Constants

  • FILE = 'application/config/schedule.php'
  • TABLE = 'caligrafy_job_runs'
  • LISTING_VERSION = 1
  • EVERY = ...
  • DEFAULT_TIMEOUT = 55
  • MAX_TIMEOUT = 300
  • KEEP_DAYS = 30
  • FIELDS = array('name', 'capability', 'input', 'every', 'cron', 'timezone', 'timeout', 'enabled')
  • OK = 0
  • FAILED = 1
  • INVALID = 2
  • SKIPPED = 3

Methods

->__construct()

public function __construct($root = '.')

No doc comment.

Parameters

  • $root, default '.'

Source: framework/core/Scheduler.php:42

->jobs()

public function jobs($capabilities = true)

The jobs of the project's schedule file, validated and completed (an empty list when there is no file)

Parameters

  • $capabilities bool, default true: also check that each capability exists

  • @throws \InvalidArgumentException with every problem, one per line

Source: framework/core/Scheduler.php:55

Scheduler::validate()

public static function validate(array $declared, ?callable $exists = null)

Validates declared jobs and completes them (cron from every, timezone, timeout, enabled)

Parameters

  • $declared array: the array the schedule file returns
  • $exists ?callable, default null: tells whether a capability exists (null: not checked)

Returns array: the jobs, in the file's order

  • @throws \InvalidArgumentException with every problem, one per line

Source: framework/core/Scheduler.php:75

Scheduler::listing()

public static function listing(array $jobs)

The listing Caligrafy Cloud reads at deploy time (schedule list --json): the enabled jobs, every as cron

Parameters

  • $jobs array

Source: framework/core/Scheduler.php:149

Scheduler::parse()

public static function parse($cron)

The allowed values of each field of a five-field cron (minute hour day-of-month month day-of-week)

Parameters

  • $cron

Returns array: five sorted lists of integers (day of week: 0-6, Sunday is 0 or 7)

  • @throws \InvalidArgumentException

Source: framework/core/Scheduler.php:168

Scheduler::isDue()

public static function isDue($cron, \DateTimeInterface $at, $timezone = 'UTC')

Whether a cron is due at a time (to the minute), read in a timezone. When both the day of the month and the day of the week are restricted, either one matches (as in cron)

Parameters

  • $cron
  • $at \DateTimeInterface
  • $timezone, default 'UTC'

Source: framework/core/Scheduler.php:225

->run()

public function run($name, ?callable $say = null, $ifDue = false)

Runs one job now: takes its lock, runs it in a child process (stopped at its timeout), records the run

Parameters

  • $name string: the job's name
  • $say ?callable, default null: prints a line
  • $ifDue bool, default false: only when the job is due this minute in its timezone (--if-due), else nothing is run or recorded

Returns int: an exit code (OK, FAILED, SKIPPED)

Source: framework/core/Scheduler.php:254

->execute()

public function execute($name)

What a run's child process does: calls the job's capability as the scheduler and prints the result as JSON

Parameters

  • $name

Returns int: OK or FAILED

Source: framework/core/Scheduler.php:286

->dueAt()

public function dueAt(\DateTimeInterface $at)

The jobs due in a minute (enabled ones only)

Parameters

  • $at \DateTimeInterface

Source: framework/core/Scheduler.php:305

->due()

public function due(?callable $say = null, ?\DateTimeInterface $at = null)

Runs every job due in the current minute, side by side, and waits for them

Parameters

  • $say ?callable, default null
  • $at ?\DateTimeInterface, default null

Returns int: OK when every run is ok or skipped, FAILED otherwise

Source: framework/core/Scheduler.php:316

->work()

public function work(?callable $say = null)

Runs schedule due at the start of every minute until stopped (local development)

Parameters

  • $say ?callable, default null

Source: framework/core/Scheduler.php:341

Scheduler::history()

public static function history($name = null, $limit = 50)

The latest runs, newest first

Parameters

  • $name, default null
  • $limit, default 50

Source: framework/core/Scheduler.php:358

Scheduler::spawn()

public static function spawn(array $args, $root, $timeout)

Runs php caligrafer.php <args> in $root, stopped after $timeout seconds (the scheduler's jobs, the queue's jobs)

Parameters

  • $args array
  • $root
  • $timeout

Returns array: [exit code, or null when it was stopped, or false when it could not start; its output]

Source: framework/core/Scheduler.php:400

class Caligrafy\Queue

namespace Caligrafy;

class Queue

Source: framework/core/Queue.php:26

Class Queue (2.18.0)

Queue::push('send_welcome_email', ['user_id' => $id]);                       // as soon as a worker is free
Queue::push('build_report', ['month' => '2026-11'], ['delay' => 600, 'attempts' => 5, 'timeout' => 120]);

A job is a capability and its input, kept in the caligrafy_jobs table (php caligrafer.php platform install, or the deploy step, creates it). A worker runs each one in its own process, stopped at its timeout, with full access, as a scheduled job (Context::system('queue', '<capability> #<id>')): check who may ask for the work before pushing it.

Workers: php caligrafer.php queue work (a loop, on your computer or your own server), or the scheduler: a job of application/config/schedule.php on the framework's capability queue_work, every minute, which Caligrafy Cloud runs too. A failed run is tried again after 30 s, 1 min, 2 min... until its attempts are used; an input the capability refuses (invalid, not found) fails at once. Jobs are kept 7 days after they finish.

Constants

  • TABLE = 'caligrafy_jobs'
  • DEFAULT_ATTEMPTS = 3
  • DEFAULT_TIMEOUT = 60
  • MAX_TIMEOUT = 900
  • RETRY_SECONDS = 30
  • KEEP_DAYS = 7
  • NAME = '/^[a-z0-9_-]{1,40}$/'

Methods

Queue::push()

public static function push($capability, array $input = array(), array $options = array())

Adds a job

Parameters

  • $capability
  • $input array, default array()
  • $options array, default array(): delay (seconds), attempts (1-20), timeout (seconds), queue (a name, default)

Returns int: the job's id

Source: framework/core/Queue.php:41

Queue::work()

public static function work(array $options = array())

Runs jobs: until none is left (once), for $seconds, or forever

Parameters

  • $options array, default array(): queue (default), seconds (stop starting jobs after), once (stop when empty), sleep (seconds between looks when empty), root (the project), say (callable)

Returns array: counts: done, retried, failed

Source: framework/core/Queue.php:69

Queue::execute()

public static function execute($id)

The child process of a job (php caligrafer.php queue exec <id>): calls its capability, prints its answer as JSON

Parameters

  • $id

Returns int: 0 done, 1 failed (try again), 2 refused (do not try again)

Source: framework/core/Queue.php:111

Queue::jobs()

public static function jobs($status = null, $limit = 50)

Jobs, newest first

Parameters

  • $status string|null, default null: pending, running, done or failed
  • $limit, default 50

Source: framework/core/Queue.php:136

Queue::counts()

public static function counts()

How many jobs are in each state

Source: framework/core/Queue.php:150

Queue::retry()

public static function retry($id = null)

Puts failed jobs back in the queue with new attempts: one id, or all (null)

Parameters

  • $id, default null

Returns int: how many

Source: framework/core/Queue.php:163

class Caligrafy\Notify

Notify::user($userId, ['title' => ..., 'body' => ..., 'url' => ..., 'tag' => ..., 'urgency' => ...]) sends to every channel the user turned on and logs the result (caligrafy_notifications: never the body; kept 30 days): ...

Its 20 public methods have a page of their own: Caligrafy\Notify.

class Caligrafy\Mail

namespace Caligrafy;

class Mail extends \stdClass

Source: framework/core/Mail.php:24

The Mail class handles all emails sent from the framework

Methods

->__construct()

public function __construct()

No doc comment.

Source: framework/core/Mail.php:32

->sendMail()

public function sendMail($recipients, $emailContent, $from, array $headers = array())

Parameters

  • $recipients
  • $emailContent
  • $from
  • $headers array, default array(): extra headers, name => value (Notify: List-Unsubscribe, List-Unsubscribe-Post)

Source: framework/core/Mail.php:73

Caligrafy: Describe it. Approve it. Ship it. Your idea turned into a complete app: every feature built once, for web pages, Vue apps, a REST API and AI agents, and online.

Start here

Why Caligrafy: the benefits, the measurements, and what it is not yet

  1. Quickstart with Claude: describe it, approve it, ship it

    or the Quickstart: the same three steps by hand, in 5 minutes

  2. How Caligrafy works: the ideas in 5 minutes
  3. Your first capability: build a feature, page included

Capabilities

Experiences

Data and people

  1. Models
  2. Relationships
  3. Queries: filters, paging, related rows
  4. Sign-in, users and tokens

Built-in features

Put it online

Build with AI

Reference

Clone this wiki locally