Beyond one machine / When the home dies
When the home dies
A file's home is the one machine that writes it. While it runs, its copies read and pass their writes to it. This chapter covers what happens when it stops: moving a home on purpose, promoting a copy by hand when the home is gone, and the epochs that keep a file from ever having two writers.
Why nothing happens by itself
No node can tell a dead home from a cut cable: both are silence. A copy that guessed wrong and started writing while the old home lived would make a second home, and the file would split into two histories for good. So in the first version a person decides, once they know the old home is stopped.
Epochs
Every change of a file's home raises the file's epoch. A node refuses pages of an older epoch, and a home refuses writes once a later epoch reaches it (contract REPL-08). An old home that wakes up after its copy was promoted cannot write over the new history: the first link it makes tells it that it is no longer the home.
Move a home that is alive
tinystore::replication::move_home(&store, "sql/app.db")?; // on the node that takes the file overThe old home stops taking writes, ships its last commits, and the new home opens its writer at the next epoch, through the catalog. No commit is lost (contract REPL-10). Until the new home's claim reaches the catalog, the old home can call the move off; after that it never can.
Promote a copy when the home is gone
America's data centre is down and will not come back soon. Europe holds the freshest copy:
# stop Europe's server first
tinystore node promote ./eu --from us.internal:7444
tinystore serve ./eu --node-listen 0.0.0.0:7444 --node-config node.toml # without --from: it is the home nowpromote asks each node named by --from first. If America still answers
and serves the file, promote refuses, because promoting then would make a
second home; --force overrides that, for a person who knows better. The
promoted files continue at the next epoch, and nodes that copied from America
try the next address in their from and find Europe.
await sessions.under(userId).set(digest(token), session)- America commits 499 and 500, and goes down before their pages reach Europe.
- A person checks that America is stopped, and runs node promote on Europe. Europe becomes the home at the next epoch.
- Writes go on in Europe. Commits 499 and 500 were never shipped: they are lost, and the promotion says so.
- America comes back. Its epoch is older, so it takes no writes, and node demote makes its files copies of Europe.
By default a home answers a write after its own commit, so the commits that had not reached a copy when the home died are lost with it. That is the trade-off of asynchronous copies. A synchronous home, from Readers in another region, loses nothing it answered: every success means a copy held the write (contract REPL-09).
Bring the old home back
tinystore node demote ./us
tinystore serve ./us --from eu.internal:7444 --node-listen 0.0.0.0:7444 --node-config node.tomldemote makes the old home's files copies again. The commits it had not
shipped are dropped, counted and logged, and it follows the new home before
it opens any writer.
Why this design?
Why a person and not automatic failover. Automatic failover is only safe with something outside the two nodes that decides, and that keeps the decision durably: a judge. Without one, a network cut that hides the home from its copy looks exactly like a dead home. TinyStore's witness is that judge, and it is a draft. Until it is promised, the safe default is a command that a person runs, and that refuses when the old home still answers.
Why epochs. A promotion is a decision that must win over everything the old home does afterwards, including writes it accepted while it was cut off. A number that only grows, carried by every page and every write, makes the older side lose every time, without asking anyone.
Why the loss is counted and logged, not hidden. A failover that loses commits silently leaves the program believing writes that no longer exist. TinyStore names how many were lost, and offers the synchronous mode for files where none may be.
See also
- Readers in another region: homes, copies and writes passed home.
- What TinyStore promises: every contract, replication's among them.