Version 1 of 1 · · razie · in person · Current version

name
d3-f-engine
description
The engine — behaviour as $when rules in Spec topics, checked by stories; events, requests, web fetches, expressions, limits. Get skills only from /api/v2/skills/d3.
feature
eng
concepts
[rule, story, flow, event, request, fetch, expression]
tags
#skill #feature #d3skill #wip

d3-f-engine

Intro

Rules, stories and flows: a project's behaviour.

The engine runs a project's behaviour: $when rules in Spec: topics react to messages, strictly in order; Story: topics send messages and check what comes back. d2 raises events rules can handle, rules may send requests to d2, and fetch from the web. Rules orchestrate, tools compute. Schedules are d3-f-crons; objects d3-f-data. Examples: hello / hello, order / order. Spec: Spec › engine-plan, Spec › execution-model.

Essentials

  • R-eng-1 MUST run a rule's story before telling your person it works.
  • R-eng-2 Behaviour lives in Spec: $when rules; Story: topics only send and expect.
  • R-eng-3 NEVER send an event (….on.…) from a rule or story; only d2 raises them.
  • R-eng-4 NEVER put secrets in rules: flows can't read the vault.
  • R-eng-5 Keep flows short: they run one at a time per project, within the plan's flow time.
  • R-eng-6 Web fetches only in rules and flows — never in a computed field, table or query.

Concepts

rule

A $when declaration in a Spec: topic that runs when its message arrives and its guard holds. Also called: spec, behaviour, handler. Fields: message name, params (name: Type), guard (if (…)), body of statements.

