This demo showcases a TodoMVC app that implements the Command Query Responsibility Segregation (CQRS) architecture with the REST command APIs and an SSE query API created by Zilla.
-
The TodoMVC UI lets you maintain a list of tasks across browsers and sessions.
- Type a new todo task in the provided text box and press
enter
to save it. - Click on the circle next to a task to toggle its completion.
- Filter tasks by status with the controls on the bottom.
- Delete all completed tasks withe the
Clear completed
button.
- Type a new todo task in the provided text box and press
-
The TodoMVC UI sends state changes for tasks to Zilla as Commands to be executed by the Todo Management Service.
-
The Todo Management Service will process each command and persist the new todo state.
-
The TodoMVC UI sends a single Query to Zilla and gets a stream of task data.
-
All changes happen in the Todo Management Service.
-
There are NO state mutations in the browser.
-
Start all of the services using
docker-compose
. Thestartup.sh
script willbuild
andstart
all the services. This command will alsorestart
an existing stack../startup.sh
- You can also run this demo with Redpanda.
KAFKA_BROKER=redpanda ./startup.sh
-
Use the local TodoMVC UI for the demo.
-
Browse the topics in the Kafka UI.
- The Kafka topics are created during
startup
. - Browse the topics in the Kafka UI.
- The task commands are recorded on the
task-commands
topic with acknowledgement of the command recorded on thetask-replies
topic. - All of the task state updates are recorded on the
task-snapshots
topic.
The task commands to Create, Update, and Delete todos are separated into the Command endpoints declared in Zilla. The Query endpoint is an SSE stream proxied from a kafka topic by Zilla.
flowchart LR
style zilla1 stroke:#0d9b76,stroke-width:4px
ui[\TodoMVC/] -.- |HTTP| rest
ui -.- |HTTP| sse
subgraph zilla1 [Zilla]
rest{{REST}} --- pr[produce]
rest{{REST}} --- co[consume]
sse{{SSE}} --- fe[fetch]
end
subgraph kafka [Kafka]
tc[[task-commands]]
tr[[task-replies]]
ts[[task-snapshots]]
end
pr -.- tc -.- tms{{Todo Management Service}}
co -.- tr -.- tms
fe -.- ts -.- tms
The todo Command sequence leverages Zilla to enable the command creation based on simple REST endpoints.
- when:
- method: POST
path: /tasks
...
todo-command:operation: CreateTaskCommand
- when:
- method: PUT
path: /tasks/{id}
...
todo-command:operation: UpdateTaskCommand
- when:
- method: DELETE
path: /tasks/{id}
...
todo-command:operation: DeleteTaskCommand
sequenceDiagram
TodoMVC ->> Zilla: POST /tasks
activate Zilla
Zilla ->> Kafka: CreateTaskCommand [task-commands]
TodoMVC ->> Zilla: PUT /tasks/{id}
Zilla ->> Kafka: UpdateTaskCommand [task-commands]
TodoMVC ->> Zilla: DELETE /tasks/{id}
Zilla ->> Kafka: DeleteTaskCommand [task-commands]
Service -->> Kafka: subscribe [task-commands]
Service ->> Kafka: acknowledge [task-replies]
Zilla -->> Kafka: subscribe [task-replies]
Zilla ->> TodoMVC: HTTP response
deactivate Zilla
Querying for todo updates becomes a simple HTTP GET on an the SSE endpoint which will contain every state change.
sequenceDiagram
TodoMVC ->> Zilla: GET /tasks (SSE)
activate Zilla
Zilla -->> Kafka: subscribe [task-snapshots]
Kafka ->> Zilla: current messages
Zilla ->> TodoMVC: SSE message stream
Service ->> Kafka: publish [task-snapshots]
Kafka ->> Zilla: new messages
Zilla ->> TodoMVC: SSE message stream
deactivate Zilla