Skip to content

craft: in-memory reference model + client-facing API surface#166

Merged
szmyd merged 1 commit into
eBay:dev/v6.xfrom
szmyd:craft/in-memory-reference-model
Jul 8, 2026
Merged

craft: in-memory reference model + client-facing API surface#166
szmyd merged 1 commit into
eBay:dev/v6.xfrom
szmyd:craft/in-memory-reference-model

Conversation

@szmyd

@szmyd szmyd commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

What & why

The production CRAFT path (CraftReplDev) is HomeStore-coupled and the wire transport is still
undecided (CRAFT-1), so a client has nothing to build against yet. This adds a HomeStore-free,
in-process reference model of the CRAFT server side
-- a correctness oracle a client can be built and
tested against now -- plus the client-facing CRAFT API that model (and, later, production) exposes.
Canonical protocol lives in the CRAFT-Design wiki and docs/craft/.

Blast radius is small: the product IO path is untouched (purely additive), and the only deletion is the
obsolete disabled memory_backend stub.

The API a client builds against (home_blocks.hpp)

Per-replica free functions over the opaque volume_handle -- one handle == one replica device (a
server in production; an in-process object here). The client does the CRAFT work: assign dLSN,
broadcast the write to each member, tally quorum, route the read to one member.

async_result<LoginResult> login(volume_handle, uint64_t client_token);
async_status              async_write(volume_handle, client_hdr, int64_t dlsn,
                                      uint64_t addr, uint64_t len, sisl::sg_list data);
async_result<std::vector<io_extent>>
                          async_read(volume_handle, client_hdr, int64_t read_lsn,
                                     uint64_t addr, uint64_t len, sisl::sg_list dest);
async_result<LSNPair>     keep_alive(volume_handle, client_hdr);

Design points -- each deliberate; flagging so they don't need re-litigating in review:

  • client_hdr {term, commit_lsn, all_committed_lsn} on every IO. Commit is piggybacked via
    commit_lsn -- there is no standalone commit verb (matches the design's "commit / keep_alive /
    piggyback on the next write"). keep_alive is its dedicated carrier and is term-fenced (a stale
    client must not be able to reset the liveness watchdog and stall failover).
  • Byte-based addr/len, aligned to lba_size (returned by login), enforced server-side with
    invalid_argument -- consistent with the existing byte-based block API; byte↔block conversion stays
    inside the server.
  • One buffer type both ways: sisl::sg_list (caller/iomgr-owned). An empty buffer is a zero
    write
    (WRITE_ZEROES) -- no all_zeros flag. Reads fill the caller's dest buffer and return a
    sparse io_extent layout (which byte ranges were data vs holes).
  • Legacy byte block ops (async_read/async_write/async_unmap) are [[deprecated]], kept as
    reference; the deprecation is demoted to a warning on the three existing callers via
    -Wno-error=deprecated-declarations so -Werror stays green.

The model (src/lib/craft/memory/)

  • MemCraftReplica (implements the internal craft_replica) -- the protocol, and the reviewable
    meat
    : dLSN→slot journal, per-LBA index, journal-tail overlay, horizon-clamped sparse reads
    (data / holes / all-zero-collapse in read_range()), term fencing, in-order commit apply.
  • MemTransport -- in-process stand-in for the network + the cold path (fixed leader, login
    orchestration GetRSCommitLSN → SyncRSCommitLSN → InternalLogin) + fault hooks
    (set_up / force_subquorum). No production analog -- real servers + config play that role.
  • create_memory_volume / make_memory_replica_set -- the thin adapter that wraps each replica
    behind a volume_handle; the only glue that reuses volume (and therefore links HomeStore).

HomeStore-free by construction: the model lib references no engine symbol -- its unit-test binary
links sisl + gtest without homestore::homestore and still resolves (an undefined-symbol error
would mean it touched the engine). Coroutines complete inline, so tests need no iomgr reactor.

Review guide

