Help › Init · version 2 ·
tags
#help #lifecycle
order
110
description
the init page: what it is, the lifecycle messages it handles, declaring crons, examples

Help: the init page✎ edit

A project's init page is where it sets itself up, in rules rather than in settings screens: what it needs when it starts, the jobs it runs on a schedule, and how it reacts to what happens to its data. It's one topic, Settings:Init, and d2 sends it messages as things happen.

What it is✎ edit

  • One page per project: Settings:Init. Open it from Admin → Init. A new project has none: the Init card says so and offers Create the init page, which makes a starter page with a short explanation and one rule.
  • Compiled like a spec: its frontmatter has tags: spec, so the lines starting with $ are rules ($when, $class…) and the rest is notes for people. Save it and it's compiled at once; a mistake is shown when you save.
  • Only mods and admins edit it, like every Settings page. Members can read it.
  • Its rules run as flows: each message it handles runs as a flow you can open under Flows. A failing rule shows there and in the audit log, and never stops the project from loading.
  • Sent only when handled: d2 raises a message in your project only if a rule there takes it, so a message you don't handle costs nothing and leaves no flow behind.

The lifecycle messages✎ edit

The ones an init page usually handles (every message, and what it carries: LifecycleMessages):

  • diesel.project.on.init: the project was loaded (d2 started or was updated) or this page was saved. The place to declare what the project needs, since it runs again whenever you change the page.
  • diesel.project.on.created: once, when the project was made.
  • diesel.project.on.released (version): after a release (Admin → Project).
  • diesel.entity.on.created, updated, deleted (category, key): an object was added, changed or deleted, by a form, the API, your AI or a flow. category is its class; pick the ones a rule is for with a condition: if (category is "Holding").
  • People, pages, the pipeline and quotas have their own messages too (a join request, a page published, an item done, a limit reached): see LifecycleMessages.

Two safety rules: the writes a rule makes while handling an object's message don't send more of them, so a rule can't loop on its own writes; and your rules can't send d2's own messages themselves (E_NATIVE), only handle them.

Declaring crons✎ edit

A cron sends one of your messages on a schedule. Declare them in diesel.project.on.init, so they're made on every start and follow the page whenever you change it:

$when diesel.project.on.init {
  diesel.cron(name = "morning-prices", schedule = "0 7 * * 1-5", tz = "America/Toronto", msg = "portfolio.refresh", args = {})
  diesel.cron(name = "nightly-tidy", schedule = "daily 03:15", msg = "portfolio.tidy")
}

$when portfolio.refresh {
  log (msg = "refreshing prices")
}
  • The schedule is a 5-field cron (0 7 * * 1-5), every 15m, hourly or daily 03:15, in UTC unless tz names a time zone. A bad schedule or zone fails the flow with E_ARG.
  • The same name again replaces it with the new schedule; the same cron sent again unchanged stays as it was, on or off. diesel.cron.remove (name) deletes one, diesel.cron.list () lists them.
  • msg is your own message, never one of d2's; when it's due it's sent in the project with args, as a flow.
  • Limits: how many crons a project may have, and how often at most, depend on its plan (Admin → Quotas); over them the flow fails with E_QUOTA.
  • Watching them: the Crons page (/crons, a Toolbox tile) lists them with their next and last runs; admins run one now or turn it on or off. After 5 failures in a row a cron is switched off and the owner gets a notice.

Examples✎ edit

Record each start and each release:

$class Stats (@key id: String, started: String?, lastRelease: String?)

$when diesel.project.on.init {
  s = dom.find(cls = "Stats", key = "main") ?? {id: "main"}
  dom.upsert(cls = "Stats", entity = s + {started: isoDate(now())})
}

$when diesel.project.on.released (version) {
  s = dom.find(cls = "Stats", key = "main") ?? {id: "main"}
  dom.upsert(cls = "Stats", entity = s + {lastRelease: version})
}

Tell the owner when an order comes in:

$when diesel.entity.on.created (category, key) if (category is "Order") {
  diesel.user.notify (to = "razie", text = "New order " + key, code = "new-order", link = "/dom/Order/" + key)
}

A weekly report, as a cron:

$when diesel.project.on.init {
  diesel.cron(name = "weekly-report", schedule = "0 8 * * 1", tz = "America/Toronto", msg = "report.weekly")
}

$when report.weekly {
  diesel.ai.pipeline.create (title = "Write the weekly report", forRole = "user", forName = "razie", kind = "admin")
}

A complete page to copy from, with a running count of objects: InitExample. The expressions used in rules: Expressions.

Good to know✎ edit

  • Keep diesel.project.on.init safe to run again: it runs on every start and every save of the page, so write it to set things (upsert, declare a cron by name) rather than add them.
  • A rule acts as the project: requests it sends (notices, emails, pipeline items) go only to the project's members and count against the project's quotas.
  • Scratch runs don't count: the fiddle and runs that don't write send no object messages, and nothing a fiddle run asks for is sent.