Watch
0
0
Fork
You've already forked hyperhive
0

hive-c0re: bound forge API calls so a stalled forge can't wedge the swarm event loop

forgejo-api 0.11.1 takes no caller-built client, so a request to a forge that
accepts the connection and never answers waited forever. Every forge::api()
call site now goes through forge::bounded, a 10s timeout that errors naming the
operation. The PR-comment calls run inline in swarm_status::drain_swarm_events,
the one task serving both swarm subscriptions, so a stalled forge stopped both.

Refs #5066
This commit is contained in:
atlas 2026-10-09 15:30:57 +02:00 • committed by mara
commit 2b0154be28
5 changed files with 111 additions and 41 deletions

View file

@ -16,8 +16,8 @@ use reqwest::StatusCode;
use crate::coordinator::Coordinator;
use super::{
CONFIG_ORG, api, core_auth_header, core_token, forge_git_url, forge_http_base, is_present,
reader_token,
CONFIG_ORG, api, bounded, core_auth_header, core_token, forge_git_url, forge_http_base,
is_present, reader_token,
};
/// Creation options for an empty repo defaulting to `main`.
@ -79,10 +79,13 @@ fn created_or_exists(res: Result<Repository, ForgejoError>, label: &str) -> Resu
/// to the user we want the repo owned by (we use `core`'s token for
/// `core/meta`). Idempotent.
pub async fn ensure_repo(name: &str, token: &str) -> Result<()> {
let res = api(token)?
.create_current_user_repo(repo_option(name, true))
.await;
created_or_exists(res, &format!("core/{name}"))
let label = format!("core/{name}");
let res = bounded(
&format!("create repo {label}"),
api(token)?.create_current_user_repo(repo_option(name, true)),
)
.await?;
created_or_exists(res, &label)
}
/// Dashboard-warning guard for the meta non-fast-forward condition.
@ -397,21 +400,24 @@ async fn add_collaborator(
permission: AddCollaboratorOptionPermission,
token: &str,
) -> Result<()> {
let res = api(token)?
.repo_add_collaborator(
let op = format!("add collaborator {user} to {owner}/{repo}");
let res = bounded(
&op,
api(token)?.repo_add_collaborator(
owner,
repo,
user,
AddCollaboratorOption {
permission: Some(permission),
},
)
.await;
),
)
.await?;
match res {
Ok(()) => {}
Err(ForgejoError::UnexpectedStatusCode(s)) if s == StatusCode::CREATED => {}
Err(e) => {
return Err(e).with_context(|| format!("add collaborator {user} to {owner}/{repo}"));
return Err(e).context(op);
}
}
tracing::debug!(%owner, %repo, %user, ?permission, "forge: collaborator set");