Quick start
This is a simple of starting a 2-node Corrosion cluster running on the same host and replicating data.
Node A
1. Create a schema file
-- /etc/corrosion/schema/todo.sql
CREATE TABLE todos (
id BLOB NOT NULL PRIMARY KEY,
title TEXT NOT NULL DEFAULT '',
completed_at INTEGER
);
2. Configure Corrosion
# /etc/corrosion/config.toml
[db]
path = "/var/lib/corrosion/state.db"
schema_paths = ["/etc/corrosion/schema"]
[gossip]
addr = "[::]:8787" # the address we bind to
external_addr = "[::1]:8787" # the address we advertise as
plaintext = true
[api]
addr = "127.0.0.1:8080"
[admin]
path = "/var/run/corrosion/admin.sock"
3. Start a Corrosion agent
$ corrosion agent
2023-09-18T13:13:26.526907Z INFO corrosion::command::agent: Starting Corrosion Agent v0.0.1
2023-09-18T13:13:26.623782Z INFO corro_agent::agent: Actor ID: a3f72d6d38a24d0daee8258e10071f13
2023-09-18T13:13:26.655779Z INFO corro_admin: Starting Corrosion admin socket at /var/run/corrosion/admin.sock
2023-09-18T13:13:26.658476Z INFO corro_agent::agent: Starting peer API on udp/[::]:8787 (QUIC)
2023-09-18T13:13:26.661713Z INFO corro_agent::agent: Starting public API server on tcp/127.0.0.1:8080
2023-09-18T13:13:27.022947Z INFO corro_types::schema: creating table 'todos'
2023-09-18T13:13:27.023884Z INFO corro_agent::api::public: updated 1 rows in __corro_schema for table todos
2023-09-18T13:13:27.025223Z INFO corrosion::command::agent: Applied schema in 0.35491575s
4. Insert some data
$ corrosion exec --param 'some-id' --param 'Write some Corrosion docs!' 'INSERT INTO todos (id, title) VALUES (?, ?)'
INFO corrosion: Rows affected: 1
5. Query some data
Either via SQLite directly if you have access to the database directly:
$ sqlite3 /var/lib/corrosion/state.db 'SELECT * FROM todos;'
some-id|Write some Corrosion docs!|
or via the API if you don't:
$ corrosion query 'SELECT * FROM todos;'
some-id|Write some Corrosion docs!|
Node B
1. Copy the schema file
$ mkdir -p /etc/corrosion-b/schema
$ cp /etc/corrosion/schema/todo.sql /etc/corrosion-b/schema/todo.sql
2. Configure Corrosion
# /etc/corrosion-b/config.toml
[db]
path = "/var/lib/corrosion-b/state.db"
schema_paths = ["/etc/corrosion-b/schema"]
[gossip]
addr = "[::]:8788" # the address we bind to
external_addr = "[::1]:8788" # the address we advertise as
bootstrap = ["[::1]:8787"] # bootstrap the node's cluster discovery w/ node A
plaintext = true
[api]
addr = "127.0.0.1:8081"
[admin]
path = "/var/run/corrosion-b/admin.sock"
3. Start a Corrosion agent
$ corrosion -c /etc/corrosion-b/config.toml agent
2023-09-18T13:37:00.696728Z INFO corrosion::command::agent: Starting Corrosion Agent v0.0.1
2023-09-18T13:37:00.768080Z INFO corro_agent::agent: Actor ID: 4e3e57d1faee47449c1f238559284bc2
2023-09-18T13:37:00.772773Z INFO corro_admin: Starting Corrosion admin socket at /var/run/corrosion-b/admin.sock
2023-09-18T13:37:00.773162Z INFO corro_agent::agent: Starting peer API on udp/[::]:8788 (QUIC)
2023-09-18T13:37:00.773559Z INFO corro_agent::agent: Starting public API server on tcp/127.0.0.1:8081
2023-09-18T13:37:00.775504Z INFO corro_types::schema: creating table 'todos'
2023-09-18T13:37:00.775964Z INFO corro_agent::api::public: updated 1 rows in __corro_schema for table todos
2023-09-18T13:37:00.776398Z INFO corro_agent::agent: Current node is considered ACTIVE
2023-09-18T13:37:00.776731Z INFO corrosion::command::agent: Applied schema in 0.001515042s
2023-09-18T13:37:01.954585Z INFO corro_agent::agent: synced 2 changes w/ b4fcbb65501f44f0802aba631508be9d in 0.012817167s @ 156.04072257153237 changes/s
This last log shows that node B synchronized changes w/ node A.
Why were 2 changes
synchronized? There's only 1 row!
cr-sqlite creates 1 change per column "changed" in a row. It's possible to inspect this directly for troubleshooting:
$ sqlite3 data-b/corrosion.db
sqlite> .mode column
sqlite> select * from todos__crsql_clock;
key col_name col_version db_version site_id seq
--- ------------ ----------- ---------- ------- ---
1 title 1 1 1 0
2 completed_at 1 1 1 1
4. Query for the just-synchronized data
Either via SQLite directly if you have access to the database directly:
$ sqlite3 /var/lib/corrosion-b/state.db 'SELECT * FROM todos;'
some-id|Write some Corrosion docs!|
5. Insert some data of our own
$ corrosion -c /etc/corrosion-b/config.toml exec --param 'some-id-2' --param 'Show how broadcasts work' 'INSERT INTO todos (id, title) VALUES (?, ?)'
INFO corrosion: Rows affected: 1
6. Query data from Node A
The second row has been propagated.
# here we're pointing at node A's config explicitly for clarity, the default is /etc/corrosion/config.toml
$ corrosion -c /etc/corrosion/config.toml query 'SELECT * FROM todos;'
some-id|Write some Corrosion docs!|
some-id-2|Show how broadcasts work|
Appendix: Templates
1. Create a Corrosion template
Corrosion templates are powered by Rhai w/ custom functions. On change, templates are re-rendered.
<% for todo in sql("SELECT title, completed_at FROM todos") { %>
[<% if todo.completed_at.is_null() { %> <% } else { %>X<% } %>] <%= todo.title %>
<% } %>
2. Process the template
$ corrosion template "./todos.rhai:todos.txt"
INFO corrosion::command::tpl: Watching and rendering ./todos.rhai to todos.txt
3. Watch the todos.txt file for change
Uses watch
in a different terminal to see updates when your todos change:
$ watch -n 0.5 cat todos.txt
Every 0.5s: cat todos.txt
[ ] Write some Corrosion docs!
[ ] Show how broadcasts work
Add another todo:
$ corrosion -c /etc/corrosion-b/config.toml exec --param 'some-id-3' --param 'Hello from a template!' 'INSERT INTO todos (id, title) VALUES (?, ?)'
INFO corrosion: Rows affected: 1
Your watch
should have been update and should display:
$ watch -n 0.5 cat todos.txt
Every 0.5s: cat todos.txt
[ ] Write some Corrosion docs!
[ ] Show how broadcasts work
[ ] Hello from a template!
We did all those, so let's tick them off:
$ corrosion -c /etc/corrosion-b/config.toml exec 'UPDATE todos SET completed_at = 1234567890'
INFO corrosion: Rows affected: 3
$ watch -n 0.5 cat todos.txt
Every 0.5s: cat todos.txt
[X] Write some Corrosion docs!
[X] Show how broadcasts work
[X] Hello from a template!