Examples
Worked cases you can run against examples/basic_counter/. Each assumes a build
with the management API:
cmake -S . -B build -DSIG_NET=ON -DSIG_HTTP_SERVER=ON -DSIG_MGMT=ONcmake --build buildThe example project has these capsule configurations and services:
| Configuration | Capsule | Properties |
|---|---|---|
Sim |
simulator |
0..9 step 1 every 250 ms |
SimToo |
simulator |
0..9 step 1 every 550 ms |
Count |
counter |
reports every 1000 ms |
Logger |
logger |
level warn |
| Service | Shape |
|---|---|
test |
Sim and SimToo both feed Count, which feeds Logger |
Foo, Dave |
small scratch services created from the web UI; they reuse the configurations above |
A second project, examples/weather/, logs the current temperature in London
through the weather capsule. It needs a host built with
-DSIG_HTTP_CLIENT=ON -DSIG_CAPSULES="counter;simulator;logger;weather" (and
libcurl) and network access:
build/host/posix/sighost -p examples/weather1. Run the example and watch it work
Section titled “1. Run the example and watch it work”build/host/posix/sighost -p examples/basic_counter -m 8080test has "auto_start": true, so it is already running; Foo and Dave have no
auto_start and stay stopped until you POST /services/{name}/start.
The service looks like this (arrows are receivers; every link uses the
default terminal __default_terminal_value):
flowchart LR
Sim[Sim<br/>simulator] --> Count
SimToo[SimToo<br/>simulator] --> Count[Count<br/>counter]
Count --> Logger[Logger<br/>logger]
Both simulators emit integers; Count tallies signals from either, and once per
interval logs counter Count: processed N signals in the past 1000ms and emits
N to Logger. Logger is set to warn, so under the default -l trace you
see its lines, and under -l error you do not. Fan-in (two sources to one input)
needs nothing special: both routes enqueue onto the same destination.
Stop and restart it, or read what it is made of:
curl -s localhost:8080/services/test # instances, terminals, linkscurl -s localhost:8080/services/test/instances/Sim # configured propertiescurl -s -X POST localhost:8080/services/test/restart2. Fan-out: one source, many destinations
Section titled “2. Fan-out: one source, many destinations”A receiver list may name several destinations. Signals are delivered to each, and one failing destination does not stop the others.
{ "execution": [ { "name": "Sim", "receivers": { "__default_terminal_value": [ { "name": "Count", "input": "__default_terminal_value" }, { "name": "Logger", "input": "__default_terminal_value" } ] } }, { "name": "Count" }, { "name": "Logger" } ]}Logger here prints every integer Sim emits (raw), while Count summarises them.
Create it without touching the disk by hand:
curl -s -X PUT -H 'Content-Type: application/json' -d @fanout.json localhost:8080/services/fanoutcurl -s -X POST localhost:8080/services/fanout/start3. A configuration shared by two services
Section titled “3. A configuration shared by two services”Sim is in test and could be in fanout as well: a configuration is project-wide
and each service that lists it gets its own instance, with its own storage and
its own position in the simulator’s sequence. Editing Sim’s end marks every
service that uses it as "dirty": true:
curl -s -X PATCH -H 'Content-Type: application/json' \ -d '{"attr_value":{"end":99}}' localhost:8080/configurations/Simcurl -s localhost:8080/services # test (and fanout, if it uses Sim): "dirty": truecurl -s -X POST localhost:8080/services/test/restartA running service is not disturbed by an edit; the change applies on its next
start. DELETE /configurations/Sim is refused (409 configuration_in_use) while
any service still lists it.
4. A validation failure
Section titled “4. A validation failure”Property tables are enforced on write, so a bad configuration never reaches disk:
curl -s -X PUT -H 'Content-Type: application/json' -d '{"type":"simulator"}' \ localhost:8080/configurations/Bad# {"error":"invalid_config","message":"end: required"}curl -s -X PUT -H 'Content-Type: application/json' \ -d '{"type":"simulator","attr_value":{"end":9,"interval_ms":0}}' \ localhost:8080/configurations/Bad# {"error":"invalid_config","message":"interval_ms: must be >= 1"}A hand-edited .cfg that violates its capsule’s table loads fine but the service
refuses to start (422 invalid_config from POST .../start, with the property
named in the host log).
5. Editing in the web UI
Section titled “5. Editing in the web UI”build/host/posix/sighost -p examples/basic_counter -m 8080 -o http://localhost:5173cd ui && pnpm install && pnpm devOpen http://localhost:5173, connect to 127.0.0.1:8080, then:
- Pick
testin the service list; the graph appears. - Click
Countto inspect its properties. - Drag Logger from the palette onto the canvas. That creates a configuration
(named like
Logger2) and an instance of it in this service. - Drag from
Count’s output terminal toLogger2’s input to link them. - Select
Logger2and setleveltoinfoin the form. - Save. The toolbar then shows Needs restart; press Restart and the new link is live.
If another client edited the same service meanwhile, Save asks whether to overwrite or reload instead of silently clobbering it. See ui/README.md for the details of the draft model.
6. A new capsule
Section titled “6. A new capsule”writing-capsules.md walks through declaring terminals and a
property table. Once your capsule is registered, it appears in GET /capsules
and in the UI palette with a form generated from its properties; no UI code is
needed.
7. Embedding without sighost
Section titled “7. Embedding without sighost”See the README for creating a
runtime and registering the management modules in your own main(). A host with
no management modules is just the project runner: services start from
auto_start and run until you request shutdown.