helia_interface/
blocks.rs

1//! Block storage and retrieval interfaces
2
3use async_trait::async_trait;
4use bytes::Bytes;
5use cid::Cid;
6use libp2p::{Multiaddr, PeerId};
7use serde::{Deserialize, Serialize};
8
9use crate::{AbortOptions, AwaitIterable, HeliaError, ProgressOptions};
10
11/// A key-value pair for block operations
12#[derive(Debug, Clone)]
13pub struct Pair {
14    pub cid: Cid,
15    pub block: Bytes,
16}
17
18/// Input pair that may not have been stored yet
19#[derive(Debug, Clone)]
20pub struct InputPair {
21    pub cid: Option<Cid>,
22    pub block: Bytes,
23}
24
25/// Options for specifying content providers
26#[derive(Debug, Clone, Default)]
27pub struct ProviderOptions {
28    /// An optional list of peers known to host at least the root block of the DAG
29    /// that will be fetched.
30    ///
31    /// If this list is omitted, or if the peers cannot supply the root or any
32    /// child blocks, a `findProviders` routing query will be run to find peers
33    /// that can supply the blocks.
34    pub providers: Vec<ProviderInfo>,
35}
36
37/// Information about a content provider
38#[derive(Debug, Clone)]
39pub enum ProviderInfo {
40    /// Provider identified by peer ID
41    PeerId(PeerId),
42    /// Provider identified by address
43    Multiaddr(Multiaddr),
44    /// Provider with multiple addresses
45    MultipleAddrs(Vec<Multiaddr>),
46}
47
48/// Progress events for checking if a block exists
49#[derive(Debug, Clone, Serialize, Deserialize)]
50#[serde(tag = "type")]
51pub enum HasBlockProgressEvents {
52    #[serde(rename = "blocks:put:duplicate")]
53    Duplicate { cid: Cid },
54    #[serde(rename = "blocks:put:providers:notify")]
55    ProvidersNotify { cid: Cid },
56    #[serde(rename = "blocks:put:blockstore:put")]
57    BlockstorePut { cid: Cid },
58}
59
60/// Progress events for putting a single block
61#[derive(Debug, Clone, Serialize, Deserialize)]
62#[serde(tag = "type")]
63pub enum PutBlockProgressEvents {
64    #[serde(rename = "blocks:put:duplicate")]
65    Duplicate { cid: Cid },
66    #[serde(rename = "blocks:put:providers:notify")]
67    ProvidersNotify { cid: Cid },
68    #[serde(rename = "blocks:put:blockstore:put")]
69    BlockstorePut { cid: Cid },
70}
71
72/// Progress events for putting multiple blocks
73#[derive(Debug, Clone, Serialize, Deserialize)]
74#[serde(tag = "type")]
75pub enum PutManyBlocksProgressEvents {
76    #[serde(rename = "blocks:put-many:duplicate")]
77    Duplicate { cid: Cid },
78    #[serde(rename = "blocks:put-many:providers:notify")]
79    ProvidersNotify { cid: Cid },
80    #[serde(rename = "blocks:put-many:blockstore:put-many")]
81    BlockstorePutMany,
82}
83
84/// Progress events for getting a block
85#[derive(Debug, Clone, Serialize, Deserialize)]
86#[serde(tag = "type")]
87pub enum GetBlockProgressEvents {
88    #[serde(rename = "blocks:get:providers:want")]
89    ProvidersWant { cid: Cid },
90    #[serde(rename = "blocks:get:blockstore:get")]
91    BlockstoreGet { cid: Cid },
92    #[serde(rename = "blocks:get:blockstore:put")]
93    BlockstorePut { cid: Cid },
94}
95
96/// Progress events for getting multiple blocks
97#[derive(Debug, Clone, Serialize, Deserialize)]
98#[serde(tag = "type")]
99pub enum GetManyBlocksProgressEvents {
100    #[serde(rename = "blocks:get-many:providers:want")]
101    ProvidersWant { cid: Cid },
102    #[serde(rename = "blocks:get-many:blockstore:get")]
103    BlockstoreGet { cid: Cid },
104    #[serde(rename = "blocks:get-many:blockstore:put")]
105    BlockstorePut { cid: Cid },
106}
107
108/// Progress events for getting all blocks
109#[derive(Debug, Clone, Serialize, Deserialize)]
110#[serde(tag = "type")]
111pub enum GetAllBlocksProgressEvents {
112    #[serde(rename = "blocks:get-all:providers:want")]
113    ProvidersWant { cid: Cid },
114    #[serde(rename = "blocks:get-all:blockstore:get")]
115    BlockstoreGet { cid: Cid },
116    #[serde(rename = "blocks:get-all:blockstore:put")]
117    BlockstorePut { cid: Cid },
118}
119
120/// Progress events for deleting blocks
121#[derive(Debug, Clone, Serialize, Deserialize)]
122#[serde(tag = "type")]
123pub enum DeleteManyBlocksProgressEvents {
124    #[serde(rename = "blocks:delete-many:blockstore:delete")]
125    BlockstoreDelete { cid: Cid },
126}
127
128/// Options for getting a block
129#[derive(Debug, Default)]
130pub struct GetBlockOptions {
131    pub abort: AbortOptions,
132    pub progress: ProgressOptions<GetBlockProgressEvents>,
133    pub provider: ProviderOptions,
134}
135
136impl Clone for GetBlockOptions {
137    fn clone(&self) -> Self {
138        Self {
139            abort: self.abort.clone(),
140            progress: self.progress.clone(),
141            provider: self.provider.clone(),
142        }
143    }
144}
145
146/// Options for getting multiple blocks
147#[derive(Debug, Default)]
148pub struct GetManyOptions {
149    pub abort: AbortOptions,
150    pub progress: ProgressOptions<GetManyBlocksProgressEvents>,
151    pub provider: ProviderOptions,
152}
153
154impl Clone for GetManyOptions {
155    fn clone(&self) -> Self {
156        Self {
157            abort: self.abort.clone(),
158            progress: self.progress.clone(),
159            provider: self.provider.clone(),
160        }
161    }
162}
163
164/// Options for getting all blocks
165#[derive(Debug, Default)]
166pub struct GetAllOptions {
167    pub abort: AbortOptions,
168    pub progress: ProgressOptions<GetAllBlocksProgressEvents>,
169    pub provider: ProviderOptions,
170}
171
172impl Clone for GetAllOptions {
173    fn clone(&self) -> Self {
174        Self {
175            abort: self.abort.clone(),
176            progress: self.progress.clone(),
177            provider: self.provider.clone(),
178        }
179    }
180}
181
182/// Options for putting a block
183#[derive(Debug, Default)]
184pub struct PutBlockOptions {
185    pub abort: AbortOptions,
186    pub progress: ProgressOptions<PutBlockProgressEvents>,
187}
188
189impl Clone for PutBlockOptions {
190    fn clone(&self) -> Self {
191        Self {
192            abort: self.abort.clone(),
193            progress: self.progress.clone(),
194        }
195    }
196}
197
198/// Options for putting multiple blocks
199#[derive(Debug, Default)]
200pub struct PutManyOptions {
201    pub abort: AbortOptions,
202    pub progress: ProgressOptions<PutManyBlocksProgressEvents>,
203}
204
205impl Clone for PutManyOptions {
206    fn clone(&self) -> Self {
207        Self {
208            abort: self.abort.clone(),
209            progress: self.progress.clone(),
210        }
211    }
212}
213
214/// Options for checking if blocks exist
215#[derive(Debug, Default)]
216pub struct HasOptions {
217    pub abort: AbortOptions,
218    pub progress: ProgressOptions<HasBlockProgressEvents>,
219}
220
221impl Clone for HasOptions {
222    fn clone(&self) -> Self {
223        Self {
224            abort: self.abort.clone(),
225            progress: self.progress.clone(),
226        }
227    }
228}
229
230/// Options for deleting blocks
231#[derive(Debug, Default)]
232pub struct DeleteManyOptions {
233    pub abort: AbortOptions,
234    pub progress: ProgressOptions<DeleteManyBlocksProgressEvents>,
235}
236
237impl Clone for DeleteManyOptions {
238    fn clone(&self) -> Self {
239        Self {
240            abort: self.abort.clone(),
241            progress: self.progress.clone(),
242        }
243    }
244}
245
246/// Block storage interface
247#[async_trait]
248pub trait Blocks: Send + Sync {
249    /// Retrieve a block from the blockstore
250    async fn get(&self, cid: &Cid, options: Option<GetBlockOptions>) -> Result<Bytes, HeliaError>;
251
252    /// Retrieve multiple blocks from the blockstore
253    async fn get_many_cids(
254        &self,
255        cids: Vec<Cid>,
256        options: Option<GetManyOptions>,
257    ) -> Result<AwaitIterable<Result<Pair, HeliaError>>, HeliaError>;
258
259    /// Retrieve all blocks from the blockstore
260    async fn get_all(
261        &self,
262        options: Option<GetAllOptions>,
263    ) -> Result<AwaitIterable<Pair>, HeliaError>;
264
265    /// Store a block in the blockstore
266    async fn put(
267        &self,
268        cid: &Cid,
269        block: Bytes,
270        options: Option<PutBlockOptions>,
271    ) -> Result<Cid, HeliaError>;
272
273    /// Store multiple blocks in the blockstore
274    async fn put_many_blocks(
275        &self,
276        blocks: Vec<InputPair>,
277        options: Option<PutManyOptions>,
278    ) -> Result<AwaitIterable<Cid>, HeliaError>;
279
280    /// Check if blocks exist in the blockstore
281    async fn has(&self, cid: &Cid, options: Option<HasOptions>) -> Result<bool, HeliaError>;
282
283    /// Check if multiple blocks exist in the blockstore
284    async fn has_many_cids(
285        &self,
286        cids: Vec<Cid>,
287        options: Option<HasOptions>,
288    ) -> Result<AwaitIterable<bool>, HeliaError>;
289
290    /// Delete multiple blocks from the blockstore
291    async fn delete_many_cids(
292        &self,
293        cids: Vec<Cid>,
294        options: Option<DeleteManyOptions>,
295    ) -> Result<AwaitIterable<Cid>, HeliaError>;
296}