Closes a bounded, high-value slice of the remaining D3 stubs. settings.*/rules.*/ limiter.*/schedule.*/grabber.*/media.*/capture.*/queue.reorder/download.refreshUrl/ download.update stay deferred — reasons noted individually in deferrals.md (settings.* specifically: a real, large field<->key<->JSON-type mapping table across ~43 fields / ~50 SettingKeys, not started rather than rushed). category.upsert/remove: store/categories.hpp gains get/upsert/remove. upsert generates an id when absent and always ignores the payload's `builtin` (preserved from the existing row on replace, false on create); saveDir goes through the same fs::resolve_target canonicalize-and-root-check as download.add. remove refuses a builtin at both layers (dispatcher's -32602 pre-check; the store's own "DELETE ... AND builtin = 0" as defense in depth) and reassigns member tasks to reassignTo (default "general") inside one transaction before deleting the row. queue.upsert: store/queues.hpp gains get/upsert (set_state already existed from D4b). Same create-generates-id pattern; a create always starts 'stopped', a replace keeps the queue's current run state (upsert edits config, not run state — that's queue.start/stop). Also fixed in passing: on_complete has been a real column since migration 0001 but Queues::list/get never projected it onto Queue.onComplete. download.remove: cancels with discard_partial=true (always drops the .veloxpart pair — unlike download.cancel, which keeps them, the row is gone either way), deletes the finished file only when deleteFile is true and the task was complete (best-effort), deletes the row (segments cascade via the FK), and publishes event.task.removed (closing the last open note under D5). download.addBatch: on_download_add's body is now a shared add_one(), called once per item after merging each item's unset fields against params.defaults. download.provideAuth: forwards to EnginePort::provide_auth via a new TaskActionPort::provide_auth. `remember`/persisting to the Secret Service is accepted but not acted on — nothing in this build talks to libsecret yet. Verified against real veloxd + tools/testserver: category create/replace/ remove-with-reassignment, queue create/replace-keeps-run-state, a batch add sharing defaults.saveDir, and download.remove with deleteFile actually deleting the file and the task then 404ing download.get with -32010. Full ctest: 39/39. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01GRDjHGgpYmMoPE2UFbe7pP
132 lines
7.7 KiB
C++
132 lines
7.7 KiB
C++
#pragma once
|
|
|
|
// VeloxDispatcher implements the generated velox::proto::Dispatcher — one virtual per RPC
|
|
// method. The generated dispatch() does the envelope, the transport check and the param
|
|
// parse; a method here only ever sees a validated, typed params struct and returns a
|
|
// typed result.
|
|
//
|
|
// Scope of this drop (AGENT-DAEMON.md build order): the transports are real and the store
|
|
// is behind download.add / download.list / download.get. session.hello / session.pair /
|
|
// session.subscribe are handled in the server layer (connection- and transport-stateful)
|
|
// and never reach this class in the running daemon. Everything else still returns
|
|
// "not implemented in this build" (-> -32603) until its handler and the scheduler land;
|
|
// see daemon/docs/deferrals.md.
|
|
|
|
#include <functional>
|
|
|
|
#include "rpc/event_hub.hpp"
|
|
#include "rpc/task_action_port.hpp"
|
|
#include "store/sqlite.hpp"
|
|
#include "velox_proto.hpp"
|
|
|
|
namespace velox::daemon::rpc {
|
|
|
|
class VeloxDispatcher final : public velox::proto::Dispatcher {
|
|
public:
|
|
// `actions` drives download.pause/resume/start/cancel and queue.start/stop
|
|
// immediately (D4b) — those cannot wait for the next tick(), unlike download.add's
|
|
// on_mutation nudge. Optional so existing tests that only exercise download.add/list/
|
|
// get keep building with no scheduler at hand; a null actions_ makes those methods
|
|
// answer "not implemented" instead of crashing. See rpc/task_action_port.hpp for why
|
|
// this is an interface owned by rpc/ rather than a direct sched::Scheduler* (avoids a
|
|
// veloxd_rpc <-> veloxd_sched circular library dependency).
|
|
VeloxDispatcher(velox::daemon::store::Db& db, EventHub& hub, TaskActionPort* actions = nullptr)
|
|
: db_(db), hub_(hub), actions_(actions) {}
|
|
|
|
// Called after a handler mutates task state (download.add for now). main.cpp wires it
|
|
// to nudge the scheduler; unset in tests.
|
|
void set_on_mutation(std::function<void()> fn) { on_mutation_ = std::move(fn); }
|
|
|
|
velox::proto::HandlerResult<velox::proto::CaptureRules>
|
|
on_capture_getRules(const velox::proto::CaptureGetRulesParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::CaptureOfferResult>
|
|
on_capture_offer(const velox::proto::CaptureOfferParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::CategoryListResult>
|
|
on_category_list(const velox::proto::CategoryListParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::CategoryRemoveResult>
|
|
on_category_remove(const velox::proto::CategoryRemoveParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::CategoryUpsertResult>
|
|
on_category_upsert(const velox::proto::CategoryUpsertParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::DownloadAddResult>
|
|
on_download_add(const velox::proto::DownloadSpec&) override;
|
|
velox::proto::HandlerResult<velox::proto::DownloadAddBatchResult>
|
|
on_download_addBatch(const velox::proto::DownloadAddBatchParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::BulkTaskResult>
|
|
on_download_cancel(const velox::proto::DownloadCancelParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::TaskDetail>
|
|
on_download_get(const velox::proto::DownloadGetParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::DownloadListResult>
|
|
on_download_list(const velox::proto::DownloadListParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::BulkTaskResult>
|
|
on_download_pause(const velox::proto::DownloadPauseParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::DownloadProbeResult>
|
|
on_download_probe(const velox::proto::DownloadProbeParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::DownloadProvideAuthResult>
|
|
on_download_provideAuth(const velox::proto::DownloadProvideAuthParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::DownloadRefreshUrlResult>
|
|
on_download_refreshUrl(const velox::proto::DownloadRefreshUrlParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::DownloadRemoveResult>
|
|
on_download_remove(const velox::proto::DownloadRemoveParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::BulkTaskResult>
|
|
on_download_resume(const velox::proto::DownloadResumeParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::BulkTaskResult>
|
|
on_download_start(const velox::proto::DownloadStartParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::TaskSummary>
|
|
on_download_update(const velox::proto::DownloadUpdateParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::GrabberHarvestResult>
|
|
on_grabber_harvest(const velox::proto::GrabberHarvestParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::GrabberStartResult>
|
|
on_grabber_start(const velox::proto::GrabberStartParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::GrabberStatusResult>
|
|
on_grabber_status(const velox::proto::GrabberStatusParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::Limiter>
|
|
on_limiter_get(const velox::proto::LimiterGetParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::Limiter> on_limiter_set(const velox::proto::Limiter&) override;
|
|
velox::proto::HandlerResult<velox::proto::MediaAddVariantResult>
|
|
on_media_addVariant(const velox::proto::MediaAddVariantParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::MediaListVariantsResult>
|
|
on_media_listVariants(const velox::proto::MediaListVariantsParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::QueueListResult>
|
|
on_queue_list(const velox::proto::QueueListParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::QueueReorderResult>
|
|
on_queue_reorder(const velox::proto::QueueReorderParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::QueueStartResult>
|
|
on_queue_start(const velox::proto::QueueStartParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::QueueStopResult>
|
|
on_queue_stop(const velox::proto::QueueStopParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::QueueUpsertResult>
|
|
on_queue_upsert(const velox::proto::QueueUpsertParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::RulesListResult>
|
|
on_rules_list(const velox::proto::RulesListParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::RulesUpsertResult>
|
|
on_rules_upsert(const velox::proto::RulesUpsertParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::ScheduleGetResult>
|
|
on_schedule_get(const velox::proto::ScheduleGetParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::ScheduleSetResult>
|
|
on_schedule_set(const velox::proto::ScheduleSetParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::SessionHelloResult>
|
|
on_session_hello(const velox::proto::SessionHelloParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::SessionPairResult>
|
|
on_session_pair(const velox::proto::SessionPairParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::SessionSubscribeResult>
|
|
on_session_subscribe(const velox::proto::SessionSubscribeParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::SettingsGetResult>
|
|
on_settings_get(const velox::proto::SettingsGetParams&) override;
|
|
velox::proto::HandlerResult<velox::proto::SettingsSetResult>
|
|
on_settings_set(const velox::proto::SettingsSetParams&) override;
|
|
|
|
private:
|
|
// The whole of download.add's body; on_download_add and on_download_addBatch (each
|
|
// item merged against DownloadAddBatchParams.defaults first) both call this — exactly
|
|
// one place turns a DownloadSpec into a stored, admitted task.
|
|
velox::proto::HandlerResult<velox::proto::DownloadAddResult> add_one(
|
|
const velox::proto::DownloadSpec& spec);
|
|
|
|
velox::daemon::store::Db& db_;
|
|
EventHub& hub_;
|
|
TaskActionPort* actions_;
|
|
std::function<void()> on_mutation_;
|
|
};
|
|
|
|
} // namespace velox::daemon::rpc
|