Reuse
Structs
A struct is a single object defined once, for many flows to use: its states, attributes and parts. When several flows exchange the same thing, such as a Ticket with a key, a summary and a priority, a struct keeps that shape in one place.
Why structs
An object's shape is a contract: an agent fills in exactly its attributes, a script prints exactly those keys, a person's form asks for exactly those fields. When two flows hand the same thing to each other, or both work on the same kind of record, the contract should be the same in both. Drawing it twice lets the two drift apart; a struct can't.
Making a struct
Create it
On the flow list, type a name under Structs and press New struct.
Shape the object
A struct's board holds only its one object, unfolded: there is no Start, no End, no processes and no runs. Add attributes, with their definitions, in its settings; add parts on its board as for any unfolded object; add states with right-click, Add state, and their rules under State rules.
Name it
The struct's name is its object's name. Renaming the struct renames the object.
Using a struct
Structs are listed under Structs in the board's sidebar. Drag one onto a board and you get a copy of its object, which you link like any other object. Its subtitle says where it comes from, and its settings link to the struct.
A copy follows its source:
| Set in the struct | The copy's own |
|---|---|
| Name, quantity, states, state rules, attributes, parts, what it specializes | Where it sits on the board, its width, and whether it is stored (Store what runs generate), unless the struct shares its records |
In the copy, Rename and Add state are disabled and the settings fields are locked. Links name its states as the struct names them. On the flow list, a struct's card says how many flows use it, or Not used yet.
Shared records
Normally each flow keeps its own copy's values to itself. Tick Share its records with every flow using it on a struct's object and every copy of it, in whatever flow, reads and writes one store of records, like a table the flows have in common. Use it when one flow adds things and another works on them, such as one fetching Sentry issues and another fixing them. A shared object, and every copy of it, wears a round database badge on its top right corner, as a stored object does; hovering over it says Shared.
- The object needs a Unique attribute first: it is what tells records apart. A record written again with the same value is the same record.
- A process that only generates the object, such as a Sentry step or a fetching script, adds the records that are new, in the state its link names, and refreshes the fields of those it knows, keeping their state. Fetching an issue again doesn't undo how far it got. Name the state new records start in on the link, rather than by a rule that holds of every record.
- A process that also takes it, by any input link or a query, moves the records it generates into the state they come out in: the one named on the link, one a rule gives, or one an agent decides. Fields it leaves out stay as they were.
- A list writes a record per item, all in the state the list comes out in.
- Which records get worked on, or worked on again, is up to queries. A query reads the records in a state, whichever flow wrote them, and a rule on their fields narrows them, such as
attempts < 3.
An example: fetch in one flow, fix in another
A struct Exception is a shared list with a unique id and the states new, completed and failed.
- Fetch exceptions, scheduled every hour, has a Sentry step yielding Exception in
new. Issues it has seen before keep whatever state they reached. - Fix exceptions, scheduled every ten minutes, has an agent Fix that queries the oldest record in
newand yields Exception incompleted. - Fix's failure handler, Report, takes Exception and yields it in
failed. To try failed ones again, queryfailedtoo, narrowed by a rule such asattempts < 3.
structs:
- name: Exception
shared: true
many: true
states: [new, completed, failed]
attributes:
- name: id
unique: true
- name: title
- name: permalink
flows:
- name: Fetch exceptions
start: {next: Fetch}
objects:
- copyOf: {flow: Exception}
processes:
- name: Fetch
kind: sentry
sentry: {organization: acme, project: shop}
yields:
- object: Exception
state: new
- name: Fix exceptions
start: {next: Fix}
objects:
- copyOf: {flow: Exception}
processes:
- name: Fix
prompt: Find the cause of the exception in Exception and fix it.
takes:
- object: Exception
query: {state: new, limit: 1, oldest: true}
yields:
- object: Exception
state: completed
onFailure: [Report]
- name: Report
prompt: Say on the Sentry issue why Exception couldn't be fixed.
takes: [Exception]
yields:
- object: Exception
state: failedA shared object's copy can't also be stored in its own flow's runs (Store what runs generate), and in a setup file shared: true goes on the struct, never together with persistent.
Exception is shared, so every flow using it reads and writes the same records.
Fix looks up the earliest 1 stored records of Exception in new.
Fix yields Exception as completed.
The records table
The struct's board lists its records in the sidebar under Records, and the Records button on its toolbar opens them as a table, at #/flows/<struct>/records.
- One row per record, newest first: its number, its state, a column for each field in the order the board has them, when it was last updated, and a link to the run that wrote it, on that run's own flow.
- The query bar searches every stored record, up to 20 000, such as
state:new title:*timeout*. Facets on the left count each column's values, the State facet included, with no value for records without a state. Click a column's name to sort by it. It all works as on a flow's Data page: see Searching and sorting the data. - Click a cell to see all of its value.
- The table shows the latest 1000 matching records and refreshes every ten seconds.
Struct or procedure?
| Struct | Procedure | |
|---|---|---|
| Shares | The shape of one object | A piece of flow: steps and the objects between them |
| Runs | Never | As a run of its own, whenever a caller reaches it |
| Used through | A copy of its object | A procedure process, plus copies of its outcomes |
| Good for | Records several flows exchange: a Ticket, a Change, a Release | Work several flows repeat: announce, triage, open a PR |
In a setup file
structs:
- name: Ticket
attributes:
- name: key
definition: The Jira key, such as SHOP-123.
- name: summary
- name: priority
states: [bug, feature]
flows:
- name: Triage ticket
objects:
- copyOf: {flow: Ticket}A copy lists none of its source's fields, and its name may be left out. See Setup files.