about summary refs log tree commit diff
path: root/tvix/store/src/nar/grpc_nar_calculation_service.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/store/src/nar/grpc_nar_calculation_service.rs')
-rw-r--r--tvix/store/src/nar/grpc_nar_calculation_service.rs69
1 files changed, 69 insertions, 0 deletions
diff --git a/tvix/store/src/nar/grpc_nar_calculation_service.rs b/tvix/store/src/nar/grpc_nar_calculation_service.rs
new file mode 100644
index 000000000000..429593743914
--- /dev/null
+++ b/tvix/store/src/nar/grpc_nar_calculation_service.rs
@@ -0,0 +1,69 @@
+use super::NARCalculationService;
+use crate::proto;
+use tonic::transport::Channel;
+use tonic::Status;
+
+/// A NAR calculation service which asks a remote tvix-store for NAR calculation
+/// (via the gRPC PathInfoService).
+#[derive(Clone)]
+pub struct GRPCNARCalculationService {
+    /// A handle into the active tokio runtime. Necessary to spawn tasks.
+    tokio_handle: tokio::runtime::Handle,
+
+    /// The internal reference to a gRPC client.
+    /// Cloning it is cheap, and it internally handles concurrent requests.
+    grpc_client: proto::path_info_service_client::PathInfoServiceClient<Channel>,
+}
+
+impl GRPCNARCalculationService {
+    /// construct a new [GRPCNARCalculationService], by passing a handle to the
+    /// tokio runtime, and a gRPC client.
+    pub fn new(
+        tokio_handle: tokio::runtime::Handle,
+        grpc_client: proto::path_info_service_client::PathInfoServiceClient<Channel>,
+    ) -> Self {
+        Self {
+            tokio_handle,
+            grpc_client,
+        }
+    }
+
+    /// construct a [GRPCNARCalculationService], from a [proto::path_info_service_client::PathInfoServiceClient<Channel>].
+    /// panics if called outside the context of a tokio runtime.
+    pub fn from_client(
+        grpc_client: proto::path_info_service_client::PathInfoServiceClient<Channel>,
+    ) -> Self {
+        Self {
+            tokio_handle: tokio::runtime::Handle::current(),
+            grpc_client,
+        }
+    }
+}
+
+impl NARCalculationService for GRPCNARCalculationService {
+    fn calculate_nar(
+        &self,
+        root_node: &proto::node::Node,
+    ) -> Result<(u64, [u8; 32]), super::RenderError> {
+        // Get a new handle to the gRPC client, and copy the root node.
+        let mut grpc_client = self.grpc_client.clone();
+        let root_node = root_node.clone();
+
+        let task: tokio::task::JoinHandle<Result<_, Status>> =
+            self.tokio_handle.spawn(async move {
+                Ok(grpc_client
+                    .calculate_nar(proto::Node {
+                        node: Some(root_node),
+                    })
+                    .await?
+                    .into_inner())
+            });
+
+        match self.tokio_handle.block_on(task).unwrap() {
+            Ok(resp) => Ok((resp.nar_size, resp.nar_sha256.to_vec().try_into().unwrap())),
+            Err(e) => Err(super::RenderError::StoreError(crate::Error::StorageError(
+                e.to_string(),
+            ))),
+        }
+    }
+}