daemon: wire the engine into veloxd — the vertical slice runs end to end

CORE stage 8 merged, so vdm::Engine is linkable. This closes D4a and
narrows D4b: `velox add <url>` now actually downloads.

- sched/engine_port_core.hpp — the real EnginePort: forwards to a live
  vdm::Engine, keeps the DownloadHandle per task for pause/resume/
  cancel/provide_auth/decide/refresh_url, drives set_task_order /
  set_max_active_segments / set_host_segment_cap via
  engine.segment_budget(). CORE confirmed the admission model: DAEMON
  decides when to start(); the engine's own download_task calls
  register_task/set_want internally — DAEMON never touches per-task
  budget calls. EnginePort gains release(TaskId) so the port drops a
  handle when the task goes terminal.
- rpc/event_loop — EventLoop::post(fn): thread-safe, runs fn on the
  loop thread next iteration. The marshaller for engine-thread
  callbacks.
- main.cpp — constructs vdm::Engine + EnginePortCore + Scheduler
  (post_to_loop = loop.post). At startup: reconcile_after_restart()
  (ADR 0013 §5), reload_config(), tick(). A 1 s timerfd on the loop
  re-runs tick() (schedule windows, missed nudges); download.add nudges
  via dispatcher.set_on_mutation.

End-to-end verified against tools/testserver: `velox add
http://127.0.0.1:.../file/512K` -> task queued -> scheduler admits ->
engine downloads 524288 bytes -> complete, file on disk. First
byte-path all the way through the project.

safepath-adversarial.md: re-verified per its own note — CORE landed
O_NOFOLLOW on the target open (core/src/io/sparse_file.cpp), so the
leaf-symlink TOCTOU is now closed; residual is down to one
intermediate-dir gap (documented post-M1 chase).

36 daemon/cli tests green; scheduler + uds_roundtrip TSan-clean.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Upd9WhG9oppieig5nRDLig
This commit is contained in:
2026-09-10 20:36:11 +04:00
co-authored by Claude Sonnet 5
parent d93c8e10a0
commit 08d7ee9263
11 changed files with 171 additions and 21 deletions
+41
View File
@@ -15,14 +15,20 @@
#include <sys/un.h>
#include <unistd.h>
#include <sys/timerfd.h>
#include "rpc/dispatcher.hpp"
#include "rpc/event_loop.hpp"
#include "rpc/pairing.hpp"
#include "rpc/runtime_dir.hpp"
#include "rpc/uds_server.hpp"
#include "rpc/ws_server.hpp"
#include "sched/engine_port_core.hpp"
#include "sched/governor.hpp"
#include "sched/scheduler.hpp"
#include "store/migrations.hpp"
#include "store/sqlite.hpp"
#include "vdm/engine.hpp"
#include "version.hpp"
namespace {
@@ -101,7 +107,38 @@ int main() {
return 1;
}
// --- engine + scheduler ---------------------------------------------------------
vdm::Engine engine;
velox::daemon::sched::EnginePortCore engine_port(engine);
velox::daemon::sched::Scheduler scheduler(
*db, engine_port, velox::daemon::sched::Governor{},
{/*local_now*/ {},
/*post_to_loop*/ [&loop](std::function<void()> fn) { loop.post(std::move(fn)); }});
if (const auto ec = scheduler.reconcile_after_restart(); !ec)
std::cerr << "veloxd: restart reconcile: " << ec.error().to_string() << "\n";
(void)scheduler.reload_config();
(void)scheduler.tick(); // admit anything already queued in the DB
velox::daemon::rpc::VeloxDispatcher dispatcher(*db);
dispatcher.set_on_mutation([&loop, &scheduler] {
loop.post([&scheduler] { (void)scheduler.tick(); });
});
// A 1 s timer re-runs the scheduler so schedule windows opening/closing and any
// missed nudge are picked up. Registered on the loop, no extra thread.
const int tick_fd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
if (tick_fd >= 0) {
itimerspec spec{};
spec.it_value.tv_sec = 1;
spec.it_interval.tv_sec = 1;
::timerfd_settime(tick_fd, 0, &spec, nullptr);
loop.add_fd(tick_fd, velox::daemon::rpc::kRead, [&](int fd, unsigned) {
std::uint64_t ticks = 0;
[[maybe_unused]] ssize_t n = ::read(fd, &ticks, sizeof(ticks));
(void)scheduler.tick();
});
}
velox::daemon::rpc::UdsServer uds(loop, dispatcher, rt.socket_path());
if (const auto ec = uds.start()) {
@@ -128,6 +165,10 @@ int main() {
loop.run();
std::cout << "veloxd: shutting down\n";
if (tick_fd >= 0) {
loop.del_fd(tick_fd);
::close(tick_fd);
}
g_loop = nullptr;
::close(lock_fd);
return 0;