Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
3.4 kB · 95 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596//! mirror crawl triggers: after a generation or provisioning, poke knotmirror/gitmirror//! instead of waiting for the network to notice.//!//! the static knot serves no event stream, so mirrors can't discover updates by subscription.//! instead, knot-static POSTs the configured admin endpoints. knotmirror's admin server is the//! known-good target://!//! POST <admin>/api/triggerRepoResync form: repo=<repo DID>//!//! gitmirror (knotmirror v2) speaks XRPC with an in-flux internal interface;//! add its NSID when it settles.
use anyhow::Context as _;use bytes::Bytes;use knot_runtime::{HttpLimits, HttpRequest, HttpTransport, ReqwestHttp};use knot_types::RepoDid;use tracing::warn;
#[derive(Debug, Clone)]pub struct MirrorTrigger { pub url: String, pub auth_token: Option<String>,}
pub fn triggers_from_config(config: &crate::config::ValidatedConfig) -> Vec<MirrorTrigger> { let Some(mirror) = &config.mirror else { return Vec::new(); }; let auth_token = mirror .auth_token_env .as_ref() .and_then(|env| std::env::var(env).ok()) .filter(|token| !token.is_empty()); mirror .resync_urls .iter() .map(|url| MirrorTrigger { url: url.clone(), auth_token: auth_token.clone(), }) .collect()}
/// fire-and-log: trigger all mirrors across all changed repos concurrently.pub async fn trigger_all(triggers: &[MirrorTrigger], repos: &[RepoDid]) { if triggers.is_empty() || repos.is_empty() { return; } let futures = repos.iter().flat_map(|repo_did| { triggers.iter().map(move |trigger| async move { match post_resync(trigger, repo_did).await { Ok(status) if status.is_success() => {} Ok(status) => warn!( "mirror resync trigger returned {status} for {repo_did} at {}", trigger.url ), Err(error) => warn!( "mirror resync trigger failed for {repo_did} at {}: {error:#}", trigger.url ), } }) }); futures::future::join_all(futures).await;}
/// fire-and-log: mirror availability must never fail a generation.pub async fn trigger_repo_resync(triggers: &[MirrorTrigger], repo_did: &RepoDid) { trigger_all(triggers, std::slice::from_ref(repo_did)).await;}
async fn post_resync( trigger: &MirrorTrigger, repo_did: &RepoDid,) -> anyhow::Result<http::StatusCode> { let transport = ReqwestHttp::new(HttpLimits::default()).context("init http transport")?; let url = url::Url::parse(&trigger.url).context("parse mirror resync url")?; let mut request = HttpRequest::post(url, Bytes::from(format!("repo={repo_did}"))); request.headers.insert( http::header::CONTENT_TYPE, http::header::HeaderValue::from_static("application/x-www-form-urlencoded"), ); if let Some(token) = &trigger.auth_token { request.headers.insert( http::header::AUTHORIZATION, http::header::HeaderValue::from_str(&format!("Bearer {token}")) .context("mirror auth token is not a valid header value")?, ); } transport .execute(request) .await .map(|response| response.status) .context("mirror resync request")}