#core/persistence/wal

    Write-Ahead Log (WAL) for crash recovery.

    #Format

    Header (12 bytes): - Magic: "VCDBMBT\0" (8 bytes) - Type: 1 byte - Version: 1 byte - Reserved: 2 bytes Records: - Type: 1 byte (Upsert/Remove/SetAttrs) - Reserved: 1 byte - ID: 8 bytes - AttrsLen: 4 bytes - VectorLen: 4 bytes - Attrs: JSON UTF-8 - Vector: Float32 array Footer (8 bytes, optional): - Magic: "WCRC" (4 bytes) - CRC32: 4 bytes

    #Record Types

    • Upsert: Insert or update vector with attrs
    • Remove: Delete vector
    • SetAttrs: Update attrs only

    #Usage

    let writer = WalWriter::new()
    writer.write_upsert(id, vector, attrs)
    let bytes = writer.finalize()

    AsyncWalRuntime

    pub struct AsyncWalRuntime[S] {
    storage : S
    path : String
    kind :
    StorageKind

    data : Bytes
    record_count : Int
    loaded : Bool
    }

    AsyncWalRuntime::append

    Append records to the WAL. Merges in-memory (no read from storage), then writes to storage. Delegates merge logic to format.mbt's merge_wal.

    AsyncWalRuntime::async_exists

    Check if WAL exists on storage.

    AsyncWalRuntime::byte_size

    fn[S] AsyncWalRuntime::byte_size(self : AsyncWalRuntime[S]) -> Int

    Current WAL data size in bytes (for byte-size checkpoint decisions).

    AsyncWalRuntime::is_loaded

    fn[S] AsyncWalRuntime::is_loaded(self : AsyncWalRuntime[S]) -> Bool

    Whether load() has been called.

    AsyncWalRuntime::load

    Load WAL data from storage into the in-memory buffer. Must be called once before append/truncate. Idempotent. Returns the WAL data bytes (for callers that need it, e.g., replay).

    AsyncWalRuntime::new

    fn[S] AsyncWalRuntime::new(storage : S, path : String, kind? :
    StorageKind
    ) -> AsyncWalRuntime[S]

    AsyncWalRuntime::path

    fn[S] AsyncWalRuntime::path(self : AsyncWalRuntime[S]) -> String

    Get the WAL file path.

    AsyncWalRuntime::record_count

    fn[S] AsyncWalRuntime::record_count(self : AsyncWalRuntime[S]) -> Int

    Number of records in the current WAL buffer (since last truncate).

    AsyncWalRuntime::replay_into

    Replay WAL records into a CoreStore. Returns number of records applied. Delegates replay logic to replay_wal_data in runtime.mbt.

    Uses in-memory buffer if loaded, otherwise reads from storage.

    AsyncWalRuntime::truncate

    Truncate the WAL — reset in-memory buffer and write empty header.

    WalRecord

    pub struct WalRecord {
    record_type : WalRecordType
    id :
    VectorId

    attrs :
    Attrs
    ?
    vector : Array[Double]?
    timestamp : Int64
    } derive(
    Debug
    )

    WAL record with timestamp
    impl Show for WalRecord

    WalRecord::remove

    fn WalRecord::remove(id :
    VectorId
    , timestamp? : Int64) -> WalRecord

    Create a remove record with timestamp

    WalRecord::set_attrs

    Create a set_attrs record with timestamp

    WalRecord::upsert

    fn WalRecord::upsert(id :
    VectorId
    , vector : Array[Double], attrs :
    Attrs
    , timestamp? : Int64) -> WalRecord

    Create an upsert record with timestamp

    WalRecordType

    pub enum WalRecordType {
    Upsert
    Remove
    SetAttrs
    } derive(Eq,
    Debug
    )

    WAL record types

    WalRecordType::from_byte

    fn WalRecordType::from_byte(b : Byte) -> WalRecordType?

    WalRecordType::to_byte

    fn WalRecordType::to_byte(self : WalRecordType) -> Byte

    decode_wal_record

    Decode a WAL record from reader (public entry point — assumes v3 format). For reading v1/v2 WAL files, use decode_wal_records which handles versioning.

    decode_wal_records

    fn decode_wal_records(data : Bytes) -> Array[WalRecord]

    Decode all records from WAL data (supports v1, v2, and v3)
    fn encode_wal_footer(body : Bytes) -> Bytes

    Encode WAL footer with CRC32

    encode_wal_header

    fn encode_wal_header() -> Bytes

    Encode WAL header (12 bytes)

    encode_wal_record

    fn encode_wal_record(record : WalRecord) -> Bytes

    Encode a WAL record to bytes (v2 format with timestamp)

    encode_wal_segment

    fn encode_wal_segment(records : Array[WalRecord]) -> Bytes

    Encode multiple records to a complete WAL segment

    filter_wal_by_timestamp

    fn filter_wal_by_timestamp(data : Bytes, cutoff_ts : Int64) -> Array[WalRecord]

    Filter WAL records by timestamp — returns only records with timestamp <= cutoff. Used for read-at-timestamp (consistent cross-shard reads).

    max_wal_timestamp

    fn max_wal_timestamp(data : Bytes) -> Int64

    Get the maximum timestamp across all records in a WAL. Returns 0 if no timestamped records.

    merge_wal

    fn merge_wal(existing : Bytes, new_segment : Bytes) -> Bytes

    Merge an existing WAL with a new WAL segment.

    replay_wal_data

    fn replay_wal_data(data : Bytes, store :
    CoreStore
    , cutoff_ts? : Int64) -> Int

    Replay WAL binary data into a CoreStore (no Storage dependency). Used by:
    • AsyncWalRuntime::replay_into (reads from AsyncStorage, then delegates here)
    • JS persistent exports (passes WAL bytes directly)

    Returns the number of records applied. Returns 0 for empty/invalid data.

    verify_wal_checksum

    fn verify_wal_checksum(data : Bytes) -> Bool

    Check if WAL has valid footer and verify CRC32

    verify_wal_header

    fn verify_wal_header(r :
    BinaryReader
    ) -> Bool

    Verify WAL header (accepts v1, v2, and v3). Returns the version byte on success.
    let wal_footer_magic : UInt

    WAL Footer magic: "WCRC" in little-endian

    wal_records_for_replay

    fn wal_records_for_replay(data : Bytes, cutoff_ts? : Int64) -> Array[WalRecord]

    Decode replayable WAL records after validating header and checksum.

    wal_version

    let wal_version : Byte

    Current WAL format version