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

@ -10,7 +10,7 @@ use forgejo_api::structs::UpdateUserAvatarOption;
use forgejo_api::{ApiErrorKind, ForgejoError};
use reqwest::StatusCode;
use super::{api, forge_admin};
use super::{api, bounded, forge_admin};
const TOKEN_NAME_PREFIX: &str = "hyperhive";
// Where the host-side `core` admin token lives. Used by hive-c0re itself
@ -172,12 +172,14 @@ pub(super) async fn ensure_core_avatar(token: &str) -> Result<()> {
// `token` IS the core user's own token though, so updating "the
// current user's avatar" (`POST /user/avatar`) is behaviorally
// identical.
api(token)?
.user_update_avatar(UpdateUserAvatarOption {
bounded(
"set core avatar",
api(token)?.user_update_avatar(UpdateUserAvatarOption {
image: Some(base64::engine::general_purpose::STANDARD.encode(&png_bytes)),
})
.await
.context("set core avatar")?;
}),
)
.await?
.context("set core avatar")?;
if let Some(parent) = marker.parent() {
std::fs::create_dir_all(parent).ok();
}
@ -232,7 +234,11 @@ async fn check_core_token(token: &str) -> CoreTokenCheck {
let Ok(client) = api(token) else {
return CoreTokenCheck::Indeterminate;
};
match client.user_get_current().await {
let Ok(probe) = bounded("probe core token", client.user_get_current()).await else {
tracing::debug!("forge: core-token probe timed out; treating as indeterminate");
return CoreTokenCheck::Indeterminate;
};
match probe {
Ok(_) => CoreTokenCheck::Valid,
Err(e) => {
let outcome = classify_core_token_error(&e);