daemon: store/ — SQLite WAL schema + forward-only migrator (build step 3)

The daemon's persistent state. SQLite in WAL mode, foreign keys on,
5 s busy timeout so a writer waits rather than SQLITE_BUSY under the
RPC loop.

- store/sqlite — RAII Db/Stmt over the C API; errors returned as
  DbResult<T> (std::expected), never thrown — the RPC loop must not
  unwind. transaction() helper: BEGIN / fn / COMMIT, ROLLBACK on error.
- store/migrations/0001_initial.sql — the eight tables from the brief:
  settings, categories, queues, tasks, segments, rules, history,
  pairings. Notable choices:
    * tasks columns project onto proto TaskSummary with no computation;
      requested vs effective segments/buffer split per ADR 0010/0012;
      pause_reason column per ADR 0013.
    * segments end_byte is NOT constrained >= 0 so a whole-file
      zero-length download is one row with end_byte = -1 (ADR 0010 B3a).
    * pairings stores only token_sha256 — the plaintext token is
      returned once from session.pair and never persisted (CLAUDE.md §4).
    * indices on tasks(state), (category_id), (queue_id, queue_position),
      (created_at), (completed_at) for the "1000 tasks, download.list
      under 50 ms" DoD.
    * six built-in categories + a Main queue seeded.
- store/migrations — runs every embedded migration past PRAGMA
  user_version, each in its own transaction, forward-only. SQL files
  are embedded at build time by cmake/embed_migrations.cmake.

Test veloxd.store_migrations (ASan+UBSan and TSan clean): fresh DB ->
head, all tables present, seed rows, FK cascade (segment orphan
rejected, task delete cascades), the end_byte=-1 zero-length case,
idempotent re-run, and forward-only from every released user_version.

Also: daemon/docs/proto-requests-m1.md — P1 marked landed on lane/proto
as 1.4.0 (HandlerError/HandlerResult), to be adopted in rpc/ once that
merges to main; P2 resolved.

Not linked into the running daemon yet — the store is wired to the
dispatcher when download.add/list/get get real bodies, next.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Upd9WhG9oppieig5nRDLig
This commit is contained in:
2026-09-10 15:27:20 +04:00
co-authored by Claude Sonnet 5
parent 0c7ce1437c
commit 4b279e8271
11 changed files with 731 additions and 1 deletions
+30 -1
View File
@@ -11,6 +11,35 @@ if(NOT TARGET nlohmann_json::nlohmann_json)
find_package(nlohmann_json 3.11 REQUIRED)
endif()
find_package(Threads REQUIRED)
find_package(SQLite3 REQUIRED)
# --- generated: migrations_embedded.hpp from src/store/migrations/*.sql ---------------
set(_mig_dir ${CMAKE_CURRENT_SOURCE_DIR}/src/store/migrations)
set(_mig_hdr ${CMAKE_CURRENT_BINARY_DIR}/generated/migrations_embedded.hpp)
file(GLOB _mig_srcs ${_mig_dir}/*.sql)
add_custom_command(
OUTPUT ${_mig_hdr}
COMMAND ${CMAKE_COMMAND} -DMIG_DIR=${_mig_dir} -DOUT=${_mig_hdr}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/embed_migrations.cmake
DEPENDS ${_mig_srcs} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/embed_migrations.cmake
COMMENT "Embedding SQL migrations"
VERBATIM)
add_custom_target(veloxd_migrations_hdr DEPENDS ${_mig_hdr})
# --- veloxd_store — SQLite store + migrations -----------------------------------------
add_library(veloxd_store STATIC
src/store/sqlite.cpp
src/store/migrations.cpp
${_mig_hdr}
)
add_library(velox::daemon_store ALIAS veloxd_store)
target_include_directories(veloxd_store
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/generated
)
target_compile_features(veloxd_store PUBLIC cxx_std_23)
target_compile_options(veloxd_store PRIVATE -Wall -Wextra -Wpedantic -Werror)
target_link_libraries(veloxd_store PUBLIC SQLite::SQLite3)
# --- veloxd_rpc — the server library ----------------------------------------------------
add_library(veloxd_rpc STATIC
@@ -34,7 +63,7 @@ target_link_libraries(veloxd_rpc
add_executable(veloxd src/main.cpp)
target_compile_features(veloxd PRIVATE cxx_std_23)
target_compile_options(veloxd PRIVATE -Wall -Wextra -Wpedantic -Werror)
target_link_libraries(veloxd PRIVATE veloxd_rpc)
target_link_libraries(veloxd PRIVATE veloxd_rpc veloxd_store)
if(VELOX_BUILD_TESTS AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt)
add_subdirectory(tests)