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/store/src/pathinfoservice/redb.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/store/src/pathinfoservice/redb.rs')
-rw-r--r-- | tvix/store/src/pathinfoservice/redb.rs | 45 |
1 files changed, 24 insertions, 21 deletions
diff --git a/tvix/store/src/pathinfoservice/redb.rs b/tvix/store/src/pathinfoservice/redb.rs index bd0e0fc2b686..6e794e1981f0 100644 --- a/tvix/store/src/pathinfoservice/redb.rs +++ b/tvix/store/src/pathinfoservice/redb.rs @@ -1,5 +1,5 @@ -use super::PathInfoService; -use crate::proto::PathInfo; +use super::{PathInfo, PathInfoService}; +use crate::proto; use data_encoding::BASE64; use futures::{stream::BoxStream, StreamExt}; use prost::Message; @@ -78,10 +78,13 @@ impl PathInfoService for RedbPathInfoService { let table = txn.open_table(PATHINFO_TABLE)?; match table.get(digest)? { Some(pathinfo_bytes) => Ok(Some( - PathInfo::decode(pathinfo_bytes.value().as_slice()).map_err(|e| { - warn!(err=%e, "failed to decode stored PathInfo"); - Error::StorageError("failed to decode stored PathInfo".to_string()) - })?, + proto::PathInfo::decode(pathinfo_bytes.value().as_slice()) + .map_err(|e| { + warn!(err=%e, "failed to decode stored PathInfo"); + Error::StorageError("failed to decode stored PathInfo".to_string()) + })? + .try_into() + .map_err(|e| Error::StorageError(format!("Invalid path info: {e}")))?, )), None => Ok(None), } @@ -92,25 +95,19 @@ impl PathInfoService for RedbPathInfoService { #[instrument(level = "trace", skip_all, fields(path_info.root_node = ?path_info.node))] async fn put(&self, path_info: PathInfo) -> Result<PathInfo, Error> { - // Call validate on the received PathInfo message. - let store_path = path_info - .validate() - .map_err(|e| { - warn!(err=%e, "failed to validate PathInfo"); - Error::StorageError("failed to validate PathInfo".to_string()) - })? - .to_owned(); - - let path_info_encoded = path_info.encode_to_vec(); let db = self.db.clone(); tokio::task::spawn_blocking({ + let path_info = path_info.clone(); move || -> Result<(), Error> { let txn = db.begin_write()?; { let mut table = txn.open_table(PATHINFO_TABLE)?; table - .insert(store_path.digest(), path_info_encoded) + .insert( + *path_info.store_path.digest(), + proto::PathInfo::from(path_info).encode_to_vec(), + ) .map_err(|e| { warn!(err=%e, "failed to insert PathInfo"); Error::StorageError("failed to insert PathInfo".to_string()) @@ -137,12 +134,18 @@ impl PathInfoService for RedbPathInfoService { for elem in table.iter()? { let elem = elem?; tokio::runtime::Handle::current() - .block_on(tx.send(Ok( - PathInfo::decode(elem.1.value().as_slice()).map_err(|e| { + .block_on(tx.send(Ok({ + let path_info_proto = proto::PathInfo::decode( + elem.1.value().as_slice(), + ) + .map_err(|e| { warn!(err=%e, "invalid PathInfo"); Error::StorageError("invalid PathInfo".to_string()) - })?, - ))) + })?; + PathInfo::try_from(path_info_proto).map_err(|e| { + Error::StorageError(format!("Invalid path info: {e}")) + })? + }))) .map_err(|e| Error::StorageError(e.to_string()))?; } |