Conversation
By default nothing changes: a write is durable at assignment, sync() is a no-op, and an unconfigured disk draws no randomness and records no trace events, so existing runs decide everything exactly as they did. net.set_disk(name, buffered=True) queues writes and deletes until a sync() while the host reads them back immediately; a crash drops the queue, and torn=True keeps a seeded prefix of it instead - the state a machine that lost power mid-batch actually reboots into. The prefix is drawn from a seed-derived stream of its own so a torn run makes exactly the network draws it would have made untorn.
Storage grows a sync() and a DiskStorage that puts the whole record - term, vote and log - under one key on the host's disk, so a torn crash can rewind a node to an earlier record but never pair this term with the previous vote. Two Safeguards flags name the syncs the node owes before it answers: sync_before_vote and sync_before_ack. The unsynced ack is ablation row six - seed 0 elects a term that never heard of a committed entry, minimized to FIFO except one step of 1,273 - while the synced version holds the same scenario across 150 seeds and a 5,000-seed torn disk chaos campaign. The vote's window is one heartbeat wide and 4,000 seeds never hit it, so that flag is covered by deterministic units and the README says exactly that.
The supported-API table gets the set_disk row and the reworked host.disk row, the design doc records why the crash model is a prefix and nothing more - reordering and sector corruption would need a layer nothing else uses, while a prefix is the failure an application can defend against - and the README and changelog carry the short form.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SimDisk stays durable-at-assignment by default — an unconfigured disk draws no randomness, records no trace events, and leaves every existing hash where it was; the replay guards check exactly that. net.set_disk(name, buffered=True) makes it lie the way real storage does: writes and deletes queue in order until sync() while the host reads them back immediately, a crash drops the queue, and torn=True keeps a seeded prefix of it instead — the state a machine that lost power mid-batch actually reboots into. A prefix is the whole model, deliberately: no reordering, no half-written values, and the design doc says why it stops there. The torn draw comes from its own seed-derived stream, so a torn run makes exactly the network draws it would have made untorn.
The Raft demo is the consumer. Its record — term, vote and log — goes under one key of the host's disk, and two Safeguards flags name the syncs the node owes before answering an RPC. Dropping the one before an append is acknowledged is ablation row six: seed 0 elects a term that never heard of a committed entry, and the schedule minimizes to FIFO except one step of 1,273. With the sync restored the same scenario holds across 150 seeds, and a 5,000-seed chaos campaign on buffered, torn disks with hard power cuts runs green in under a minute at jobs=8. The vote-side sync has a one-heartbeat window that 4,000 searched seeds never hit, so it is covered by deterministic unit tests and the README says exactly that rather than claiming a detection.