guardian_db/ipfs_core_api/backends/
mod.rs

1/// Backend intercambiável para operações IPFS
2///
3/// Este módulo define a interface comum para diferentes implementações de IPFS,
4/// permitindo suporte nativo ao Iroh e implementações híbridas.
5use crate::error::{GuardianError, Result};
6use crate::ipfs_core_api::types::*;
7use async_trait::async_trait;
8use cid::Cid;
9use libp2p::PeerId;
10use std::pin::Pin;
11use tokio::io::AsyncRead;
12
13// Módulos principais
14pub mod hybrid;
15pub mod iroh;
16pub mod iroh_pubsub;
17pub mod key_synchronizer;
18pub mod networking_metrics;
19
20// Módulos de otimização
21pub mod batch_processor;
22pub mod connection_pool;
23pub mod optimized_cache;
24
25pub use hybrid::HybridBackend;
26pub use iroh::IrohBackend;
27pub use iroh_pubsub::IrohPubSub;
28
29/// Trait principal para backends IPFS intercambiáveis
30///
31/// Define a interface comum que todos os backends devem implementar,
32/// garantindo compatibilidade total independentemente da implementação subjacente.
33#[async_trait]
34pub trait IpfsBackend: Send + Sync + 'static {
35    // === OPERAÇÕES DE CONTEÚDO ===
36
37    /// Adiciona dados ao IPFS e retorna o CID resultante
38    ///
39    /// # Argumentos
40    /// * `data` - Stream de dados para adicionar
41    ///
42    /// # Retorna
43    /// Resposta contendo o CID e metadados do objeto adicionado
44    async fn add(&self, data: Pin<Box<dyn AsyncRead + Send>>) -> Result<AddResponse>;
45
46    /// Recupera dados do IPFS pelo CID
47    ///
48    /// # Argumentos  
49    /// * `cid` - Content Identifier do objeto desejado
50    ///
51    /// # Retorna
52    /// Stream de dados do objeto
53    async fn cat(&self, cid: &str) -> Result<Pin<Box<dyn AsyncRead + Send>>>;
54
55    /// Fixa um objeto no storage local (evita garbage collection)
56    ///
57    /// # Argumentos
58    /// * `cid` - CID do objeto a ser fixado
59    async fn pin_add(&self, cid: &str) -> Result<()>;
60
61    /// Remove fixação de um objeto (permite garbage collection)
62    ///
63    /// # Argumentos  
64    /// * `cid` - CID do objeto a ser desfixado
65    async fn pin_rm(&self, cid: &str) -> Result<()>;
66
67    /// Lista objetos fixados
68    ///
69    /// # Retorna
70    /// Lista de CIDs fixados com seus tipos
71    async fn pin_ls(&self) -> Result<Vec<PinInfo>>;
72
73    // === OPERAÇÕES DE REDE ===
74
75    /// Conecta explicitamente a um peer
76    ///
77    /// # Argumentos
78    /// * `peer` - ID do peer para conectar
79    async fn connect(&self, peer: &PeerId) -> Result<()>;
80
81    /// Lista peers atualmente conectados
82    ///
83    /// # Retorna
84    /// Lista de informações dos peers conectados
85    async fn peers(&self) -> Result<Vec<PeerInfo>>;
86
87    /// Obtém informações do nó local
88    ///
89    /// # Retorna
90    /// Informações do nó incluindo ID, chaves públicas, endereços
91    async fn id(&self) -> Result<NodeInfo>;
92
93    /// Resolve um peer ID para seus endereços conhecidos
94    ///
95    /// # Argumentos
96    /// * `peer` - PeerId a ser resolvido
97    ///
98    /// # Retorna
99    /// Lista de endereços multiaddr do peer
100    async fn dht_find_peer(&self, peer: &PeerId) -> Result<Vec<String>>;
101
102    // === OPERAÇÕES DO REPOSITÓRIO ===
103
104    /// Obtém estatísticas do repositório local
105    ///
106    /// # Retorna
107    /// Estatísticas incluindo tamanho, número de objetos, etc.
108    async fn repo_stat(&self) -> Result<RepoStats>;
109
110    /// Obtém versão e informações do nó IPFS
111    ///
112    /// # Retorna
113    /// Informações de versão do software IPFS
114    async fn version(&self) -> Result<VersionInfo>;
115
116    // === OPERAÇÕES DE BLOCOS (LOWER-LEVEL) ===
117
118    /// Obtém um bloco raw pelo seu CID
119    ///
120    /// # Argumentos
121    /// * `cid` - CID do bloco desejado
122    ///
123    /// # Retorna
124    /// Dados raw do bloco
125    async fn block_get(&self, cid: &Cid) -> Result<Vec<u8>>;
126
127    /// Armazena dados raw como bloco
128    ///
129    /// # Argumentos
130    /// * `data` - Dados raw para armazenar
131    ///
132    /// # Retorna
133    /// CID do bloco criado
134    async fn block_put(&self, data: Vec<u8>) -> Result<Cid>;
135
136    /// Verifica se um bloco existe localmente
137    ///
138    /// # Argumentos
139    /// * `cid` - CID do bloco a verificar
140    ///
141    /// # Retorna
142    /// true se o bloco existe localmente
143    async fn block_stat(&self, cid: &Cid) -> Result<BlockStats>;
144
145    // === METADADOS DO BACKEND ===
146
147    /// Retorna o tipo/nome do backend
148    fn backend_type(&self) -> BackendType;
149
150    /// Verifica se o backend está online e operacional
151    async fn is_online(&self) -> bool;
152
153    /// Obtém métricas de performance do backend
154    async fn metrics(&self) -> Result<BackendMetrics>;
155
156    /// Executa health check completo do backend
157    async fn health_check(&self) -> Result<HealthStatus>;
158}
159
160/// Tipo do backend IPFS
161#[derive(Debug, Clone, PartialEq, Eq)]
162pub enum BackendType {
163    /// Backend usando Iroh embarcado (padrão)
164    Iroh,
165    /// Backend híbrido (Iroh + LibP2P)
166    Hybrid,
167    /// Backend de teste/mock
168    Mock,
169}
170
171impl BackendType {
172    pub fn as_str(&self) -> &'static str {
173        match self {
174            BackendType::Iroh => "iroh",
175            BackendType::Hybrid => "hybrid",
176            BackendType::Mock => "mock",
177        }
178    }
179}
180
181/// Informações de um objeto fixado
182#[derive(Debug, Clone)]
183pub struct PinInfo {
184    pub cid: String,
185    pub pin_type: PinType,
186}
187
188/// Tipo de fixação (pin)
189#[derive(Debug, Clone, PartialEq, Eq)]
190pub enum PinType {
191    /// Fixação direta do objeto
192    Direct,
193    /// Fixação recursiva (inclui referencias)
194    Recursive,
195    /// Fixação indireta (referenciado por outro pin)
196    Indirect,
197}
198
199/// Estatísticas de um bloco
200#[derive(Debug, Clone)]
201pub struct BlockStats {
202    pub cid: Cid,
203    pub size: u64,
204    pub exists_locally: bool,
205}
206
207/// Estatísticas de garbage collection
208#[derive(Debug, Clone)]
209pub struct GcStats {
210    pub blocks_removed: u64,
211    pub bytes_freed: u64,
212    pub duration_ms: u64,
213}
214
215/// Métricas de performance do backend
216#[derive(Debug, Clone)]
217pub struct BackendMetrics {
218    /// Operações por segundo
219    pub ops_per_second: f64,
220    /// Latência média em ms
221    pub avg_latency_ms: f64,
222    /// Número de operações totais
223    pub total_operations: u64,
224    /// Número de erros
225    pub error_count: u64,
226    /// Uso de memória em bytes
227    pub memory_usage_bytes: u64,
228}
229
230/// Status de saúde do backend
231#[derive(Debug, Clone)]
232pub struct HealthStatus {
233    /// Backend está saudável
234    pub healthy: bool,
235    /// Mensagem descritiva
236    pub message: String,
237    /// Tempo de resposta em ms
238    pub response_time_ms: u64,
239    /// Componentes verificados
240    pub checks: Vec<HealthCheck>,
241}
242
243/// Verificação individual de saúde
244#[derive(Debug, Clone)]
245pub struct HealthCheck {
246    pub name: String,
247    pub passed: bool,
248    pub message: String,
249}
250
251/// Factory para criar backends baseado na configuração
252pub struct BackendFactory;
253
254impl BackendFactory {
255    /// Cria um backend baseado no tipo especificado
256    ///
257    /// # Argumentos
258    /// * `backend_type` - Tipo do backend desejado
259    /// * `config` - Configuração específica do backend
260    ///
261    /// # Retorna
262    /// Instância do backend configurado
263    pub async fn create_backend(
264        backend_type: BackendType,
265        config: &crate::ipfs_core_api::config::ClientConfig,
266    ) -> Result<Box<dyn IpfsBackend>> {
267        match backend_type {
268            BackendType::Iroh => {
269                let backend = iroh::IrohBackend::new(config).await?;
270                Ok(Box::new(backend))
271            }
272            BackendType::Hybrid => {
273                let backend = hybrid::HybridBackend::new(config).await?;
274                Ok(Box::new(backend))
275            }
276            BackendType::Mock => Err(GuardianError::Other(
277                "Mock backend não implementado ainda".to_string(),
278            )),
279        }
280    }
281
282    /// Auto-detecta o melhor backend baseado na configuração disponível
283    ///
284    /// # Argumentos
285    /// * `config` - Configuração do cliente
286    ///
287    /// # Retorna
288    /// Backend mais apropriado para a configuração
289    pub async fn auto_detect_backend(
290        config: &crate::ipfs_core_api::config::ClientConfig,
291    ) -> Result<Box<dyn IpfsBackend>> {
292        // Prioridade: Hybrid > Iroh (nativo)
293
294        // Tenta Hybrid primeiro (melhor desempenho + compatibilidade P2P)
295        if config.data_store_path.is_some()
296            && config.enable_pubsub
297            && let Ok(backend) = hybrid::HybridBackend::new(config).await
298        {
299            return Ok(Box::new(backend));
300        }
301
302        // Fallback para Iroh puro (sempre disponível)
303        if let Ok(backend) = iroh::IrohBackend::new(config).await {
304            return Ok(Box::new(backend));
305        }
306
307        Err(GuardianError::Other(
308            "Falha ao inicializar backend Iroh".to_string(),
309        ))
310    }
311}