Events
A calculation names what its answer sets off, so what happens next is decided by rules you can test, and done by whoever runs it.
After reading this guide, you will know:
- How to declare the events a calculation sets off.
- What an event carries.
- How a case says which events it expects.
- Where events appear, and what a host does with them.
Why Events
An answer often means something should happen: a letter goes out, a review starts, another calculation runs. The condition belongs with the rules, where it is checked and tested like any step. The action does not: a blueprint only works out values, so it names the event and leaves the doing to whoever ran it.
Declaring Events
events: sits beside outputs: and lists conditions on the calculation’s values:
# sanity.yml
calculations:
sanity_check:
inputs:
sanity: {type: number}
loss: {type: number}
steps:
- name: sanity_after
formula: MAX(0, sanity - loss)
outputs: [sanity_after]
events:
- name: temporary_insanity_risk
when: loss >= 5
data: [loss, sanity_after]
- name: permanently_insane
when: sanity_after = 0
| Key | Holds | Required |
|---|---|---|
name |
a snake_case name, unique in the calculation | yes |
when |
a condition, written as a formula, on the inputs and steps | yes |
data |
the inputs and steps the event carries | no; the outputs |
when reads every input and step, not only the outputs, and an event is set off only when it is true.
Each event is checked on its own, so one answer can set off several, in the order they are listed.
What Comes Back
explain lists the events with the outputs and steps:
{
"outputs": {"sanity_after": "51"},
"steps": [...],
"events": [
{"name": "temporary_insanity_risk", "data": {"loss": "9", "sanity_after": "51"}}
]
}
call gives the outputs alone, as before, so an output that happens to be called events never clashes.
A calculation run as a step does not pass its events up; only the calculation you run sets them off.
Cases
A case lists the events it expects by name, in any order. events: [] expects none, and a case without
events does not check them:
- name: a shoggoth in the tunnel
facts: {sanity: 60, loss: 9}
expect: {sanity_after: 51}
events: [temporary_insanity_risk]
A case that sets off different events fails with a difference on events:
✗ 1 of 3 cases failed
✗ a shoggoth in the tunnel
events: expected ["temporary_insanity_risk"], got []
Problems
check reports an event that is not a list entry with a name and a when, a name that is not snake_case or
is used twice, an unknown key, and a when or data that names something the calculation does not have:
sanity_check: event temporary_insanity_risk uses lose, which is not an input or an earlier step
sanity_check: event temporary_insanity_risk carries sanity_aftr, which is not an input or a step
What a Host Does
A host decides what an event means. In Ruby, read explain(...)[:events] and act on each.
On the hosted service, a traced run returns them, and subscriptions act on them for every run of a
published version: posting each to a webhook, or running another blueprint on its data (see
The Hosted Service). The Rails client runs an on
handler for each one after its saves are committed (see Reason Me This in a Rails App).
Related
- Worked Examples - Pin a blueprint to figures worked out by hand.
- Chaining with Imports and Runs - Join calculations in one run.