Update futriix-cli/src/main.rs

This commit is contained in:
Григорий Сафронов 2025-06-14 21:10:37 +00:00
parent 9e7b42d009
commit 143c570c48

View File

@ -13,6 +13,11 @@ enum Command {
Get { key: String }, Get { key: String },
Update { key: String, value: serde_json::Value }, Update { key: String, value: serde_json::Value },
Delete { key: String }, Delete { key: String },
BeginTransaction,
CommitTransaction,
RollbackTransaction,
CreateIndex { field: String },
DropIndex { field: String },
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
@ -32,30 +37,24 @@ async fn send_command(cmd: Command) -> Result<Response, Box<dyn Error>> {
let mut stream = TcpStream::connect(&addr).await?; let mut stream = TcpStream::connect(&addr).await?;
let cmd_bytes = rmp_serde::to_vec(&cmd)?; let cmd_bytes = rmp_serde::to_vec(&cmd)?;
// Send command length (4 bytes)
let len = cmd_bytes.len() as u32; let len = cmd_bytes.len() as u32;
stream.write_all(&len.to_be_bytes()).await?; stream.write_all(&len.to_be_bytes()).await?;
// Send command
stream.write_all(&cmd_bytes).await?; stream.write_all(&cmd_bytes).await?;
// Read response length
let mut len_buf = [0u8; 4]; let mut len_buf = [0u8; 4];
stream.read_exact(&mut len_buf).await?; stream.read_exact(&mut len_buf).await?;
let len = u32::from_be_bytes(len_buf) as usize; let len = u32::from_be_bytes(len_buf) as usize;
// Read response
let mut buf = vec![0u8; len]; let mut buf = vec![0u8; len];
stream.read_exact(&mut buf).await?; stream.read_exact(&mut buf).await?;
let response = rmp_serde::from_slice(&buf)?; Ok(rmp_serde::from_slice(&buf)?)
Ok(response)
} }
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("{}", "Futriix CLI Client".bright_blue()); println!();
println!("{}", "Futriix CLI Client".bright_cyan());
println!("Type 'help' for available commands"); println!("Type 'help' for available commands");
let mut rl = Editor::<()>::new()?; let mut rl = Editor::<()>::new()?;
@ -83,14 +82,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let key = parts[1].to_string(); let key = parts[1].to_string();
let value_str = parts[2..].join(" "); let value_str = parts[2..].join(" ");
match serde_json::from_str(&value_str) { match serde_json::from_str(&value_str) {
Ok(value) => { Ok(value) => match send_command(Command::Insert { key, value }).await {
match send_command(Command::Insert { key, value }).await { Ok(Response::Success(_)) => {
Ok(Response::Success(_)) => println!("Insert successful"), println!("{}", "Insert successful".bright_green());
Ok(Response::Error(e)) => println!("{}: {}", "Error".red(), e), println!();
Err(e) => println!("{}: {}", "Connection error".red(), e), },
} Ok(Response::Error(e)) => println!("{}", e.bold().red()),
Err(e) => println!("{}: {}", "Connection error".red(), e),
}, },
Err(e) => println!("{}: Invalid JSON: {}", "Error".red(), e), Err(e) => println!("{}: {}", "Invalid JSON".red(), e),
} }
}, },
"get" | "g" => { "get" | "g" => {
@ -100,8 +100,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
match send_command(Command::Get { key: parts[1].to_string() }).await { match send_command(Command::Get { key: parts[1].to_string() }).await {
Ok(Response::Success(Some(value))) => println!("{}", serde_json::to_string_pretty(&value)?), Ok(Response::Success(Some(value))) => println!("{}", serde_json::to_string_pretty(&value)?),
Ok(Response::Success(None)) => println!("Key not found"), Ok(Response::Success(None)) => println!("{}", "Error: Key not found".bold().red()),
Ok(Response::Error(e)) => println!("{}: {}", "Error".red(), e), Ok(Response::Error(e)) => println!("{}", e.bold().red()),
Err(e) => println!("{}: {}", "Connection error".red(), e), Err(e) => println!("{}: {}", "Connection error".red(), e),
} }
}, },
@ -113,14 +113,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let key = parts[1].to_string(); let key = parts[1].to_string();
let value_str = parts[2..].join(" "); let value_str = parts[2..].join(" ");
match serde_json::from_str(&value_str) { match serde_json::from_str(&value_str) {
Ok(value) => { Ok(value) => match send_command(Command::Update { key, value }).await {
match send_command(Command::Update { key, value }).await { Ok(Response::Success(_)) => println!("{}", "Update successful".bright_green()),
Ok(Response::Success(_)) => println!("Update successful"), Ok(Response::Error(e)) => println!("{}", e.bold().red()),
Ok(Response::Error(e)) => println!("{}: {}", "Error".red(), e), Err(e) => println!("{}: {}", "Connection error".red(), e),
Err(e) => println!("{}: {}", "Connection error".red(), e),
}
}, },
Err(e) => println!("{}: Invalid JSON: {}", "Error".red(), e), Err(e) => println!("{}: {}", "Invalid JSON".red(), e),
} }
}, },
"delete" | "d" => { "delete" | "d" => {
@ -129,8 +127,45 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
continue; continue;
} }
match send_command(Command::Delete { key: parts[1].to_string() }).await { match send_command(Command::Delete { key: parts[1].to_string() }).await {
Ok(Response::Success(_)) => println!("Delete successful"), Ok(Response::Success(_)) => println!("{}", "Delete successful".bright_green()),
Ok(Response::Error(e)) => println!("{}: {}", "Error".red(), e), Ok(Response::Error(e)) => println!("{}", e.bold().red()),
Err(e) => println!("{}: {}", "Connection error".red(), e),
}
},
"begin" => match send_command(Command::BeginTransaction).await {
Ok(Response::Success(_)) => println!("{}", "Transaction started".bright_green()),
Ok(Response::Error(e)) => println!("{}", e.bold().red()),
Err(e) => println!("{}: {}", "Connection error".red(), e),
},
"commit" => match send_command(Command::CommitTransaction).await {
Ok(Response::Success(_)) => println!("{}", "Transaction committed".bright_green()),
Ok(Response::Error(e)) => println!("{}", e.bold().red()),
Err(e) => println!("{}: {}", "Connection error".red(), e),
},
"rollback" => match send_command(Command::RollbackTransaction).await {
Ok(Response::Success(_)) => println!("{}", "Transaction rolled back".bright_green()),
Ok(Response::Error(e)) => println!("{}", e.bold().red()),
Err(e) => println!("{}: {}", "Connection error".red(), e),
},
"create_index" => {
if parts.len() != 2 {
println!("{}", "Usage: create_index <field_name>".red());
continue;
}
match send_command(Command::CreateIndex { field: parts[1].to_string() }).await {
Ok(Response::Success(_)) => println!("{}", format!("Index created on field '{}'", parts[1]).bright_green()),
Ok(Response::Error(e)) => println!("{}", e.bold().red()),
Err(e) => println!("{}: {}", "Connection error".red(), e),
}
},
"drop_index" => {
if parts.len() != 2 {
println!("{}", "Usage: drop_index <field_name>".red());
continue;
}
match send_command(Command::DropIndex { field: parts[1].to_string() }).await {
Ok(Response::Success(_)) => println!("{}", format!("Index dropped on field '{}'", parts[1]).bright_green()),
Ok(Response::Error(e)) => println!("{}", e.bold().red()),
Err(e) => println!("{}: {}", "Connection error".red(), e), Err(e) => println!("{}: {}", "Connection error".red(), e),
} }
}, },
@ -140,6 +175,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" get|g <key> - Get document"); println!(" get|g <key> - Get document");
println!(" update|u <key> <json_value> - Update document"); println!(" update|u <key> <json_value> - Update document");
println!(" delete|d <key> - Delete document"); println!(" delete|d <key> - Delete document");
println!(" begin - Start transaction");
println!(" commit - Commit transaction");
println!(" rollback - Rollback transaction");
println!(" create_index <field> - Create index");
println!(" drop_index <field> - Drop index");
println!(" help|h - Show this help"); println!(" help|h - Show this help");
println!(" exit|quit|q - Exit the client"); println!(" exit|quit|q - Exit the client");
}, },