use alun_core::plugin::Plugin;
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tracing::info;
use super::local::LocalFs;
pub type StoreResult<T> = Result<T, String>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileMeta {
pub file_id: String,
pub original_name: String,
pub stored_path: String,
pub size: u64,
pub content_type: String,
pub created_at: DateTime<Utc>,
}
#[derive(Clone)]
pub enum FsBackend {
Local(Arc<LocalFs>),
}
pub struct FsPlugin {
backend: FsBackend,
}
impl FsPlugin {
pub fn new_local(root_dir: &str) -> Self {
let fs = LocalFs::new(root_dir);
Self {
backend: FsBackend::Local(Arc::new(fs)),
}
}
pub fn backend(&self) -> &FsBackend { &self.backend }
pub fn local(&self) -> Option<&Arc<LocalFs>> {
match &self.backend {
FsBackend::Local(fs) => Some(fs),
}
}
pub async fn write(&self, filename: &str, data: &[u8]) -> StoreResult<FileMeta> {
match &self.backend {
FsBackend::Local(fs) => fs.write_with_name(filename, data).await,
}
}
pub async fn read(&self, path: &str) -> StoreResult<Vec<u8>> {
match &self.backend {
FsBackend::Local(fs) => fs.read(path).await,
}
}
pub async fn delete(&self, path: &str) -> StoreResult<()> {
match &self.backend {
FsBackend::Local(fs) => fs.delete(path).await,
}
}
pub async fn exists(&self, path: &str) -> bool {
match &self.backend {
FsBackend::Local(fs) => fs.exists(path).await,
}
}
}
#[async_trait]
impl Plugin for FsPlugin {
fn name(&self) -> &str { "fs" }
async fn start(&self) -> alun_core::Result<()> {
info!("FsPlugin 启动 (local)");
Ok(())
}
async fn stop(&self) -> alun_core::Result<()> {
info!("FsPlugin 停止");
Ok(())
}
}