Cirrina Runtime
Cirrina is the runtime environment for executing Collaborative State Machines as distributed applications. It provides the infrastructure required to instantiate state machines, exchange events between runtime instances, and maintain persistent application context.
A Cirrina deployment consists of one or more runtime instances. Each instance executes state machine instances defined by a CSML application and communicates with other instances through Zenoh. Persistent context is managed through a context provider, with etcd currently supported as the default provider.
The runtime separates the application model from the execution infrastructure. Developers describe the behavior and coordination of distributed applications using Collaborative State Machines, while Cirrina manages execution, communication, persistence, and observability.
flowchart LR
A["CSML Application"]
R["Cirrina Runtime"]
Z["Zenoh"]
C["Persistent Context"]
E["etcd"]
A --> R
R <--> Z
R <--> C
C --> E
Quickstart
Pull the latest Cirrina image:
For local development, you can also use Docker Compose to start Cirrina together with its dependencies. This is convenient when repeatedly starting and stopping the complete development environment. Alternatively, Cirrina and its dependencies can be started individually.Create the network
Create a Docker network shared by the runtime, etcd, and Zenoh:
Start etcd
Start an etcd instance:
docker run -d \
--network cirrina \
--name etcd-local \
gcr.io/etcd-development/etcd:v3.5.0 \
/usr/local/bin/etcd \
--name s1 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://etcd-local:2379 \
--listen-peer-urls http://0.0.0.0:2380 \
--initial-advertise-peer-urls http://etcd-local:2380 \
--initial-cluster s1=http://etcd-local:2380
Run Cirrina
The following example executes the pingPong.pkl application:
docker run \
--network cirrina \
-e RUN=ping,pong \
-e MAIN_URI=https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/examples/concurrency/pingPong.pkl \
-e ETCD_CONTEXT_URL=http://etcd-local:2379 \
collaborativestatemachines/cirrina:latest
The RUN variable specifies the state machine instances to execute, while MAIN_URI identifies the CSML application containing their definitions. We recommend developing and maintaining your CSML application in a GitHub repository, which provides version control and makes it easy to collaborate on and distribute your use case. Once the application is available, MAIN_URI can point directly to the raw GitHub URL of the CSML file, allowing the runtime to retrieve and execute the application without requiring it to be packaged locally.
Configuration
Cirrina is configured through environment variables:
| Variable | Default | Description |
|---|---|---|
ETCD_CONTEXT_URL |
null |
Address of the etcd context provider |
ZENOH_EVENT_HANDLER_CONFIG_URI |
null |
Zenoh endpoint used for distributed communication |
MAIN_URI |
file:///app/main.pkl |
URI of the main CSML application |
CONTEXT_PROVIDER |
ETCD |
Context provider used for persistent state |
METRICS_DIRECTORY |
metrics |
Directory where runtime metrics are stored |
METRICS_PERIOD |
1 |
Metrics collection period |
RUN |
empty | Comma-separated list of state machine instances to execute |
For example:
-e RUN=ping,pong
-e MAIN_URI=https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/examples/concurrency/pingPong.pkl
-e ETCD_CONTEXT_URL=http://etcd-local:2379
Distributed communication with Zenoh
Cirrina uses Zenoh to exchange events between runtime instances. The application does not need to manage connections or transport mechanisms directly; communication is handled by the runtime.
Peer-to-peer deployment
When Cirrina instances are deployed on the same network, they can discover each other automatically through Zenoh's peer-to-peer communication. Each Cirrina instance starts a Zenoh session in peer mode, allowing it to participate directly in the Zenoh network. When peer discovery is enabled, Zenoh uses the available discovery mechanisms to identify other peers on the network and establish communication paths between them. As a result, no central broker or manually configured connection between Cirrina instances is required. Once the peers have discovered each other, Cirrina can exchange events directly between runtime instances through the Zenoh network. This configuration is particularly useful for local deployments and environments where participating nodes share a network.
flowchart LR
C1["Cirrina 1"]
C2["Cirrina 2"]
C3["Cirrina 3"]
C1 <--> |"Zenoh"| C2
C2 <--> |"Zenoh"| C3
C1 <--> |"Zenoh"| C3
Zenoh router deployment
Automatic peer discovery may not be available when nodes are deployed across different networks or infrastructure domains. In these environments, Cirrina instances can connect through a Zenoh router.
The Docker Compose configuration includes a Zenoh router by default.
flowchart LR
C1["Cirrina 1"]
C2["Cirrina 2"]
C3["Cirrina 3"]
Z["Zenoh Router"]
C1 --> |"Zenoh"| Z
C2 --> |"Zenoh"| Z
C3 --> |"Zenoh"| Z
For a manual deployment, start a Zenoh router:
Then configure Cirrina to connect to the router:
docker run \
--network cirrina \
-e RUN=ping,pong \
-e MAIN_URI=https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/examples/concurrency/pingPong.pkl \
-e ETCD_CONTEXT_URL=http://etcd-local:2379 \
-e ZENOH_EVENT_HANDLER_CONFIG_URI=tcp://zenoh:7447 \
collaborativestatemachines/cirrina:latest
For nodes deployed on different networks, replace zenoh with the hostname or IP address through which the Zenoh router is reachable.
Persistent context
Collaborative State Machines distinguish between transient execution data and persistent application context.
Transient data belongs to the execution of a particular state machine instance and is maintained by the runtime. Persistent data is associated with the root collaborative state machine and is intended to remain available independently of an individual state machine instance. Cirrina externalizes persistent context through a context provider. The default provider is etcd.
The context provider is deliberately separated from the execution layer. This allows runtime instances to access persistent application state while communicating independently through Zenoh.
Example application
The pingPong.pkl example demonstrates communication between two state machine instances. One machine emits an event to another machine, which reacts to the event and subsequently emits an event back.
Run the example with:
docker run \
--network cirrina \
-e RUN=ping,pong \
-e MAIN_URI=https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/examples/concurrency/pingPong.pkl \
-e ETCD_CONTEXT_URL=http://etcd-local:2379 \
collaborativestatemachines/cirrina:latest
The example demonstrates the basic execution model of Cirrina: state machine instances execute within the runtime, exchange events through Zenoh, and access persistent application context through the configured context provider.
Development
Cirrina provides the runtime layer for applications expressed using the Collaborative State Machines framework. Development can therefore be performed at two levels:
- Application level — define state machines, states, transitions, events, and persistent data using CSML.
- Runtime level — extend the mechanisms responsible for execution, communication, context management, and observability.
This separation allows the programming framework to remain independent of the infrastructure used to execute it.