Area Files
Public API + shared client types include/homeblks/{home_blocks.hpp, craft_types.hpp}
Backend seam on volume lib/craft/craft_replica.hpp, lib/volume/volume.hpp (memory-mode ctor + nullable craft_backend_), lib/craft/craft_api.cpp
Model logic lib/craft/memory/mem_craft_replica.{hpp,cpp} (start at read_range), mem_craft_cluster.{hpp,cpp}
Adapter → volume_handle lib/craft/memory/mem_craft_volume.{hpp,cpp}
Tests lib/craft/memory/tests/

Testing

cmake --build build/Release --target test_craft_memory --target test_craft_e2e
ctest --test-dir build/Release -R CraftMemory

15 model unit tests (login→write→keep_alive→read, overlay read above a committed hole, horizon clamp,
zero write & all-zero-data collapse, commit stall-at-gap / piggyback-on-write / piggyback-on-read, term
fencing incl. keep_alive, misalignment rejection, replica-down & sub-quorum faults) + 3 end-to-end
tests through the public volume_handle API. Existing test_volume / test_volume_io / homeblk_ublk
still build (legacy calls emit deprecation warnings, not errors).

Out of scope (seams left in place)

Full resync / FetchData fill loop, Empty/Missing verdicts, failed-sub-quorum-write resolution,
reconfiguration (S10), skinny mode, logout/lease + stand-in client, journal reclaim, and crash/restart
recovery. docs/craft/{api,rpcs,README}.md are updated to the surface landed here.

Notes for reviewers

  • lba_t / lba_count_t moved to the shared HomeStore-free craft_types.hpp (still reachable
    everywhere via home_blocks.hpp); the byte-based public API uses raw uint64_t.
  • The production CraftReplDev (S1 stub) is otherwise untouched -- it just now includes
    craft_replica.hpp for the shared internal types (CraftPartitionState, JournalSlot), which moved
    off the public surface.
  • Not included here: an unrelated pre-existing conanfile.py ublkpp version bump.

🤖 Generated with Claude Code

Add a HomeStore-free, in-process reference model of the CRAFT replication
protocol (the server side) so a client can be built and tested against it,
plus the client-facing CRAFT API it exposes.

Public API (home_blocks.hpp): per-replica CRAFT free functions over an opaque
volume_handle -- login / async_write / async_read / keep_alive -- each carrying
a client_hdr {term, commit_lsn, all_committed_lsn}. Addressing is byte-based
(addr/len aligned to lba_size, returned by login and enforced server-side);
sisl::sg_list is the one buffer type both ways (an empty buffer is a zero
write); reads fill the caller's buffer and return a sparse io_extent layout.
Commit is piggybacked via client_hdr.commit_lsn -- there is no standalone
commit verb -- and keep_alive is its term-fenced carrier. The legacy byte
block ops are marked [[deprecated]] (kept as reference).

Model (src/lib/craft/memory/): MemCraftReplica implements the internal
craft_replica backend (journal, per-LBA index, journal-tail overlay,
horizon-clamped sparse reads, term fencing, in-order commit apply);
MemTransport is the in-process network + cold path (fixed leader, login
orchestration) + fault hooks (replica down/up, sub-quorum).
create_memory_volume / make_memory_replica_set wrap each replica behind a
volume_handle (one handle == one replica device; no aggregate handle). The
model links no HomeStore -- its unit-test binary proves it -- and only the
create_memory_volume glue reuses volume (and thus links the engine).

Tests: 15 model unit tests (no HomeStore, no iomgr reactor; ops complete
inline) + 3 end-to-end tests through the public volume_handle API.

Docs: docs/craft/{api,rpcs,README}.md updated to the landed surface.

Also removes the obsolete disabled memory_backend stub.
@szmyd szmyd force-pushed the craft/in-memory-reference-model branch from a8cbce7 to d7b9848 Compare July 8, 2026 14:40
@eBay eBay deleted a comment from ne1k0 Jul 8, 2026
@szmyd szmyd merged commit c9c1b97 into eBay:dev/v6.x Jul 8, 2026
24 of 26 checks passed
@szmyd szmyd deleted the craft/in-memory-reference-model branch July 8, 2026 14:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant