docs
This commit is contained in:
+82
-119
@@ -1,207 +1,170 @@
|
||||
# Payload types
|
||||
|
||||
Every port declares a `dtype`, and every value that passes through it is
|
||||
checked against that declaration.
|
||||
Every port declares a `dtype`. Fluksio checks values against it and offers
|
||||
compatible messages when you bind dashboard widgets.
|
||||
|
||||
This is not decoration. It is what lets the dashboard editor offer you only the
|
||||
messages a gauge can actually draw, what lets the canvas refuse a binding before
|
||||
anything runs, and what lets a downstream node know the shape of what it is
|
||||
getting before the flow starts.
|
||||
Messages carry JSON. Binary data lives in the artifact store; messages carry
|
||||
references to it.
|
||||
|
||||
Everything on the wire is JSON. That is what lets the same value pass through
|
||||
the state backend, the work queue and the worker protocol unchanged.
|
||||
|
||||
## The scalars
|
||||
## Scalars
|
||||
|
||||
| `dtype` | Accepts |
|
||||
|---|---|
|
||||
| `float` | any number — `int` or `float`, but not `bool` |
|
||||
| `int` | a whole number, not `bool` |
|
||||
| `str` | a string |
|
||||
| `bool` | exactly `true` or `false` |
|
||||
| `float` | integer or floating-point number, excluding booleans |
|
||||
| `int` | integer, excluding booleans |
|
||||
| `str` | string |
|
||||
| `bool` | `true` or `false` |
|
||||
|
||||
`bool` is an `int` subclass in Python but is not a number here, so a switch
|
||||
cannot bind to a temperature.
|
||||
`NaN` and infinity are rejected, including in structured payloads. For an
|
||||
unavailable numeric result, omit that output or return `None` to publish
|
||||
nothing. A numeric port does not accept `None` as its value.
|
||||
|
||||
`NaN` and infinity are refused, wherever they sit, including inside a `json`,
|
||||
`record`, `series` or `list`. JSON cannot spell either, so one that travelled
|
||||
would come back as a response nobody can parse and a row the database rejects,
|
||||
a long way from the node that made it. An empty subset or a division with no
|
||||
denominator is what usually produces one; publish `None` instead.
|
||||
|
||||
## The structured ones
|
||||
|
||||
These are *declared shapes* rather than "some JSON", which is what makes a
|
||||
widget binding checkable.
|
||||
## Structured payloads
|
||||
|
||||
### `record`
|
||||
|
||||
Flat named scalars.
|
||||
An object with string keys and scalar or null values. Nested objects and
|
||||
lists are not allowed.
|
||||
|
||||
```json
|
||||
{"title": "Boiler", "body": "Pressure low", "severity": "warning"}
|
||||
```
|
||||
|
||||
A record cannot contain a record, so its shape is readable from the declaration
|
||||
alone.
|
||||
|
||||
Read by the **Notification** widget. It is also what an alert channel of kind
|
||||
*dashboard* writes.
|
||||
Notification and Player widgets read records. Dashboard alert channels also
|
||||
publish them.
|
||||
|
||||
### `list`
|
||||
|
||||
Ordered items of one declared shape. The port also declares `item`:
|
||||
An array with a declared item type:
|
||||
|
||||
| `item` | Meaning |
|
||||
| `item` | Accepts |
|
||||
|---|---|
|
||||
| unset | `record` — what the agenda and forecast widgets read |
|
||||
| `float`, `int`, `str`, `bool` | a list of scalars |
|
||||
| `json` | anything |
|
||||
| unset or `record` | flat records; used by Agenda and Forecast |
|
||||
| `float`, `int`, `str`, `bool` | scalars of that type |
|
||||
| `json` | arbitrary JSON values |
|
||||
|
||||
A list of lists, or a list of series, is refused. One declared level is the
|
||||
point.
|
||||
`list` and `series` cannot be declared as item types. Use `item: "json"` if
|
||||
items need arbitrary nested structures.
|
||||
|
||||
### `series`
|
||||
|
||||
Labelled lines of `(timestamp, value)` pairs, which is what a chart draws.
|
||||
Labelled lines of numeric `[timestamp, value]` pairs:
|
||||
|
||||
```json
|
||||
{
|
||||
"lines": [
|
||||
{"label": "living", "points": [[1717000000, 21.4], [1717000060, 21.5]]}
|
||||
],
|
||||
"range": "-24h"
|
||||
"range_s": 86400,
|
||||
"interval_s": 60
|
||||
}
|
||||
```
|
||||
|
||||
Keys beside `lines` are carried through untouched, which is how a querying
|
||||
chart puts the window and resolution it asked for on the request and reads them
|
||||
back off the answer. That is what stops an answer to a *different* question
|
||||
from overwriting the picture.
|
||||
Additional top-level keys are preserved. A Query chart expects the
|
||||
`range_s` and `interval_s` from its request in the response; this prevents
|
||||
an answer for another window from replacing its chart.
|
||||
|
||||
`GET /runs/series/compare` answers in this shape, which is why comparing three
|
||||
training curves is a widget binding rather than a screen of its own.
|
||||
The run-series comparison endpoint also returns this shape.
|
||||
|
||||
### `artifact`
|
||||
|
||||
A reference to stored bytes.
|
||||
A reference to bytes in the content-addressed artifact store:
|
||||
|
||||
```json
|
||||
{"digest": "sha256:…", "size": 4194304, "media_type": "application/octet-stream", "name": "weights.pt"}
|
||||
```
|
||||
|
||||
Binary payloads (tensors, checkpoints, images) never travel as a message. The
|
||||
bytes go to a content-addressed store and the message carries this. A
|
||||
thirty-megabyte checkpoint never sits in the state backend, and the reference
|
||||
stays valid wherever the store is reachable from, including on another machine.
|
||||
`digest` and `size` identify the content. `media_type` and `name` describe it.
|
||||
The reference works wherever the store is reachable.
|
||||
|
||||
Node code produces one with `fluksio.save_artifact` and opens one with
|
||||
`fluksio.load_artifact`. See [Writing node code](../code/nodes.md#bytes-artifacts).
|
||||
Create one with `fluksio.save_artifact` and read its bytes with
|
||||
`fluksio.load_artifact`. See [Artifacts](../code/nodes.md#bytes-artifacts).
|
||||
|
||||
### `image`, `audio`, `video`
|
||||
|
||||
The same reference, narrowed to a kind of media by its `media_type`.
|
||||
Artifact references restricted to the matching `media_type` family:
|
||||
|
||||
```json
|
||||
{"digest": "sha256:…", "size": 61344, "media_type": "image/jpeg", "name": "frame.jpg",
|
||||
"meta": {"width": 1280, "height": 720, "seq": 41}}
|
||||
{
|
||||
"digest": "sha256:…",
|
||||
"size": 61344,
|
||||
"media_type": "image/jpeg",
|
||||
"name": "frame.jpg",
|
||||
"meta": {"width": 1280, "height": 720, "seq": 41}
|
||||
}
|
||||
```
|
||||
|
||||
An `audio` port takes `audio/*` and refuses anything else, so a speech
|
||||
recogniser declares what it eats rather than taking any bytes at all and
|
||||
finding out. An `artifact` port still accepts all three: media narrows
|
||||
artifact, not the other way round.
|
||||
An `audio` port accepts `audio/*`; `image` and `video` work the same way.
|
||||
An `artifact` port accepts all three. Optional `meta` fields are for the
|
||||
consumer; Fluksio does not interpret them.
|
||||
|
||||
`meta` is optional and nothing here reads it: sample rates, dimensions and
|
||||
sequence numbers are for whoever consumes the media.
|
||||
A media stream is a [streaming port](../concepts/flows.md#streaming-ports)
|
||||
publishing one reference per frame or chunk. Saving with
|
||||
[`volatile=True`](../code/nodes.md#media) keeps bytes in memory and lets local
|
||||
websocket clients receive them with the value. Stored media and portal views
|
||||
fetch the bytes separately.
|
||||
|
||||
Bytes still never travel as a message. A camera publishes one reference per
|
||||
frame and a microphone one per chunk, which makes a media stream an ordinary
|
||||
[streaming port](../concepts/flows.md#streaming-ports). What that costs
|
||||
depends on how the bytes reach the screen:
|
||||
|
||||
| Rate | Where it works |
|
||||
|---|---|
|
||||
| A clip a second (speech) | anywhere, including through the portal |
|
||||
| Ten frames a second (a camera worth watching) | on the local network, with `volatile=True` |
|
||||
| A frame every second or two (a glance at a door) | anywhere, including through the portal |
|
||||
| Full-rate video, 30 fps and up | not here — see below |
|
||||
|
||||
The difference is one flag. A frame saved with
|
||||
[`volatile=True`](../code/nodes.md#media) is held in memory and pushed down the
|
||||
websocket in front of the value naming it, so a screen draws it without asking
|
||||
for anything. A stored one is fetched instead: a round trip per frame, which is
|
||||
a glance rather than a view. Through a portal every frame is fetched, so a
|
||||
remote panel is in the second row whatever the flag says.
|
||||
|
||||
Above that, video is not a message-plane problem — every frame would still be
|
||||
an event. Point a media widget's **stream URL** at whatever the camera already
|
||||
serves and the browser plays it from source; the messages then carry the
|
||||
occasional still, and the flow reacts to those.
|
||||
Use occasional snapshots through a portal. For continuous video, point a
|
||||
Media widget's **Live stream** at a browser-compatible source URL reachable
|
||||
by the screen.
|
||||
|
||||
### `json`
|
||||
|
||||
Anything JSON-serializable. The escape hatch, and the right answer when a
|
||||
payload genuinely has no fixed shape.
|
||||
Any JSON-serializable value. Use it for payloads without a fixed shape.
|
||||
Prefer a specific type when one fits; it gives widgets and other authors a
|
||||
clearer contract.
|
||||
|
||||
Reach for it last. A `json` port tells the canvas, the widget picker and the
|
||||
next author nothing.
|
||||
## Referencing a run's output
|
||||
|
||||
## Naming a run's output
|
||||
A run parameter can name an existing value instead of repeating it:
|
||||
|
||||
Any *run parameter* is also accepted as text, since nobody wants to paste an
|
||||
object into a shell. `@run:<id>.<output>` names what an earlier run produced,
|
||||
whatever its type, an `artifact` reference or a `json` config alike. A bare
|
||||
`sha256:…` digest names content in the artifact store. Both resolve before the
|
||||
run starts, so the CLI, the run dialog and a python caller all mean the same
|
||||
thing by the same string.
|
||||
- `@run:<id>.<output>` resolves an earlier run's output.
|
||||
- `sha256:…` resolves an artifact digest.
|
||||
|
||||
Both spellings are reserved on every input, `str` included: an input that has to
|
||||
carry one of them literally is asking for a value this engine reads as a name.
|
||||
These strings resolve before the run starts, regardless of the input's type.
|
||||
Both prefixes are reserved even for `str` inputs; they cannot be passed as
|
||||
literal text in run parameters.
|
||||
|
||||
## What a widget will bind to
|
||||
## Widget bindings
|
||||
|
||||
| Widget | Accepts |
|
||||
|---|---|
|
||||
| Gauge, Chart, Slider, Bar | `float`, `int` |
|
||||
| Gauge, live Chart, Slider, Bar | `float`, `int` |
|
||||
| Query Chart | `series` response, `record` request |
|
||||
| Switch | `bool` |
|
||||
| Agenda, Forecast | `list` |
|
||||
| Notification | `record` |
|
||||
| Value | anything |
|
||||
| Icon | weather strings, booleans and numbers alike |
|
||||
| Notification, Player | `record` |
|
||||
| Colour | `list` for HSV/RGB, `str` for hex |
|
||||
| Media | `image`, `audio`, `video`, `artifact` |
|
||||
| Clock, Text | nothing — they bind to no message |
|
||||
| Value, Icon, Button, Buttons, Input, Selector | no fixed type restriction |
|
||||
| Clock, Text, Website | no message binding |
|
||||
|
||||
Enforced on the server as well as in the editor.
|
||||
Player transport commands publish to a separate `str` message.
|
||||
Binding checks apply in the editor and on the server.
|
||||
|
||||
## Icon and colour names
|
||||
|
||||
A forecast is a `list` of records, one per column, each shaped
|
||||
`{label, icon, value}` with an optional `color`. The flow decides what a
|
||||
column is called and which glyph it gets; the widget only draws it.
|
||||
Forecast reads a list of records with `label`, `icon` and `value`, plus
|
||||
optional `color`:
|
||||
|
||||
```json
|
||||
[{"label": "Today", "icon": "cloud-rain", "color": "primary", "value": "14°"}]
|
||||
```
|
||||
|
||||
`icon` and `color` are names from a fixed vocabulary, the same one the icon
|
||||
widget's picker offers:
|
||||
The Icon widget uses the same vocabulary:
|
||||
|
||||
| | Names |
|
||||
|---|---|
|
||||
| Icons | `sun`, `moon`, `cloudy`, `cloud-rain`, `cloud-drizzle`, `cloud-snow`, `cloud-lightning`, `cloud-fog`, `wind`, `umbrella`, `snowflake`, `droplets`, `thermometer`, `thermometer-sun`, `flame`, `fan`, `sun-snow`, `door-open`, `house`, `bed`, `lightbulb`, `plug`, `music`, `volume-2`, `volume-x`, `zap`, `battery-charging`, `arrow-up`, `arrow-down`, `triangle-alert`, `check`, `circle-check` |
|
||||
| Icons | `sun`, `moon`, `cloudy`, `cloud-rain`, `cloud-drizzle`, `cloud-snow`, `cloud-lightning`, `cloud-fog`, `wind`, `umbrella`, `snowflake`, `droplets`, `thermometer`, `thermometer-sun`, `flame`, `fan`, `sun-snow`, `door-open`, `house`, `bed`, `lightbulb`, `plug`, `cctv`, `music`, `volume-2`, `volume-x`, `zap`, `battery-charging`, `arrow-up`, `arrow-down`, `triangle-alert`, `check`, `circle-check` |
|
||||
| Colours | `default`, `muted`, `primary`, `success`, `danger` |
|
||||
|
||||
An empty icon draws nothing. An unknown one draws a placeholder glyph and an
|
||||
unknown colour draws as `default`; either warns once in the browser console,
|
||||
listing the names it expected.
|
||||
An empty icon draws nothing. Unknown icons use a placeholder; unknown colours
|
||||
use `default`. Each warns once in the browser console.
|
||||
|
||||
## Type failures
|
||||
|
||||
A value that does not match its port's declaration raises on the node that
|
||||
published it, naming the port and what arrived. It does not get published, and
|
||||
it does not reach anything downstream. A wrong value stopping at its source is
|
||||
easier to diagnose than one propagating.
|
||||
A mismatched value raises an error on the node that produced it, naming the
|
||||
port and received value. It is not published downstream.
|
||||
|
||||
## See also
|
||||
|
||||
|
||||
Reference in New Issue
Block a user