rule_write

  • Summary: $when msg (params) if (guard) { … }, at a line start.
  • When: adding or changing behaviour.
  • Needs: the message name and its params.
  • Call: in a Spec: topic, at the start of a line or in a ```diesel fence: $when order.discount (subtotal: Float, member: Boolean) if (member) { payload = subtotal * 0.10 }.
  • Rules: Every rule whose guard holds runs, in order; each starts from the payload the one before left. Statements, one per line (or ;): a send msg (a = 1, b); x = … (this rule only); ctx.x = … (the whole flow); payload = … (what the rule gives back); if (…) { } else { } (braces required); try { } catch (e) { } with e.code, e.message; diesel.throw (code = "E_X", msg = "…"). Each rule works on its own copy of the payload: a send statement makes the reply the caller's payload; a message in an expression (total = order.price(items = xs)) returns a value and leaves the payload alone. Reads go up the call chain (the caller's variables, the flow's ctx); a rule's own x = … never changes theirs.
  • Errors: E_PARSE → fix the line.
  • Gotchas: In rules a lambda needs parentheses (xs map (x => …)), and an expression can't run onto the next line outside brackets.

rule_parse

  • Summary: check rules or a story without running them.
  • When: after writing, before a run.
  • Needs: the markdown.
  • Call: POST /api/v2/diesel/parse {source: "<markdown>"} → declarations and errors with positions.
  • Rules: —
  • Errors: E_PARSE (line, position).
  • Gotchas: —

story

A Story: topic that sends messages and states what must come back. Also called: test, scenario. Fields: $send msg (…), $val x = … (flow values), $expect cond, $expect cond if other (skipped unless other).

story_run

  • Summary: run a story on a scratch copy; data never changes.
  • When: before saying a rule works; after every rule change.
  • Needs: the story topic or its markdown.
  • Call: POST /api/v2/diesel/run {story: {topic: "Story:order"}} or {story: "<markdown>"} → ok, tests (each expect passed, failed or skipped), payload, flow (ctx values), trace, errors with lines.
  • Rules: R-eng-1. No spec → every Spec topic is used. scratch: false only for a real run from an app.
  • Errors: E_PARSE · a failed $expect → read trace and flow · E_TIMEOUT.
  • Gotchas: —

story_fiddle

  • Summary: point people to the Fiddle to run or check as they edit.
  • When: your person wants to try a story or spec themselves.
  • Needs: the topic.
  • Call: /fiddle?tab=stories&topic=Story:order runs a story; /fiddle?tab=specs&topic=Spec:order checks a spec.
  • Rules: —
  • Errors: —
  • Gotchas: —

flow

One run of messages through the rules, with its ctx and log. Also called: run. Limits: at most the plan's flow time (in the engine and inside long expressions); one at a time per project today; flows at once and API calls per plan (Settings:Quotas).

flow_view

  • Summary: what ran shows under Flows with its log.
  • When: checking what a message or event did.
  • Needs: —
  • Call: the Flows page.
  • Rules: R-eng-5.
  • Errors: E_TIMEOUT → split the flow, or move work to a cron.
  • Gotchas: —

event

A message d2 raises as things happen, named area then .on. (diesel.topic.on.published, diesel.entity.on.created, diesel.ai.pipeline.on.done, a member joining, a quota reached…). Full list: LifecycleMessages; inventory: Design › message-inventory.

event_handle

  • Summary: a $when on the event, usually in Settings:Init.
  • When: the project must react to something d2 does.
  • Needs: the event name and what it carries.
  • Call: $when diesel.topic.on.published (topic, category) if (category is "Recipe") { dom.upsert(cls = "Published", entity = {id: topic}) }.
  • Rules: R-eng-3. Each runs as a flow after what caused it, only when the project has a rule for it; a rule sees only its own project's events.
  • Errors: E_NATIVE → a rule or story sent an event.
  • Gotchas: —

request

A message a rule sends to ask d2 to act: diesel.user.notify (to, text, kind, code, link), diesel.ai.pipeline.create / assign / setStatus, diesel.ai.board.send (forName, to, text).

request_send

  • Summary: a rule acts as its project: members only, its quotas.
  • When: a rule must notify, file or message.
  • Needs: the request's params.
  • Call: a send statement in a rule, e.g. diesel.user.notify (to = …, text = …).
  • Rules: Source role is rule; a story run doesn't send them.
  • Errors: E_SCOPE, E_IN_PROGRESS, E_QUOTA, E_RATE → the project may not, or is over a limit: the flow fails; read the code.
  • Gotchas: —

fetch

Reading from the web inside a rule. Fields: https, public hosts; 10 s and 2 MB each.

fetch_get

  • Summary: http.json / http.text GET a URL; parse with csv.parse / json.parse.
  • When: a rule needs outside data.
  • Needs: a public https URL, no secret.
  • Call: http.json(url = …), http.text(url = …); csv.parse(text = …), json.parse(text = …).
  • Rules: R-eng-4, R-eng-6. Waiting doesn't count against the flow's time, up to 60 s in all; the server keeps serving meanwhile.
  • Errors: E_WAIT → a fetch outside a rule.
  • Gotchas: —

fetch_par

  • Summary: many at once with map par / flatMap par.
  • When: fetching a list of URLs.
  • Needs: the list.
  • Call: ids flatMap par (i => http.json(url = …)); flatMap par 8 (…).
  • Rules: 4 at a time by default, up to 32; results keep their order; a failure is raised after all branches end.
  • Errors: —
  • Gotchas: —

expression

The value language in rules, stories and fields; reads like English, symbols as aliases.

expression_write

  • Summary: English operators; / gives a Float; Int wraps.
  • When: any value in a rule, story or field.
  • Needs: —
  • Call: and, or, not, is, is not, in, is a Number, is defined, is empty, ??, matches /regex/, if … then … else; map, filter, fold (acc = 0) (x => …), indexBy, mkString. Every core function with examples: Expressions; try them in /fiddle.
  • Rules: Int is 64-bit and wraps like Java's long; / always gives a Float.
  • Errors: E_TIMEOUT inside a long expression.
  • Gotchas: —

Errors

  • E_PARSE (line, position) — a bad rule or story line → fix it; check with /diesel/parse. see #rule_parse
  • failed $expect — the rule's behaviour differs from the story → read trace and flow. see #story_run
  • E_TIMEOUT — the flow ran past its time → split it, or move work to a cron. see #flow_view
  • E_NATIVE — a rule or story sent an event → only d2 raises them. see #event_handle
  • E_WAIT — a web fetch outside a rule. see #fetch_get
  • E_SCOPE / E_IN_PROGRESS / E_QUOTA / E_RATE — a request the project may not make, or over a limit → the flow fails; read the code. see #request_send