daemon: D4b — download.pause/resume/start/cancel and queue.start/stop drive the scheduler
download.pause/resume/start/cancel and queue.start/stop were stubs; now they call into the scheduler and take effect immediately, not on the next 1s tick — pausing, resuming or cancelling a live transfer can't wait, and per ADR 0013 §3 the governor never touches a user-owned pause on its own. New rpc::TaskActionPort interface (owned by rpc/, implemented by sched::Scheduler) is what dispatcher.hpp depends on instead of sched/scheduler.hpp directly. Needed because veloxd_sched already links veloxd_rpc (for EventHub); dispatcher.hpp pulling in sched/scheduler.hpp directly would make it a real circular library dependency, breaking anything that links veloxd_rpc alone (cli's tests, as it turned out — hit and fixed during this change). Scheduler::user_pause/user_resume/user_start/user_cancel + pause_queue follow tick()'s existing to_pause pattern: call the engine (async, no synchronous effect) and transition the store eagerly so download.get/list are correct the instant the RPC call returns. Fixed a real bug surfaced while building this: transition() always overwrote pause_reason to NULL when the engine's own delayed pause-ack callback (on_state to paused, no error) arrived after whoever actually initiated the pause had already written the real reason — now it preserves the stored reason when the callback supplies none, instead of clobbering it. Covered by a regression check in sched_scheduler_test. store/queues gets get() and set_state() (was list()-only) for queue.start/stop. Verified against real veloxd + tools/testserver, not just unit tests: pausing a live single-segment throttled transfer freezes downloadedBytes, resume continues it from that point, cancel stops it; a bad taskId comes back in BulkTaskResult.failed with -32010, not a crash; queue.stop(pauseRunning:true) pauses the queue's running task immediately and queue.start resumes admission. Known gap: download.start's contract "a task in 'queued' jumps its queue" (priority bump) is not implemented — admission is still plain FIFO by created_at. Noted in deferrals.md. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01GRDjHGgpYmMoPE2UFbe7pP
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
// The seam between the dispatcher and the scheduler for user-initiated task/queue actions
|
||||
// (download.pause/resume/start/cancel, queue.stop's pauseRunning) — owned by rpc/ so
|
||||
// dispatcher.hpp (part of veloxd_rpc) never has to include sched/scheduler.hpp, which
|
||||
// would make veloxd_rpc depend on veloxd_sched at compile time. veloxd_sched already
|
||||
// depends on veloxd_rpc (for EventHub); the other direction too would be a real circular
|
||||
// library dependency, not just an inconvenience — anything linking veloxd_rpc alone (e.g.
|
||||
// the CLI's tests) would fail to link over symbols it never calls.
|
||||
//
|
||||
// sched::Scheduler implements this directly (it already lives in a library that depends on
|
||||
// rpc/, so adding an rpc-defined base costs nothing new); main.cpp hands the dispatcher a
|
||||
// `TaskActionPort*` pointing at the same Scheduler it constructs.
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace velox::daemon::rpc {
|
||||
|
||||
class TaskActionPort {
|
||||
public:
|
||||
virtual ~TaskActionPort() = default;
|
||||
|
||||
// Mirrors sched::Scheduler::UserActionResult: whether the task was found at all,
|
||||
// whether it actually changed state (a task already in the target/a terminal state is
|
||||
// reported found=true, changed=false — BulkTaskResult's own "not an error" contract),
|
||||
// and its resulting/current state spelling either way.
|
||||
struct Result {
|
||||
bool found = false;
|
||||
bool changed = false;
|
||||
std::string state;
|
||||
};
|
||||
|
||||
virtual Result user_pause(const std::string& wire_id) = 0;
|
||||
virtual Result user_resume(const std::string& wire_id) = 0;
|
||||
virtual Result user_start(const std::string& wire_id) = 0;
|
||||
virtual Result user_cancel(const std::string& wire_id, bool discard_partial) = 0;
|
||||
|
||||
// queue.stop(pauseRunning=true): pause every currently-running task in `queue_id` now.
|
||||
// Returns the wire ids actually paused.
|
||||
virtual std::vector<std::string> pause_queue(const std::string& queue_id) = 0;
|
||||
};
|
||||
|
||||
} // namespace velox::daemon::rpc
|
||||
Reference in New Issue
Block a user