diff options
author | Marijan Petričević <marijan.petricevic94@gmail.com> | 2024-10-10T14·11-0500 |
---|---|---|
committer | Marijan Petričević <marijan.petricevic94@gmail.com> | 2024-10-11T17·18+0000 |
commit | e8040ec61f2119ece2d396704576973f704607f3 (patch) | |
tree | 94caa469edb4b6c5534eb19a9683d786f9b7e5bf /tvix/nar-bridge/src/narinfo.rs | |
parent | b4ccaac7ad135249eb0b1866acf4c8e68fd5bdb9 (diff) |
refactor(tvix/store): use strictly typed PathInfo struct r/8787
This switches the PathInfoService trait from using the proto-derived PathInfo struct to a more restrictive struct, and updates all implementations to use it. It removes a lot of the previous conversion and checks, as invalid states became nonrepresentable, and validations are expressed on the type level. PathInfoService implementations consuming protobuf need to convert and do the verification internally, and can only return the strongly typed variant. The nix_compat::narinfo::NarInfo conversions for the proto PathInfo are removed, we only keep a version showing a NarInfo representation for the strong struct. Converting back to a PathInfo requires the root node now, but is otherwise trivial, so left to the users. Co-Authored-By: Florian Klink <flokli@flokli.de> Change-Id: I6fdfdb44063efebb44a8f0097b6b81a828717e03 Reviewed-on: https://cl.tvl.fyi/c/depot/+/12588 Reviewed-by: flokli <flokli@flokli.de> Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/nar-bridge/src/narinfo.rs')
-rw-r--r-- | tvix/nar-bridge/src/narinfo.rs | 75 |
1 files changed, 33 insertions, 42 deletions
diff --git a/tvix/nar-bridge/src/narinfo.rs b/tvix/nar-bridge/src/narinfo.rs index fc90f0b86629..76fda1d495c5 100644 --- a/tvix/nar-bridge/src/narinfo.rs +++ b/tvix/nar-bridge/src/narinfo.rs @@ -1,10 +1,14 @@ use axum::{http::StatusCode, response::IntoResponse}; use bytes::Bytes; -use nix_compat::{narinfo::NarInfo, nix_http, nixbase32}; +use nix_compat::{ + narinfo::{NarInfo, Signature}, + nix_http, nixbase32, + store_path::StorePath, +}; use prost::Message; use tracing::{instrument, warn, Span}; use tvix_castore::proto::{self as castorepb}; -use tvix_store::proto::PathInfo; +use tvix_store::pathinfoservice::PathInfo; use crate::AppState; @@ -57,35 +61,15 @@ pub async fn get( })? .ok_or(StatusCode::NOT_FOUND)?; - let store_path = path_info.validate().map_err(|e| { - warn!(err=%e, "invalid PathInfo"); - StatusCode::INTERNAL_SERVER_ERROR - })?; - - let mut narinfo = path_info.to_narinfo(store_path.as_ref()).ok_or_else(|| { - warn!(path_info=?path_info, "PathInfo contained no NAR data"); - StatusCode::INTERNAL_SERVER_ERROR - })?; - - // encode the (unnamed) root node in the NAR url itself. - // We strip the name from the proto node before sending it out. - // It's not needed to render the NAR, it'll make the URL shorter, and it - // will make caching these requests easier. - let (_, root_node) = path_info - .node - .as_ref() - .expect("invalid pathinfo") - .to_owned() - .into_name_and_node() - .expect("invalid pathinfo"); - let url = format!( "nar/tvix-castore/{}?narsize={}", - data_encoding::BASE64URL_NOPAD - .encode(&castorepb::Node::from_name_and_node("".into(), root_node).encode_to_vec()), - narinfo.nar_size, + data_encoding::BASE64URL_NOPAD.encode( + &castorepb::Node::from_name_and_node("".into(), path_info.node.clone()).encode_to_vec() + ), + path_info.nar_size, ); + let mut narinfo = path_info.to_narinfo(); narinfo.url = &url; Ok(( @@ -128,9 +112,6 @@ pub async fn put( // Extract the NARHash from the PathInfo. Span::current().record("path_info.nar_info", nixbase32::encode(&narinfo.nar_hash)); - // populate the pathinfo. - let mut pathinfo = PathInfo::from(&narinfo); - // Lookup root node with peek, as we don't want to update the LRU list. // We need to be careful to not hold the RwLock across the await point. let maybe_root_node: Option<tvix_castore::Node> = @@ -138,19 +119,29 @@ pub async fn put( match maybe_root_node { Some(root_node) => { - // Set the root node from the lookup. - // We need to rename the node to the narinfo storepath basename, as - // that's where it's stored in PathInfo. - pathinfo.node = Some(castorepb::Node::from_name_and_node( - narinfo.store_path.to_string().into(), - root_node, - )); - // Persist the PathInfo. - path_info_service.put(pathinfo).await.map_err(|e| { - warn!(err=%e, "failed to persist the PathInfo"); - StatusCode::INTERNAL_SERVER_ERROR - })?; + path_info_service + .put(PathInfo { + store_path: narinfo.store_path.to_owned(), + node: root_node, + references: narinfo.references.iter().map(StorePath::to_owned).collect(), + nar_sha256: narinfo.nar_hash, + nar_size: narinfo.nar_size, + signatures: narinfo + .signatures + .into_iter() + .map(|s| { + Signature::<String>::new(s.name().to_string(), s.bytes().to_owned()) + }) + .collect(), + deriver: narinfo.deriver.as_ref().map(StorePath::to_owned), + ca: narinfo.ca, + }) + .await + .map_err(|e| { + warn!(err=%e, "failed to persist the PathInfo"); + StatusCode::INTERNAL_SERVER_ERROR + })?; Ok("") } |