refactor(web_ui): share one broker_request helper; /send timeout now 409 not 500

This commit is contained in:
müde 2026-07-05 21:55:28 +02:00
commit 785a36b907
4 changed files with 86 additions and 83 deletions

View file

@ -267,3 +267,52 @@ fn error_response(status: StatusCode, message: &str) -> Response {
// in its alert, so a benign "busy, retry" must not read as a 500.
(status, message.to_owned()).into_response()
}
/// Why a deadline-bounded broker request via the per-agent socket didn't
/// yield a response. Kept distinct so action handlers pick the right status
/// code (see [`broker_error_response`]) while decorative fetches `.ok()` both.
enum BrokerError {
/// Outran [`SOCKET_FETCH_TIMEOUT`] — hive-c0re is busy or stalled. A
/// retryable state conflict (→ 409), not a server fault.
Timeout,
/// The socket transport itself failed (connect / encode / decode).
Transport(anyhow::Error),
}
/// Issue a broker request over the per-agent socket, bounded by
/// [`SOCKET_FETCH_TIMEOUT`] so a busy or stalled hive-c0re degrades the
/// response instead of hanging it. Callers match the returned [`Response`]
/// variant themselves; the error side distinguishes a retryable timeout from
/// a transport failure. This is the one shared broker-call scaffold — every
/// web-UI handler that talks to the broker goes through it.
async fn broker_request(
socket: &Path,
req: &hive_sh4re::Request,
) -> std::result::Result<hive_sh4re::Response, BrokerError> {
match tokio::time::timeout(
SOCKET_FETCH_TIMEOUT,
crate::client::request::<_, hive_sh4re::Response>(socket, req),
)
.await
{
Ok(Ok(resp)) => Ok(resp),
Ok(Err(e)) => Err(BrokerError::Transport(e)),
Err(_) => Err(BrokerError::Timeout),
}
}
/// Map a [`BrokerError`] to an operator-facing error response: a timeout is a
/// retryable "busy" conflict (409), a transport failure is a 500. `action`
/// prefixes the message (e.g. `"send"`, `"get_loose_ends"`).
fn broker_error_response(err: &BrokerError, action: &str) -> Response {
match err {
BrokerError::Timeout => error_response(
StatusCode::CONFLICT,
&format!("{action}: timed out — hive-c0re busy, retry"),
),
BrokerError::Transport(e) => error_response(
StatusCode::INTERNAL_SERVER_ERROR,
&format!("{action}: transport: {e:#}"),
),
}
}