Skip to main content

xet_client/cas_client/
interface.rs

1use bytes::Bytes;
2use xet_core_structures::merklehash::MerkleHash;
3use xet_core_structures::metadata_shard::file_structs::MDBFileInfo;
4use xet_core_structures::xorb_object::SerializedXorbObject;
5
6use super::adaptive_concurrency::ConnectionPermit;
7use super::progress_tracked_streams::ProgressCallback;
8use crate::cas_types::{
9    BatchQueryReconstructionResponse, FileChunkHashesResponse, FileRange, HttpRange, QueryReconstructionResponseV2,
10};
11use crate::error::Result;
12
13#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
14#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
15pub trait URLProvider: Send + Sync {
16    /// Retrieves the URL and the byte ranges to fetch.
17    /// For single-range (V1) blocks, the Vec has one entry.
18    /// For multi-range (V2) blocks, all ranges are included.
19    async fn retrieve_url(&self) -> Result<(String, Vec<HttpRange>)>;
20
21    /// Asks for a refresh of the URL; triggered on 403 errors.
22    async fn refresh_url(&self) -> Result<()>;
23}
24
25/// A Client to the Shard service. The shard service
26/// provides for
27/// 1. upload shard to the shard service
28/// 2. querying of file->reconstruction information
29/// 3. querying of chunk->shard information
30#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
31#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
32pub trait Client: Send + Sync {
33    async fn get_file_reconstruction_info(
34        &self,
35        file_hash: &MerkleHash,
36    ) -> Result<Option<(MDBFileInfo, Option<MerkleHash>)>>;
37
38    /// Returns reconstruction info always in V2 format.
39    /// Implementations may try V2 first and fall back to V1 + convert.
40    async fn get_reconstruction(
41        &self,
42        file_id: &MerkleHash,
43        bytes_range: Option<FileRange>,
44    ) -> Result<Option<QueryReconstructionResponseV2>>;
45
46    async fn batch_get_reconstruction(&self, file_ids: &[MerkleHash]) -> Result<BatchQueryReconstructionResponse>;
47
48    async fn acquire_download_permit(&self) -> Result<ConnectionPermit>;
49
50    /// Optional progress callback receives (delta, completed, total) in transfer bytes.
51    /// When [uncompressed_size_if_known] is [Some], the returned Bytes must have len() equal to that value.
52    async fn get_file_term_data(
53        &self,
54        url_info: Box<dyn URLProvider>,
55        download_permit: ConnectionPermit,
56        progress_callback: Option<ProgressCallback>,
57        uncompressed_size_if_known: Option<usize>,
58    ) -> Result<(Bytes, Vec<u32>)>;
59
60    async fn query_for_global_dedup_shard(&self, prefix: &str, chunk_hash: &MerkleHash) -> Result<Option<Bytes>>;
61
62    /// Acquire an upload permit.
63    async fn acquire_upload_permit(&self) -> Result<ConnectionPermit>;
64
65    /// Upload a new shard.
66    async fn upload_shard(&self, shard_data: bytes::Bytes, upload_permit: ConnectionPermit) -> Result<bool>;
67
68    /// Upload a new xorb. Optional progress callback receives (delta, completed, total) in transfer bytes.
69    async fn upload_xorb(
70        &self,
71        prefix: &str,
72        serialized_xorb_object: SerializedXorbObject,
73        progress_callback: Option<ProgressCallback>,
74        upload_permit: ConnectionPermit,
75    ) -> Result<u64>;
76
77    /// Compute chunk-aligned dirty windows + opaque gap [`MerkleHashSubtree`] summaries for the
78    /// given file, narrowed to `dirty_ranges`.
79    ///
80    /// `dirty_ranges` must be sorted and non-overlapping. Per-chunk hashes are never returned;
81    /// the response carries only `windows.len()` dirty windows and `windows.len() + 1` gap
82    /// subtrees, which the client merges with locally-recomputed window subtrees to obtain the
83    /// new file hash.
84    async fn get_file_chunk_hashes(
85        &self,
86        file_id: &MerkleHash,
87        dirty_ranges: Vec<FileRange>,
88    ) -> Result<FileChunkHashesResponse>;
89}