hive-c0re: push HelperEvent::Spawned as a todo, not a broker message
Follow-up from #2955 (mara: 'make core able to give agent a todo'). First migration slice: Spawned was pure FYI-check-when-convenient material, not something needing an immediate turn. Coordinator::push_todo/push_todo_submitter do a best-effort live dial of the target agent's own hive-agent-sock (hive_host_sock::agent_todo_ socket), sending the exact UpsertTodo request in-container producers (matrix/bash/forge-notify) already send. Push, not queue: agent offline (socket absent) or dial failure is a silent no-op, no retry, no fallback delivery -- matches mara's 'not available if offline' call exactly. HelperEvent::Spawned removed entirely (enum variant + all 3 call sites migrated: handle_spawn's two arms, finish_approval's Spawn approval-kind arm) rather than kept alongside a translation layer -- per mara's correction on the first design attempt, migrating the producer means deleting the old path, not bridging it. Verified: cargo build/clippy/test -p hive-c0re -p hive-host-sock -p hive-sh4re clean (318 tests), nix fmt clean.
This commit is contained in:
parent
f60e8a8470
commit
d77f81cd1e
8 changed files with 150 additions and 37 deletions
|
|
@ -1355,12 +1355,91 @@ impl Coordinator {
|
|||
/// failure — fall back to the root agent, preserving the prior
|
||||
/// always-root behaviour.
|
||||
pub fn notify_submitter(&self, approval_id: i64, event: &hive_sh4re::HelperEvent) {
|
||||
let target = self
|
||||
.approvals
|
||||
let target = self.submitter_or_manager(approval_id);
|
||||
self.notify_agent(&target, event);
|
||||
}
|
||||
|
||||
/// Shared resolution for "which agent should hear about approval
|
||||
/// `approval_id`" — the authenticated socket caller at submit time,
|
||||
/// falling back to the manager for legacy rows with no recorded
|
||||
/// submitter (or any lookup failure). Used by both `notify_submitter`
|
||||
/// and `push_todo_submitter` so the fallback rule lives in one place.
|
||||
fn submitter_or_manager(&self, approval_id: i64) -> String {
|
||||
self.approvals
|
||||
.submitter_of(approval_id)
|
||||
.unwrap_or_default()
|
||||
.unwrap_or_else(|| hive_sh4re::MANAGER_AGENT.to_owned());
|
||||
self.notify_agent(&target, event);
|
||||
.unwrap_or_else(|| hive_sh4re::MANAGER_AGENT.to_owned())
|
||||
}
|
||||
|
||||
/// Push a todo directly into `agent`'s in-container todo store — a
|
||||
/// best-effort *live* dial of its `hive-agent-sock` socket
|
||||
/// (`hive_host_sock::agent_todo_socket`), same `UpsertTodo` request
|
||||
/// shape the in-container producers (matrix/bash/forge-notify)
|
||||
/// already send. This is the migration target for `HelperEvent`
|
||||
/// variants that are pure "FYI, check when convenient" notices: the
|
||||
/// event stops being a broker `Message` (which always drives an
|
||||
/// immediate turn) and becomes a todo instead, with the same
|
||||
/// dedup-by-key semantics as any other producer.
|
||||
///
|
||||
/// Deliberately push, not queue: if the agent's container is down
|
||||
/// (socket file absent) or the dial otherwise fails, this is a
|
||||
/// silent no-op (logged at `debug`/`warn`) — no retry, no fallback
|
||||
/// delivery. An agent that's down doesn't need a todo about
|
||||
/// something it'll never see appear this way; whatever mechanism
|
||||
/// resurfaces its state on the next boot is unrelated to this path.
|
||||
pub async fn push_todo(
|
||||
&self,
|
||||
agent: &str,
|
||||
subsystem: &str,
|
||||
key: Option<String>,
|
||||
summary: String,
|
||||
source: Option<String>,
|
||||
) {
|
||||
let Ok(ident) = hive_types::Ident::parse(agent) else {
|
||||
tracing::warn!(%agent, "push_todo: not a valid agent ident, skipping");
|
||||
return;
|
||||
};
|
||||
let path = hive_host_sock::agent_todo_socket(&ident);
|
||||
if !path.exists() {
|
||||
tracing::debug!(%agent, path = %path.display(), "push_todo: agent socket not present (offline?), skipping");
|
||||
return;
|
||||
}
|
||||
let req = hive_agent_sock::Request::UpsertTodo {
|
||||
subsystem: subsystem.to_owned(),
|
||||
key,
|
||||
summary,
|
||||
source,
|
||||
};
|
||||
match hive_sock_client::request::<_, hive_agent_sock::Response>(
|
||||
&path,
|
||||
&req,
|
||||
hive_sock_client::Retry::None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(hive_agent_sock::Response::Err { message }) => {
|
||||
tracing::warn!(%agent, %message, "push_todo: agent rejected the todo");
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::warn!(%agent, error = ?e, "push_todo: dial failed");
|
||||
}
|
||||
Ok(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// `push_todo` to whichever agent submitted approval `approval_id` —
|
||||
/// same resolution `notify_submitter` uses.
|
||||
pub async fn push_todo_submitter(
|
||||
&self,
|
||||
approval_id: i64,
|
||||
subsystem: &str,
|
||||
key: Option<String>,
|
||||
summary: String,
|
||||
source: Option<String>,
|
||||
) {
|
||||
let target = self.submitter_or_manager(approval_id);
|
||||
self.push_todo(&target, subsystem, key, summary, source)
|
||||
.await;
|
||||
}
|
||||
|
||||
/// Push a `HelperEvent` into an arbitrary agent's inbox. Encoded
|
||||
|
|
|
|||
Loading…
Reference in a new issue