use crate::types::RepoStatus;
use axum::{http::header, response::IntoResponse};
use jacquard_common::types::{string::Did, tid::Tid};
use super::*;
#[derive(Deserialize)]
pub struct GetRepo {
pub did: Did,
pub since: Option<Tid>,
}
pub async fn handle(
State(hydrant): State<Hydrant>,
ExtractXrpc(req): ExtractXrpc<GetRepo>,
) -> XrpcResult<impl IntoResponse> {
if req.since.is_some() {
return Err(bad_request("hydrant does not support since paramater"));
}
let repo = hydrant.repos.get(&req.did);
let Some(state) = repo.state().await.map_err(internal_error)? else {
return Err(xrpc_error(StatusCode::NOT_FOUND, "RepoNotFound", None));
};
let xrpc_err = match &state.status {
RepoStatus::Takendown => Some(("RepoTakendown", None)),
RepoStatus::Suspended => Some(("RepoSuspended", None)),
RepoStatus::Deactivated => Some(("RepoDeactivated", None)),
RepoStatus::Deleted => Some(("RepoNotFound", Some("deleted".into()))),
_ => None,
};
if let Some((code, msg)) = xrpc_err {
return Err(xrpc_error(StatusCode::FORBIDDEN, code, msg));
}
let _permit = hydrant
.state
.get_repo_semaphore
.try_acquire()
.map_err(|_| rate_limited("too many concurrent getRepo requests"))?;
let Some(car_bytes) = repo.generate_car().await.map_err(internal_error)? else {
return Err(xrpc_error(
StatusCode::NOT_FOUND,
"RepoNotFound",
Some("repo still backfilling".into()),
));
};
Ok((
[(header::CONTENT_TYPE, "application/vnd.ipld.car")],
axum::body::Body::from_stream(car_bytes),
))
}