pub struct WalWriter { /* private fields */ }Expand description
Write-Ahead Log writer.
Appends records to WAL files, manages rotation, and enforces the configured fsync policy. Thread-safe: internal state is protected by a mutex.
§Group commit
When using FsyncPolicy::PerBatch, the append_durable
method enables group commit: concurrent callers write their records under the
write lock, then coordinate so that a single fsync covers all pending
writes. The first waiter becomes the sync leader and performs the flush;
subsequent waiters piggy-back on the leader’s sync.
Implementations§
Source§impl WalWriter
impl WalWriter
Sourcepub fn is_poisoned(&self) -> bool
pub fn is_poisoned(&self) -> bool
Returns true if the WAL writer has been poisoned due to an
unrecoverable I/O error.
Sourcepub fn clear_poison(&self) -> Result<(), WalError>
pub fn clear_poison(&self) -> Result<(), WalError>
Clear the poison flag after operator-verified recovery.
Re-opens the current WAL file for appending to ensure the underlying file descriptor is in a known-good state. Returns an error if the WAL file cannot be reopened.
§Safety (logical)
Call this only after verifying the WAL directory is intact
(e.g. via WalReader replay). Clearing poison on a
genuinely corrupt WAL risks silent data loss.
Sourcepub fn append_batch(&self, payloads: &[&[u8]]) -> Result<u64, WalError>
pub fn append_batch(&self, payloads: &[&[u8]]) -> Result<u64, WalError>
Append a batch of payloads as a single atomic WAL record, followed by
a single fsync (when using PerBatch policy).
All payloads are serialized into a batch-framed compound record whose CRC covers the entire batch. On crash recovery, either all sub-payloads survive (CRC valid) or none (CRC mismatch / truncation), guaranteeing all-or-nothing batch atomicity.
Uses the same group-commit pattern as append_durable:
the write lock is released before fsync, allowing concurrent writers to
proceed while the sync leader fsyncs for all pending records.
Returns the sequence number of the batch record.
§Errors
Returns WalError on I/O failure or if the internal lock was
poisoned.
Sourcepub fn append_durable(&self, payload: &[u8]) -> Result<u64, WalError>
pub fn append_durable(&self, payload: &[u8]) -> Result<u64, WalError>
Append a single payload and ensure it is durably committed.
With FsyncPolicy::PerBatch this participates in group commit:
the calling thread writes its record and then either becomes the sync
leader (flushing and calling fsync for all pending records) or waits
for an in-progress sync to complete. This amortises the cost of fsync
across concurrent callers.
With FsyncPolicy::PerWrite this behaves identically to
append.
With FsyncPolicy::Periodic the record is written and then
unconditionally flushed + synced, because “durable” means the
caller requires the data to be on stable storage before returning
.
§Errors
Returns WalError on I/O failure, if the WAL is full, or if the
internal lock was poisoned.
Sourcepub fn fsync_count(&self) -> u64
pub fn fsync_count(&self) -> u64
Number of fsync calls issued against the WAL data file.
The observable form of the fsync policy: with
FsyncPolicy::Periodic this grows with elapsed time, not with the
number of appends.
Sourcepub fn start_periodic_sync(self: &Arc<Self>)
pub fn start_periodic_sync(self: &Arc<Self>)
Start the background periodic sync thread.
When the WAL is configured with FsyncPolicy::Periodic(interval),
this spawns a dedicated thread that calls flush + fsync at the
configured interval. The thread runs until shutdown_periodic_sync
is called or the WalWriter is dropped.
No-op if the policy is not Periodic.
Sourcepub fn shutdown_periodic_sync(&self)
pub fn shutdown_periodic_sync(&self)
Stop the periodic sync thread and wait for it to finish.
Sourcepub fn memory_bytes(&self) -> usize
pub fn memory_bytes(&self) -> usize
Approximate heap bytes held by the writer’s own buffers.
The BufWriter’s capacity, which is what stands between an append and
an fsync. It is one of the three terms the memtable budget does not
count, and unlike the other two it is fixed rather than a function of
the workload — so it is worth having as a number precisely because it
is easy to forget.
Sourcepub fn current_sequence(&self) -> u64
pub fn current_sequence(&self) -> u64
Returns the current sequence number (the last assigned).
Sourcepub fn file_count(&self) -> Result<usize, WalError>
pub fn file_count(&self) -> Result<usize, WalError>
Sourcepub fn total_bytes(&self) -> Result<u64, WalError>
pub fn total_bytes(&self) -> Result<u64, WalError>
Sourcepub fn emit_metrics(&self)
pub fn emit_metrics(&self)
Emit WAL gauge metrics for monitoring lag and resource usage.
Emits chronix_wal_file_count, chronix_wal_total_bytes, and
chronix_wal_sequence_number gauges.
Sourcepub fn close(self) -> Result<(), WalError>
pub fn close(self) -> Result<(), WalError>
Explicitly close the WAL writer, flushing all data to stable storage.
Unlike the implicit Drop cleanup, this method returns I/O errors
so close failures are not silently ignored.
The shutdown sequence is:
- Stop the periodic sync thread (if running).
- Flush all buffered data to the operating system.
- Issue
sync_allto commit data and metadata to stable storage.
§Close-path efficiency
This method takes ownership of self (mut self), which guarantees
exclusive access. The inner state is obtained via
Mutex::get_mut (no-lock fast path),
so flush and fsync execute outside any lock scope. This prevents
mutex contention with concurrent readers or writers during shutdown.
§Errors
Returns WalError if the flush or fsync fails.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for WalWriter
impl !RefUnwindSafe for WalWriter
impl !UnwindSafe for WalWriter
impl Send for WalWriter
impl Sync for WalWriter
impl Unpin for WalWriter
impl UnsafeUnpin for WalWriter
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more