#pragma once // The seam between the Scheduler and CORE's engine. Everything the Scheduler drives on the // engine goes through this interface, so the Scheduler is unit-testable without a live // engine and the daemon is not bound to the concrete `vdm::Engine`. The real // implementation (engine_port_core, added when velox::core's stage-8 bodies reach main) // wraps `vdm::Engine` + `vdm::segment::SegmentBudget`; FakeEnginePort records calls. // // Task ids here are `vdm::TaskId` — the engine assigns one from start() and the Scheduler // keeps the wire-UUID <-> TaskId map (ADR 0013). Admission is the Scheduler's: it calls // start() only for a task the governor admitted, and the engine begins probing at once // (it does not queue). The min-1 fairness rule in SegmentBudget then guarantees each // started task a slot; set_task_order pushes the priority. #include #include #include #include #include "vdm/ids.hpp" #include "vdm/task/download.hpp" namespace velox::daemon::sched { class EnginePort { public: virtual ~EnginePort() = default; virtual vdm::TaskId start(const vdm::task::DownloadSpec& spec, vdm::task::DownloadCallbacks callbacks) = 0; virtual void pause(vdm::TaskId) = 0; virtual void resume(vdm::TaskId) = 0; virtual void cancel(vdm::TaskId, bool discard_partial) = 0; virtual void provide_auth(vdm::TaskId, const std::string& username, const std::string& password, bool remember) = 0; virtual void decide(vdm::TaskId, vdm::task::Decision) = 0; virtual void refresh_url(vdm::TaskId, const std::string& url) = 0; // The daemon is done with this task (it went terminal). Drop the handle. Idempotent. virtual void release(vdm::TaskId) = 0; // ADR 0011 admission surface. Values are DAEMON's; enforcement is the engine's. virtual void set_task_order(const std::vector& order) = 0; virtual void set_max_active_segments(std::uint32_t n) = 0; virtual void set_host_segment_cap(const std::string& host, std::uint32_t cap) = 0; }; } // namespace velox::daemon::sched