class Raft::Log::File

Overview

On-disk log storage backend with crash recovery.

Stores log entries in an append-only binary file (log.bin), metadata in metadata.bin, and snapshots in snapshot.bin. All multi-byte integers use big-endian encoding. Metadata and snapshot files are written atomically via tmp+rename.

Entry record format: [Index:8B][Term:8B][Type:1B][DataLen:4B][Data:NB]

By default every write is followed by an fsync(2) syscall so that entries are durable against power loss or kernel panics. Pass fsync: false to skip the syscall and rely on OS page-cache writeback instead — acceptable when an external restore path exists (replicated block storage, periodic backups, or a peer that always holds the full log).

log = Raft::Log::File.new("/var/lib/raft/node-1")               # fsync on (default)
log = Raft::Log::File.new("/var/lib/raft/node-1", fsync: false) # page-cache only

Defined in:

raft/log/file.cr

Constructors

Instance Method Summary

Instance methods inherited from class Raft::Log

append(entries : Array(Entry)) : Nil append, close : Nil close, get(index : UInt64) : Entry | Nil get, last_index : UInt64 last_index, last_term : UInt64 last_term, load_metadata : Metadata load_metadata, load_snapshot : Tuple(UInt64, UInt64, Bytes) | Nil load_snapshot, save_metadata(meta : Metadata) : Nil save_metadata, save_snapshot(last_index : UInt64, last_term : UInt64, data : Bytes) : Nil save_snapshot, slice(from : UInt64, to : UInt64) : Array(Entry) slice, term_at(index : UInt64) : UInt64 | Nil term_at, truncate_from(index : UInt64) : Nil truncate_from

Constructor Detail

def self.new(data_dir : String, fsync : Bool = true) #

Creates a new file-backed log in the given data_dir.

The directory is created if it doesn't exist. On startup, the log file is scanned to rebuild the in-memory offset index.


[View source]

Instance Method Detail

def append(entries : Array(Entry)) : Nil #
Description copied from class Raft::Log

Appends entries to the log with conflict detection.

If an existing entry at the same index has a different term, all entries from that index onward are truncated before appending. Entries with matching index and term are skipped (idempotent).


[View source]
def close : Nil #
Description copied from class Raft::Log

Releases any resources held by the log (e.g., file handles).


[View source]
def get(index : UInt64) : Entry | Nil #
Description copied from class Raft::Log

Returns the entry at the given 1-based index, or nil if not present.


[View source]
def last_index : UInt64 #
Description copied from class Raft::Log

Returns the index of the last entry, or 0 if the log is empty.


[View source]
def last_term : UInt64 #
Description copied from class Raft::Log

Returns the term of the last entry, or 0 if the log is empty.


[View source]
def load_metadata : Metadata #
Description copied from class Raft::Log

Loads the persisted metadata, or returns defaults (term 0, no vote).


[View source]
def load_snapshot : Tuple(UInt64, UInt64, Bytes) | Nil #
Description copied from class Raft::Log

Loads the most recent snapshot, or returns nil if none exists.

Returns a tuple of {last_included_index, last_included_term, snapshot_data}.


[View source]
def save_metadata(meta : Metadata) : Nil #
Description copied from class Raft::Log

Persists the node's current term and voted-for state.


[View source]
def save_snapshot(last_index : UInt64, last_term : UInt64, data : Bytes) : Nil #
Description copied from class Raft::Log

Saves a snapshot and compacts the log up to last_index.

All entries with index <= last_index are removed from the log.


[View source]
def slice(from : UInt64, to : UInt64) : Array(Entry) #
Description copied from class Raft::Log

Returns entries in the inclusive range [from, to].


[View source]
def term_at(index : UInt64) : UInt64 | Nil #
Description copied from class Raft::Log

Returns the term of the entry at index, or nil if not present.


[View source]
def truncate_from(index : UInt64) : Nil #
Description copied from class Raft::Log

Removes all entries at index and beyond (inclusive).


[View source]