fix invalid values in RPC response about database instance details
This commit is contained in:
133
src/rpc.rs
133
src/rpc.rs
@@ -338,6 +338,92 @@ impl RpcServerImpl {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Build database file path for given server/db_id
|
||||||
|
fn db_file_path(&self, server: &Server, db_id: u64) -> std::path::PathBuf {
|
||||||
|
std::path::PathBuf::from(&server.option.dir).join(format!("{}.db", db_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Recursively compute size on disk for the database path
|
||||||
|
fn compute_size_on_disk(&self, path: &std::path::Path) -> Option<u64> {
|
||||||
|
fn dir_size(p: &std::path::Path) -> u64 {
|
||||||
|
if p.is_file() {
|
||||||
|
std::fs::metadata(p).map(|m| m.len()).unwrap_or(0)
|
||||||
|
} else if p.is_dir() {
|
||||||
|
let mut total = 0u64;
|
||||||
|
if let Ok(read) = std::fs::read_dir(p) {
|
||||||
|
for entry in read.flatten() {
|
||||||
|
total += dir_size(&entry.path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(dir_size(path))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extract created and last access times (secs) from a path, with fallbacks
|
||||||
|
fn get_file_times_secs(path: &std::path::Path) -> (u64, Option<u64>) {
|
||||||
|
let now = std::time::SystemTime::now();
|
||||||
|
let created = std::fs::metadata(path)
|
||||||
|
.and_then(|m| m.created().or_else(|_| m.modified()))
|
||||||
|
.unwrap_or(now)
|
||||||
|
.duration_since(std::time::UNIX_EPOCH)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.as_secs();
|
||||||
|
|
||||||
|
let last_access = std::fs::metadata(path)
|
||||||
|
.and_then(|m| m.accessed())
|
||||||
|
.ok()
|
||||||
|
.and_then(|t| t.duration_since(std::time::UNIX_EPOCH).ok().map(|d| d.as_secs()));
|
||||||
|
|
||||||
|
(created, last_access)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compose a DatabaseInfo by probing storage, metadata and filesystem
|
||||||
|
async fn build_database_info(&self, db_id: u64, server: &Server) -> DatabaseInfo {
|
||||||
|
// Probe storage to determine encryption state
|
||||||
|
let storage = server.current_storage().ok();
|
||||||
|
let encrypted = storage.as_ref().map(|s| s.is_encrypted()).unwrap_or(server.option.encrypt);
|
||||||
|
|
||||||
|
// Load meta to get access key count
|
||||||
|
let meta = Self::load_meta_static(&self.base_dir, db_id).await.unwrap_or(DatabaseMeta {
|
||||||
|
public: true,
|
||||||
|
keys: HashMap::new(),
|
||||||
|
});
|
||||||
|
let key_count = Some(meta.keys.len() as u64);
|
||||||
|
|
||||||
|
// Compute size on disk and timestamps
|
||||||
|
let db_path = self.db_file_path(server, db_id);
|
||||||
|
let size_on_disk = self.compute_size_on_disk(&db_path);
|
||||||
|
|
||||||
|
let meta_path = std::path::PathBuf::from(&self.base_dir).join(format!("{}_meta.json", db_id));
|
||||||
|
let (created_at, last_access) = if meta_path.exists() {
|
||||||
|
Self::get_file_times_secs(&meta_path)
|
||||||
|
} else {
|
||||||
|
Self::get_file_times_secs(&db_path)
|
||||||
|
};
|
||||||
|
|
||||||
|
let backend = match server.option.backend {
|
||||||
|
crate::options::BackendType::Redb => BackendType::Redb,
|
||||||
|
crate::options::BackendType::Sled => BackendType::Sled,
|
||||||
|
};
|
||||||
|
|
||||||
|
DatabaseInfo {
|
||||||
|
id: db_id,
|
||||||
|
name: None,
|
||||||
|
backend,
|
||||||
|
encrypted,
|
||||||
|
redis_version: Some("7.0".to_string()),
|
||||||
|
storage_path: Some(server.option.dir.clone()),
|
||||||
|
size_on_disk,
|
||||||
|
key_count,
|
||||||
|
created_at,
|
||||||
|
last_access,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[jsonrpsee::core::async_trait]
|
#[jsonrpsee::core::async_trait]
|
||||||
@@ -426,28 +512,9 @@ impl RpcServer for RpcServerImpl {
|
|||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
|
|
||||||
for db_id in db_ids {
|
for db_id in db_ids {
|
||||||
// Try to get or create server for this database
|
|
||||||
if let Ok(server) = self.get_or_create_server(db_id).await {
|
if let Ok(server) = self.get_or_create_server(db_id).await {
|
||||||
let backend = match server.option.backend {
|
// Build accurate info from storage/meta/fs
|
||||||
crate::options::BackendType::Redb => BackendType::Redb,
|
let info = self.build_database_info(db_id, &server).await;
|
||||||
crate::options::BackendType::Sled => BackendType::Sled,
|
|
||||||
};
|
|
||||||
|
|
||||||
let info = DatabaseInfo {
|
|
||||||
id: db_id,
|
|
||||||
name: None, // TODO: Store name in server metadata
|
|
||||||
backend,
|
|
||||||
encrypted: server.option.encrypt,
|
|
||||||
redis_version: Some("7.0".to_string()), // Default Redis compatibility
|
|
||||||
storage_path: Some(server.option.dir.clone()),
|
|
||||||
size_on_disk: None, // TODO: Calculate actual size
|
|
||||||
key_count: None, // TODO: Get key count from storage
|
|
||||||
created_at: std::time::SystemTime::now()
|
|
||||||
.duration_since(std::time::UNIX_EPOCH)
|
|
||||||
.unwrap()
|
|
||||||
.as_secs(),
|
|
||||||
last_access: None,
|
|
||||||
};
|
|
||||||
result.push(info);
|
result.push(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -457,27 +524,9 @@ impl RpcServer for RpcServerImpl {
|
|||||||
|
|
||||||
async fn get_database_info(&self, db_id: u64) -> RpcResult<DatabaseInfo> {
|
async fn get_database_info(&self, db_id: u64) -> RpcResult<DatabaseInfo> {
|
||||||
let server = self.get_or_create_server(db_id).await?;
|
let server = self.get_or_create_server(db_id).await?;
|
||||||
|
// Build accurate info from storage/meta/fs
|
||||||
let backend = match server.option.backend {
|
let info = self.build_database_info(db_id, &server).await;
|
||||||
crate::options::BackendType::Redb => BackendType::Redb,
|
Ok(info)
|
||||||
crate::options::BackendType::Sled => BackendType::Sled,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(DatabaseInfo {
|
|
||||||
id: db_id,
|
|
||||||
name: None,
|
|
||||||
backend,
|
|
||||||
encrypted: server.option.encrypt,
|
|
||||||
redis_version: Some("7.0".to_string()),
|
|
||||||
storage_path: Some(server.option.dir.clone()),
|
|
||||||
size_on_disk: None,
|
|
||||||
key_count: None,
|
|
||||||
created_at: std::time::SystemTime::now()
|
|
||||||
.duration_since(std::time::UNIX_EPOCH)
|
|
||||||
.unwrap()
|
|
||||||
.as_secs(),
|
|
||||||
last_access: None,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn delete_database(&self, db_id: u64) -> RpcResult<bool> {
|
async fn delete_database(&self, db_id: u64) -> RpcResult<bool> {
|
||||||
|
Reference in New Issue
Block a user