class

LavinMQ::Clustering::Server

Inherits LavinMQ::Clustering::Replicator < LavinMQ::Clustering::FileIndex < Reference < Object

When a follower connects: It sends a static header (wrong header disconnects the client) It sends its password (servers closes the connection if the password is wrong) Server sends a list of files in its data directory and the sha1 hash of those files Client requests files that is missing or has mismatching checksums of In the meantime the server queues up changes (all publishes/consumes are paused) When client doesn't request more files starts to stream changes Server sends "appends", which include the file path and the bytes to be appended It also sends which files should be deleted or has been rewritten (such as json files) The follower sends back/acknowledges how many bytes it has received

Constants

Log = LavinMQ::Log.for("clustering.server")

Constructors

new(config : Config, coordinator : Coordinator, id : Int32)
Source

Instance methods

all_followers
Source
append(path : String, pos : Int, length : Int)

Replicate length bytes from path starting at pos. The bytes are read from the registered MFile's mmap — zero syscalls. Callers must have registered the path as an MFile first; for regular Files use the append(path, bytes) overload instead.

Source
append_bytes(path : String, bytes : Bytes, offset : Int64)

Replicate an in-memory byte buffer. Caller owns the buffer. See append_value for offset.

Source
append_value(path : String, value : UInt32 | Int32, offset : Int64)

Replicate a small in-memory integer (e.g. Schema::VERSION, ack position). The follower writes it directly to its LZ4 stream — no heap allocation. offset is where the value is written on the leader, used to skip bytes a just-joined follower already got via full_sync.

Source
clear
Source
close
Source
delete_dir(path : String)
Source
delete_file(path : String)
Source
files_with_hash(caps : Hash(String, Int64) | Nil = nil, & : Tuple(String, Bytes) -> Nil)

When caps is given (the last full_sync of a joining follower), each file's hash is computed over only the first caps[path] bytes — the cut the follower will be marked synced at. This excludes writes whose replication dispatch hasn't happened yet (local write at message_store.cr:339 races full_sync because it doesn't hold @lock), so they are delivered incrementally instead of duplicated. Files absent from caps are capped at 0 (delivered entirely via the stream).

Source
flush_isr

Commit the current ISR to the coordinator, retrying until it succeeds. Called before any durable operation is acknowledged when a synced follower has disconnected — by each_follower after dispatching a replicated change, and by the Persister before sending publish confirms: the acknowledgment may only go out once the follower's removal from the ISR is durable, otherwise a leader crash right after the acknowledgment could elect that follower even though it lacks the acknowledged data. Operations must stall rather than be acknowledged against a stale ISR — if the coordinator stays unreachable the leader's lease eventually expires and the process exits.

Source
followers
Source
isr_dirty?

True when the ISR last written to the coordinator may be stale (a follower connected or disconnected since). Checked by the Persister before sending publish confirms.

Source
listen(server : TCPServer)
Source
nr_of_files
Source
password
Source
register_file(path : String)
Source
register_file(file : File)
Source
register_file(mfile : MFile)
Source
replace_file(path : String)
Source
replace_file(mfile : MFile)

Replace an mmap-backed file's entire content on all followers — used after an in-place compaction (e.g. a stream's consumer_offsets file). Unlike replace_file(path) the MFile stays registered, so the zero-syscall append(path, pos, length) overload keeps working for later writes, and the bytes are read from the mmap capped at mfile.size (File.size would be the sparse ftruncate capacity, not the data length).

Source
request_fsync(paths : Enumerable(String)) : Nil

Block until every in-sync follower has acked everything replicated so far, so a durable operation may be acknowledged to a client: once this returns, every node etcd lists as a failover candidate has the operation durably on disk. Wait for all followers (no short-circuit) — wait_for_confirm blocks until the follower acks or disconnects. A follower that disconnected (wait_for_confirm == false, or it dropped earlier and left the ISR dirty) may lack data that's about to be acknowledged, so its removal must be committed to the coordinator before this returns (see flush_isr).

Source
request_syncfs
Source
syncing_followers
Source
wait_for_followers

Block until every in-sync follower has acked everything replicated so far, then commit any pending ISR change. Called after a durable operation has been dispatched and locally fsynced, before it is acknowledged to a client (publish confirms via the Persister, definition changes via the DefinitionsStore).

Source
with_file(filename, cap : Int64 | Nil = nil, & : File | Nil, Int64 -> _)

Yields the file (or nil if missing) along with its real data size in bytes. For MFile-backed sparse files the size comes from mfile.size, not from File.size which would be the capacity. cap (see files_with_hash) limits the yielded size for a capped full_sync.

Source