helia_interface/
lib.rs

1//! # Helia Interface
2//!
3//! The API defined by a Helia node
4//!
5//! This crate provides the core interfaces and traits that define the Helia IPFS implementation.
6//!
7//! ## Example
8//!
9//! ```rust
10//! use helia_interface::Helia;
11//!
12//! async fn do_something<H: Helia>(helia: H) {
13//!     // use helia node functions here
14//! }
15//! ```
16
17pub mod blocks;
18pub mod errors;
19pub mod pins;
20pub mod routing;
21
22use std::collections::HashMap;
23use std::future::Future;
24use std::pin::Pin;
25use std::sync::Arc;
26
27use async_trait::async_trait;
28use bytes::Bytes;
29use cid::Cid;
30use futures::Stream;
31use libp2p::Swarm;
32use serde::{Deserialize, Serialize};
33use tokio::sync::Mutex;
34use trust_dns_resolver::TokioAsyncResolver;
35
36pub use blocks::*;
37pub use errors::*;
38pub use pins::*;
39pub use routing::*;
40
41/// Type alias for async iterables/streams
42pub type AwaitIterable<T> = Pin<Box<dyn Stream<Item = T> + Send>>;
43
44/// Type alias for awaitable results
45pub type Await<T> = Pin<Box<dyn Future<Output = T> + Send>>;
46
47/// Options that include an abort signal for canceling operations
48#[derive(Debug, Default)]
49pub struct AbortOptions {
50    // For now, we'll use a simpler approach without tokio channels
51    // pub signal: Option<mpsc::Receiver<()>>,
52}
53
54impl Clone for AbortOptions {
55    fn clone(&self) -> Self {
56        // AbortOptions can't be cloned due to the receiver, so we create a new default one
57        Self::default()
58    }
59}
60
61/// Progress event for tracking operation status
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct ProgressEvent<T> {
64    pub event_type: String,
65    pub detail: T,
66}
67
68/// Options for operations that support progress tracking
69pub struct ProgressOptions<T> {
70    /// Optional progress event handler
71    pub on_progress: Option<Box<dyn Fn(ProgressEvent<T>) + Send + Sync>>,
72}
73
74impl<T> std::fmt::Debug for ProgressOptions<T> {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        f.debug_struct("ProgressOptions")
77            .field(
78                "on_progress",
79                &self.on_progress.as_ref().map(|_| "Some(closure)"),
80            )
81            .finish()
82    }
83}
84
85impl<T> Default for ProgressOptions<T> {
86    fn default() -> Self {
87        Self { on_progress: None }
88    }
89}
90
91impl<T> Clone for ProgressOptions<T> {
92    fn clone(&self) -> Self {
93        // Progress handlers can't be cloned, so we create a new default one
94        Self::default()
95    }
96}
97
98/// Codec loader for loading IPLD codecs
99#[async_trait]
100pub trait CodecLoader: Send + Sync {
101    /// Load a codec by its code
102    async fn load_codec(&self, code: u64) -> Result<Box<dyn Codec>, HeliaError>;
103}
104
105/// Hasher loader for loading multihash hashers
106#[async_trait]
107pub trait HasherLoader: Send + Sync {
108    /// Load a hasher by its code
109    async fn load_hasher(&self, code: u64) -> Result<Box<dyn Hasher>, HeliaError>;
110}
111
112/// IPLD codec trait
113#[async_trait]
114pub trait Codec: Send + Sync {
115    /// Encode data using this codec
116    async fn encode(&self, data: &[u8]) -> Result<Bytes, HeliaError>;
117
118    /// Decode data using this codec
119    async fn decode(&self, data: &[u8]) -> Result<Bytes, HeliaError>;
120
121    /// Get the codec code
122    fn code(&self) -> u64;
123}
124
125/// Multihash hasher trait
126#[async_trait]
127pub trait Hasher: Send + Sync {
128    /// Hash data using this hasher
129    async fn hash(&self, data: &[u8]) -> Result<multihash::Multihash<64>, HeliaError>;
130
131    /// Get the hasher code
132    fn code(&self) -> u64;
133}
134
135/// Events emitted by a Helia node
136#[derive(Debug, Clone)]
137pub enum HeliaEvent {
138    /// Node has started
139    Start,
140    /// Node has stopped
141    Stop,
142}
143
144/// Garbage collection options
145#[derive(Debug)]
146pub struct GcOptions {
147    /// Abort options
148    pub abort: AbortOptions,
149    /// Progress options for GC events
150    pub progress: ProgressOptions<GcEvent>,
151}
152
153impl Default for GcOptions {
154    fn default() -> Self {
155        Self {
156            abort: AbortOptions::default(),
157            progress: ProgressOptions::default(),
158        }
159    }
160}
161
162impl Clone for GcOptions {
163    fn clone(&self) -> Self {
164        Self {
165            abort: self.abort.clone(),
166            progress: self.progress.clone(),
167        }
168    }
169}
170
171/// Events emitted during garbage collection
172#[derive(Debug, Clone, Serialize, Deserialize)]
173pub enum GcEvent {
174    /// A CID was deleted
175    Deleted(Cid),
176    /// An error occurred during GC
177    Error(String),
178}
179
180/// Component logger for structured logging
181pub trait ComponentLogger: Send + Sync {
182    /// Log a debug message
183    fn debug(&self, message: &str);
184    /// Log an info message
185    fn info(&self, message: &str);
186    /// Log a warning message
187    fn warn(&self, message: &str);
188    /// Log an error message
189    fn error(&self, message: &str);
190}
191
192/// Metrics collection interface
193#[async_trait]
194pub trait Metrics: Send + Sync {
195    /// Record a counter metric
196    async fn record_counter(&self, name: &str, value: u64, labels: HashMap<String, String>);
197
198    /// Record a gauge metric
199    async fn record_gauge(&self, name: &str, value: f64, labels: HashMap<String, String>);
200
201    /// Record a histogram metric
202    async fn record_histogram(&self, name: &str, value: f64, labels: HashMap<String, String>);
203}
204
205/// Non-generic Helia trait for backward compatibility and trait objects
206#[async_trait]
207pub trait Helia: Send + Sync {
208    /// The blockstore for storing blocks
209    fn blockstore(&self) -> &dyn Blocks;
210
211    /// The datastore for key-value storage
212    fn datastore(&self) -> &dyn Datastore;
213
214    /// Pinning operations
215    fn pins(&self) -> &dyn Pins;
216
217    /// The logger component
218    fn logger(&self) -> &dyn ComponentLogger;
219
220    /// The routing component
221    fn routing(&self) -> &dyn Routing;
222
223    /// DNS resolver
224    fn dns(&self) -> &TokioAsyncResolver;
225
226    /// Optional metrics collector
227    fn metrics(&self) -> Option<&dyn Metrics>;
228
229    /// Start the Helia node
230    async fn start(&self) -> Result<(), HeliaError>;
231
232    /// Stop the Helia node
233    async fn stop(&self) -> Result<(), HeliaError>;
234
235    /// Perform garbage collection
236    async fn gc(&self, options: Option<GcOptions>) -> Result<(), HeliaError>;
237
238    /// Load an IPLD codec
239    async fn get_codec(&self, code: u64) -> Result<Box<dyn Codec>, HeliaError>;
240
241    /// Load a hasher
242    async fn get_hasher(&self, code: u64) -> Result<Box<dyn Hasher>, HeliaError>;
243}
244
245/// Generic Helia trait with libp2p type parameter for concrete implementations
246#[async_trait]
247pub trait HeliaWithLibp2p<T>: Helia
248where
249    T: libp2p::swarm::NetworkBehaviour + Send + 'static,
250{
251    /// The libp2p swarm instance (wrapped in Arc<Mutex<>> for thread safety)
252    fn libp2p(&self) -> Arc<Mutex<Swarm<T>>>;
253}
254
255/// Key-value datastore interface
256#[async_trait]
257pub trait Datastore: Send + Sync {
258    /// Get a value by key
259    async fn get(&self, key: &[u8]) -> Result<Option<Bytes>, HeliaError>;
260
261    /// Put a key-value pair
262    async fn put(&self, key: &[u8], value: Bytes) -> Result<(), HeliaError>;
263
264    /// Delete a key
265    async fn delete(&self, key: &[u8]) -> Result<(), HeliaError>;
266
267    /// Check if a key exists
268    async fn has(&self, key: &[u8]) -> Result<bool, HeliaError>;
269
270    /// Query for keys with optional filters
271    async fn query(&self, prefix: Option<&[u8]>) -> Result<AwaitIterable<Bytes>, HeliaError>;
272}