From dd1ee7a2e761852c39a82eb8301ab4599ff642cd Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Sun, 12 Feb 2023 14:34:28 +0100 Subject: feat(tvix/store): add GRPCPathInfoServiceWrapper This exposes a proto::pathinfo_service_server::PathInfoService for a directoryservice::PathInfoService and a way to calculate NARs. Change-Id: I30cd058562f83d063c78b84976ec97190de49400 Reviewed-on: https://cl.tvl.fyi/c/depot/+/8097 Tested-by: BuildkiteCI Reviewed-by: raitobezarius --- .../src/proto/grpc_pathinfoservice_wrapper.rs | 85 ++++++++++++++++++++++ tvix/store/src/proto/mod.rs | 2 + 2 files changed, 87 insertions(+) create mode 100644 tvix/store/src/proto/grpc_pathinfoservice_wrapper.rs (limited to 'tvix/store') diff --git a/tvix/store/src/proto/grpc_pathinfoservice_wrapper.rs b/tvix/store/src/proto/grpc_pathinfoservice_wrapper.rs new file mode 100644 index 000000000000..c7df6b643a12 --- /dev/null +++ b/tvix/store/src/proto/grpc_pathinfoservice_wrapper.rs @@ -0,0 +1,85 @@ +use crate::nar::RenderError; +use crate::proto; +use crate::{nar::NARCalculationService, pathinfoservice::PathInfoService}; +use tonic::{async_trait, Request, Response, Result, Status}; +use tracing::{instrument, warn}; + +pub struct GRPCPathInfoServiceWrapper { + path_info_service: PS, + nar_calculation_service: NS, +} + +impl GRPCPathInfoServiceWrapper { + pub fn new(path_info_service: PS, nar_calculation_service: NS) -> Self { + Self { + path_info_service, + nar_calculation_service, + } + } +} + +#[async_trait] +impl< + PS: PathInfoService + Send + Sync + 'static, + NS: NARCalculationService + Send + Sync + 'static, + > proto::path_info_service_server::PathInfoService for GRPCPathInfoServiceWrapper +{ + #[instrument(skip(self))] + async fn get( + &self, + request: Request, + ) -> Result> { + match request.into_inner().by_what { + None => Err(Status::unimplemented("by_what needs to be specified")), + Some(by_what) => match self.path_info_service.get(by_what) { + Ok(None) => Err(Status::not_found("PathInfo not found")), + Ok(Some(path_info)) => Ok(Response::new(path_info)), + Err(e) => { + warn!("failed to retrieve PathInfo: {}", e); + Err(e.into()) + } + }, + } + } + + #[instrument(skip(self))] + async fn put(&self, request: Request) -> Result> { + let path_info = request.into_inner(); + + // Store the PathInfo in the client. Clients MUST validate the data + // they receive, so we don't validate additionally here. + match self.path_info_service.put(path_info) { + Ok(path_info_new) => Ok(Response::new(path_info_new)), + Err(e) => { + warn!("failed to insert PathInfo: {}", e); + Err(e.into()) + } + } + } + + #[instrument(skip(self))] + async fn calculate_nar( + &self, + request: Request, + ) -> Result> { + match request.into_inner().node { + None => Err(Status::invalid_argument("no root node sent")), + Some(root_node) => match self.nar_calculation_service.calculate_nar(root_node) { + Ok(resp) => Ok(Response::new(resp)), + Err(e) => Err(e.into()), + }, + } + } +} + +impl From for tonic::Status { + fn from(value: RenderError) -> Self { + match value { + RenderError::BlobNotFound(_, _) => Self::not_found(value.to_string()), + RenderError::DirectoryNotFound(_, _) => Self::not_found(value.to_string()), + RenderError::NARWriterError(_) => Self::internal(value.to_string()), + RenderError::StoreError(_) => Self::internal(value.to_string()), + RenderError::UnexpectedBlobMeta(_, _, _, _) => Self::internal(value.to_string()), + } + } +} diff --git a/tvix/store/src/proto/mod.rs b/tvix/store/src/proto/mod.rs index 84eeda3c66f0..ae5054df5473 100644 --- a/tvix/store/src/proto/mod.rs +++ b/tvix/store/src/proto/mod.rs @@ -9,9 +9,11 @@ use nix_compat::store_path::{ParseStorePathError, StorePath}; mod grpc_blobservice_wrapper; mod grpc_directoryservice_wrapper; +mod grpc_pathinfoservice_wrapper; pub use grpc_blobservice_wrapper::GRPCBlobServiceWrapper; pub use grpc_directoryservice_wrapper::GRPCDirectoryServiceWrapper; +pub use grpc_pathinfoservice_wrapper::GRPCPathInfoServiceWrapper; tonic::include_proto!("tvix.store.v1"); -- cgit 1.4.1