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
53 lines
1.6 KiB
CMake
53 lines
1.6 KiB
CMake
# Generates migrations_embedded.hpp from daemon/src/store/migrations/*.sql.
|
|
#
|
|
# cmake -DMIG_DIR=<dir> -DOUT=<file> -P embed_migrations.cmake
|
|
#
|
|
# Each NNNN_name.sql becomes a Migration{ version = NNNN, name = "NNNN_name", sql = R"..." }.
|
|
# The delimiter for the raw string literal is chosen to not collide with the file body.
|
|
|
|
file(GLOB _sql_files "${MIG_DIR}/*.sql")
|
|
list(SORT _sql_files)
|
|
|
|
set(_entries "")
|
|
foreach(_f ${_sql_files})
|
|
get_filename_component(_stem "${_f}" NAME_WE) # 0001_initial
|
|
string(REGEX MATCH "^([0-9]+)_" _m "${_stem}")
|
|
if(NOT _m)
|
|
message(FATAL_ERROR "migration file '${_f}' does not start with NNNN_")
|
|
endif()
|
|
string(REGEX REPLACE "^0*([0-9]+)_.*$" "\\1" _ver "${_stem}")
|
|
|
|
file(READ "${_f}" _body)
|
|
# Pick a raw-string delimiter guaranteed absent from the body.
|
|
set(_delim "MIGSQL")
|
|
while(_body MATCHES "\\)${_delim}\"")
|
|
set(_delim "${_delim}X")
|
|
endwhile()
|
|
|
|
string(APPEND _entries
|
|
" Migration{ ${_ver}, \"${_stem}\", R\"${_delim}(\n${_body}\n)${_delim}\" },\n")
|
|
endforeach()
|
|
|
|
list(LENGTH _sql_files _count)
|
|
|
|
set(_out "// GENERATED by embed_migrations.cmake — do not edit. Source: src/store/migrations/*.sql
|
|
#pragma once
|
|
#include <array>
|
|
#include \"store/migrations.hpp\"
|
|
|
|
namespace velox::daemon::store {
|
|
|
|
inline constexpr std::array<Migration, ${_count}> kEmbeddedMigrations = {{
|
|
${_entries}}};
|
|
|
|
} // namespace velox::daemon::store
|
|
")
|
|
|
|
if(EXISTS "${OUT}")
|
|
file(READ "${OUT}" _existing)
|
|
if(_existing STREQUAL "${_out}")
|
|
return() # unchanged — do not rewrite, keeps the build stable
|
|
endif()
|
|
endif()
|
|
file(WRITE "${OUT}" "${_out}")
|