hive-agent: inline todo dispatch arms instead of a sub-match + unreachable!

per mara's review on #2679: replace the separate dispatch_todo sub-match
(with its trailing unreachable! arm) with four small handler functions
called directly from dispatch's existing match. same behavior, no
unreachable! left in the todo path.
This commit is contained in:
damocles 2026-07-25 18:42:10 +02:00
commit 6c886d3fa6

View file

@ -165,10 +165,26 @@ fn dispatch(
bus: &Bus,
) -> Response {
match req {
Request::UpsertTodo { .. }
| Request::ClearTodo { .. }
| Request::ListTodos { .. }
| Request::MarkTodoDone { .. } => dispatch_todo(req, store, wake),
Request::UpsertTodo {
subsystem,
key,
summary,
source,
} => upsert_todo(
store,
wake,
&subsystem,
key.as_deref(),
&summary,
source.as_deref(),
),
Request::ClearTodo {
subsystem,
key,
all,
} => clear_todo(store, &subsystem, key.as_deref(), all),
Request::ListTodos { subsystem } => list_todos(store, subsystem.as_deref()),
Request::MarkTodoDone { id } => mark_todo_done(store, id),
Request::StoreReminder {
message,
timing,
@ -221,61 +237,68 @@ fn dispatch(
}
}
/// Todo-family requests (loose-ends v2). `req` is guaranteed by [`dispatch`]
/// to be one of the four todo variants; any other variant is a caller bug.
fn dispatch_todo(req: Request, store: &Todos, wake: &Notify) -> Response {
match req {
Request::UpsertTodo {
subsystem,
key,
summary,
source,
} => match store.upsert(&subsystem, key.as_deref(), &summary, source.as_deref()) {
Ok((id, changed)) => {
tracing::debug!(subsystem = %subsystem, key = ?key, id, changed, "todo upsert");
if changed {
wake.notify_one();
}
Response::Ok
/// `UpsertTodo` handler: writes/refreshes a todo row, logs the outcome, and
/// fires `wake` on a new-or-changed upsert so the serve loop runs a turn.
fn upsert_todo(
store: &Todos,
wake: &Notify,
subsystem: &str,
key: Option<&str>,
summary: &str,
source: Option<&str>,
) -> Response {
match store.upsert(subsystem, key, summary, source) {
Ok((id, changed)) => {
tracing::debug!(%subsystem, ?key, id, changed, "todo upsert");
if changed {
wake.notify_one();
}
Err(e) => err(&e),
},
Request::ClearTodo {
subsystem,
key,
all,
} => {
let result = if all {
store.clear_subsystem(&subsystem)
} else {
store.clear(&subsystem, key.as_deref())
};
match result {
Ok(count) => {
tracing::debug!(subsystem = %subsystem, key = ?key, all, count, "todo clear");
Response::Acked {
count: u64::try_from(count).unwrap_or(0),
}
}
Err(e) => err(&e),
Response::Ok
}
Err(e) => err(&e),
}
}
/// `ClearTodo` handler: drops one keyed todo, or every todo in `subsystem`
/// when `all` is set.
fn clear_todo(store: &Todos, subsystem: &str, key: Option<&str>, all: bool) -> Response {
let result = if all {
store.clear_subsystem(subsystem)
} else {
store.clear(subsystem, key)
};
match result {
Ok(count) => {
tracing::debug!(%subsystem, ?key, all, count, "todo clear");
Response::Acked {
count: u64::try_from(count).unwrap_or(0),
}
}
Request::ListTodos { subsystem } => match store.list(subsystem.as_deref()) {
Ok(todos) => Response::LooseEnds {
loose_ends: todos.into_iter().map(to_loose_end).collect(),
},
Err(e) => err(&e),
Err(e) => err(&e),
}
}
/// `ListTodos` handler: read-only, so no debug logging — not relevant to
/// diagnosing wake behaviour.
fn list_todos(store: &Todos, subsystem: Option<&str>) -> Response {
match store.list(subsystem) {
Ok(todos) => Response::LooseEnds {
loose_ends: todos.into_iter().map(to_loose_end).collect(),
},
Request::MarkTodoDone { id } => match store.mark_done(id) {
Ok(count) => {
tracing::debug!(id, count, "todo mark-done");
Response::Acked {
count: u64::try_from(count).unwrap_or(0),
}
Err(e) => err(&e),
}
}
/// `MarkTodoDone` handler: marks a single todo done by id.
fn mark_todo_done(store: &Todos, id: i64) -> Response {
match store.mark_done(id) {
Ok(count) => {
tracing::debug!(id, count, "todo mark-done");
Response::Acked {
count: u64::try_from(count).unwrap_or(0),
}
Err(e) => err(&e),
},
_ => unreachable!("dispatch only routes todo variants here"),
}
Err(e) => err(&e),
}
}