d5ef68c9c9
New files: - musicfs-core/src/config.rs: Config, OriginConfig, HealthConfig - musicfs-origins/src/registry.rs: OriginRegistry with watch cleanup - musicfs-origins/src/router.rs: Priority router with (priority, latency) ordering - musicfs-origins/src/health.rs: HealthMonitor with per-origin-type thresholds - musicfs-origins/src/failover.rs: FailoverExecutor with NFR-7.3 backoff Oracle fixes applied: - Per-OriginType threshold: Local=1, Remote=3 (check_one uses threshold_for) - AllOriginsUnhealthy event: Added to events.rs, emitted in select_with_fallback - Unified OriginType: Removed duplicate from traits.rs, use musicfs_core::OriginType - Watch handle cleanup: Tracked and dropped on unregister() - Retry delays: 100ms, 500ms, 2000ms (NFR-7.3 compliant) Tests: 91 pass (+20 new)
50 lines
1.3 KiB
Rust
50 lines
1.3 KiB
Rust
use async_trait::async_trait;
|
|
use musicfs_core::{DirEntry, FileStat, HealthStatus, OriginId, OriginType, Result};
|
|
use std::path::{Path, PathBuf};
|
|
use tokio::io::AsyncRead;
|
|
|
|
#[async_trait]
|
|
pub trait Origin: Send + Sync {
|
|
fn id(&self) -> &OriginId;
|
|
|
|
fn origin_type(&self) -> OriginType;
|
|
|
|
fn display_name(&self) -> &str;
|
|
|
|
async fn readdir(&self, path: &Path) -> Result<Vec<DirEntry>>;
|
|
|
|
async fn stat(&self, path: &Path) -> Result<FileStat>;
|
|
|
|
async fn read(&self, path: &Path, offset: u64, size: u32) -> Result<Vec<u8>>;
|
|
|
|
/// Read entire file content (for CDC chunking of files <4GB)
|
|
async fn read_full(&self, path: &Path) -> Result<Vec<u8>>;
|
|
|
|
async fn exists(&self, path: &Path) -> Result<bool>;
|
|
|
|
async fn health(&self) -> HealthStatus;
|
|
|
|
async fn open_read(&self, path: &Path) -> Result<Box<dyn AsyncRead + Send + Unpin>>;
|
|
|
|
async fn watch(&self, path: &Path, callback: WatchCallback) -> Result<WatchHandle>;
|
|
}
|
|
|
|
pub type WatchCallback = Box<dyn Fn(WatchEvent) + Send + Sync>;
|
|
|
|
pub struct WatchHandle {
|
|
_cancel: tokio::sync::oneshot::Sender<()>,
|
|
}
|
|
|
|
impl WatchHandle {
|
|
pub fn new(cancel: tokio::sync::oneshot::Sender<()>) -> Self {
|
|
Self { _cancel: cancel }
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum WatchEvent {
|
|
Created(PathBuf),
|
|
Modified(PathBuf),
|
|
Deleted(PathBuf),
|
|
}
|