feat: unify CLI and API with DataService trait
- Add DataService trait with streaming support for save/get operations
- Implement SyncDataService for CLI and AsyncDataService for API
- Add missing API endpoints: DELETE /api/item/{id}, GET /api/item/{id}/info, GET /api/diff
- Add GET /api/plugins/status endpoint
- Preserve stdin/stdout streaming performance via Read trait
This commit is contained in:
148
src/services/async_data_service.rs
Normal file
148
src/services/async_data_service.rs
Normal file
@@ -0,0 +1,148 @@
|
||||
use crate::common::status::StatusInfo;
|
||||
use crate::config::Settings;
|
||||
use crate::db::Item;
|
||||
use crate::db::Meta;
|
||||
use crate::services::data_service::DataService;
|
||||
use crate::services::error::CoreError;
|
||||
use crate::services::types::{ItemWithContent, ItemWithMeta};
|
||||
use clap::Command;
|
||||
use rusqlite::Connection;
|
||||
use std::collections::HashMap;
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
pub struct AsyncDataService {
|
||||
data_path: PathBuf,
|
||||
settings: Arc<Settings>,
|
||||
db: Arc<Mutex<Connection>>,
|
||||
}
|
||||
|
||||
impl AsyncDataService {
|
||||
pub fn new(data_path: PathBuf, settings: Arc<Settings>, db: Arc<Mutex<Connection>>) -> Self {
|
||||
Self {
|
||||
data_path,
|
||||
settings,
|
||||
db,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data_path(&self) -> &PathBuf {
|
||||
&self.data_path
|
||||
}
|
||||
|
||||
pub fn settings(&self) -> Arc<Settings> {
|
||||
self.settings.clone()
|
||||
}
|
||||
|
||||
pub fn db(&self) -> Arc<Mutex<Connection>> {
|
||||
self.db.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl DataService for AsyncDataService {
|
||||
type Error = CoreError;
|
||||
|
||||
fn save<R: Read>(
|
||||
&self,
|
||||
content: R,
|
||||
cmd: &mut Command,
|
||||
settings: &Settings,
|
||||
tags: Vec<String>,
|
||||
conn: &mut Connection,
|
||||
) -> Result<Item, Self::Error> {
|
||||
let sync_service =
|
||||
crate::services::SyncDataService::new(self.data_path.clone(), settings.clone());
|
||||
sync_service.save(content, cmd, settings, tags, conn)
|
||||
}
|
||||
|
||||
fn get(&self, conn: &mut Connection, id: i64) -> Result<ItemWithMeta, Self::Error> {
|
||||
let sync_service = crate::services::SyncDataService::new(
|
||||
self.data_path.clone(),
|
||||
self.settings.as_ref().clone(),
|
||||
);
|
||||
sync_service.get(conn, id)
|
||||
}
|
||||
|
||||
fn get_content(
|
||||
&self,
|
||||
conn: &mut Connection,
|
||||
id: i64,
|
||||
) -> Result<(Box<dyn Read + Send>, ItemWithMeta), Self::Error> {
|
||||
let sync_service = crate::services::SyncDataService::new(
|
||||
self.data_path.clone(),
|
||||
self.settings.as_ref().clone(),
|
||||
);
|
||||
sync_service.get_content(conn, id)
|
||||
}
|
||||
|
||||
fn list(
|
||||
&self,
|
||||
conn: &mut Connection,
|
||||
tags: Vec<String>,
|
||||
meta: HashMap<String, String>,
|
||||
) -> Result<Vec<ItemWithMeta>, Self::Error> {
|
||||
let sync_service = crate::services::SyncDataService::new(
|
||||
self.data_path.clone(),
|
||||
self.settings.as_ref().clone(),
|
||||
);
|
||||
sync_service.list(conn, tags, meta)
|
||||
}
|
||||
|
||||
fn delete(&self, conn: &mut Connection, id: i64) -> Result<Item, Self::Error> {
|
||||
let sync_service = crate::services::SyncDataService::new(
|
||||
self.data_path.clone(),
|
||||
self.settings.as_ref().clone(),
|
||||
);
|
||||
sync_service.delete(conn, id)
|
||||
}
|
||||
|
||||
fn find_item(
|
||||
&self,
|
||||
conn: &mut Connection,
|
||||
ids: Vec<i64>,
|
||||
tags: Vec<String>,
|
||||
meta: HashMap<String, String>,
|
||||
) -> Result<ItemWithMeta, Self::Error> {
|
||||
let sync_service = crate::services::SyncDataService::new(
|
||||
self.data_path.clone(),
|
||||
self.settings.as_ref().clone(),
|
||||
);
|
||||
sync_service.find_item(conn, ids, tags, meta)
|
||||
}
|
||||
|
||||
fn get_items(
|
||||
&self,
|
||||
conn: &mut Connection,
|
||||
ids: &[i64],
|
||||
tags: &[String],
|
||||
meta: &HashMap<String, String>,
|
||||
) -> Result<Vec<ItemWithMeta>, Self::Error> {
|
||||
let sync_service = crate::services::SyncDataService::new(
|
||||
self.data_path.clone(),
|
||||
self.settings.as_ref().clone(),
|
||||
);
|
||||
sync_service.get_items(conn, ids, tags, meta)
|
||||
}
|
||||
|
||||
fn generate_status(
|
||||
&self,
|
||||
_cmd: &Command,
|
||||
settings: &Settings,
|
||||
data_path: &PathBuf,
|
||||
db_path: &PathBuf,
|
||||
) -> Result<StatusInfo, Self::Error> {
|
||||
let mut cmd_mut = Command::new("keep");
|
||||
let sync_service =
|
||||
crate::services::SyncDataService::new(self.data_path.clone(), settings.clone());
|
||||
Ok(
|
||||
sync_service.generate_status(
|
||||
&mut cmd_mut,
|
||||
settings,
|
||||
data_path.clone(),
|
||||
db_path.clone(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user