fixed connection handling issue
This commit is contained in:
@@ -5,6 +5,7 @@ use tokio::sync::Mutex;
|
||||
use tokio::net::TcpListener;
|
||||
|
||||
use herodb::server;
|
||||
use herodb::server::Server;
|
||||
use herodb::rpc_server;
|
||||
|
||||
use clap::Parser;
|
||||
@@ -98,8 +99,7 @@ async fn main() {
|
||||
|
||||
let sc = Arc::clone(&server);
|
||||
tokio::spawn(async move {
|
||||
let mut server_guard = sc.lock().await;
|
||||
if let Err(e) = server_guard.handle(stream).await {
|
||||
if let Err(e) = Server::handle(sc, stream).await {
|
||||
println!("error: {:?}, will close the connection. Bye", e);
|
||||
}
|
||||
});
|
||||
|
@@ -177,11 +177,34 @@ impl RpcServer for RpcServerImpl {
|
||||
let db_path = std::path::PathBuf::from(&self.base_dir).join(format!("{}.db", db_index));
|
||||
let file_exists = db_path.exists();
|
||||
|
||||
// Get file size if it exists
|
||||
let size_on_disk = if file_exists {
|
||||
std::fs::metadata(&db_path).ok().map(|m| m.len())
|
||||
// If database doesn't exist, return an error
|
||||
if !file_exists && db_index != 0 {
|
||||
return Err(jsonrpsee::types::ErrorObjectOwned::owned(
|
||||
-32000,
|
||||
format!("Database {} does not exist", db_index),
|
||||
None::<()>
|
||||
));
|
||||
}
|
||||
|
||||
// Get file metadata if it exists
|
||||
let (size_on_disk, created_at) = if file_exists {
|
||||
if let Ok(metadata) = std::fs::metadata(&db_path) {
|
||||
let size = Some(metadata.len());
|
||||
let created = metadata.created()
|
||||
.unwrap_or(std::time::SystemTime::UNIX_EPOCH)
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap_or_default()
|
||||
.as_secs();
|
||||
(size, created)
|
||||
} else {
|
||||
(None, 0)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
// Database 0 might not have a file yet
|
||||
(None, std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs())
|
||||
};
|
||||
|
||||
Ok(DatabaseInfo {
|
||||
@@ -193,10 +216,7 @@ impl RpcServer for RpcServerImpl {
|
||||
storage_path: Some(self.base_dir.clone()),
|
||||
size_on_disk,
|
||||
key_count: None, // Would need to open DB to count keys
|
||||
created_at: std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs(),
|
||||
created_at,
|
||||
last_access: None,
|
||||
})
|
||||
}
|
||||
|
@@ -167,7 +167,7 @@ impl Server {
|
||||
}
|
||||
|
||||
pub async fn handle(
|
||||
&mut self,
|
||||
server: Arc<Mutex<Server>>,
|
||||
mut stream: tokio::net::TcpStream,
|
||||
) -> Result<(), DBError> {
|
||||
// Accumulate incoming bytes to handle partial RESP frames
|
||||
@@ -205,31 +205,49 @@ impl Server {
|
||||
// Advance the accumulator to the unparsed remainder
|
||||
acc = remaining.to_string();
|
||||
|
||||
if self.option.debug {
|
||||
println!("\x1b[34;1mgot command: {:?}, protocol: {:?}\x1b[0m", cmd, protocol);
|
||||
} else {
|
||||
println!("got command: {:?}, protocol: {:?}", cmd, protocol);
|
||||
}
|
||||
|
||||
// Check if this is a QUIT command before processing
|
||||
let is_quit = matches!(cmd, Cmd::Quit);
|
||||
|
||||
let res = match cmd.run(self).await {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
if self.option.debug {
|
||||
eprintln!("[run error] {:?}", e);
|
||||
}
|
||||
Protocol::err(&format!("ERR {}", e.0))
|
||||
// Lock the server only for command execution
|
||||
let (res, debug_info) = {
|
||||
let mut server_guard = server.lock().await;
|
||||
|
||||
if server_guard.option.debug {
|
||||
println!("\x1b[34;1mgot command: {:?}, protocol: {:?}\x1b[0m", cmd, protocol);
|
||||
} else {
|
||||
println!("got command: {:?}, protocol: {:?}", cmd, protocol);
|
||||
}
|
||||
|
||||
let res = match cmd.run(&mut server_guard).await {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
if server_guard.option.debug {
|
||||
eprintln!("[run error] {:?}", e);
|
||||
}
|
||||
Protocol::err(&format!("ERR {}", e.0))
|
||||
}
|
||||
};
|
||||
|
||||
let debug_info = if server_guard.option.debug {
|
||||
Some((format!("queued cmd {:?}", server_guard.queued_cmd), format!("going to send response {}", res.encode())))
|
||||
} else {
|
||||
Some((format!("queued cmd {:?}", server_guard.queued_cmd), format!("going to send response {}", res.encode())))
|
||||
};
|
||||
|
||||
(res, debug_info)
|
||||
};
|
||||
|
||||
if self.option.debug {
|
||||
println!("\x1b[34;1mqueued cmd {:?}\x1b[0m", self.queued_cmd);
|
||||
println!("\x1b[32;1mgoing to send response {}\x1b[0m", res.encode());
|
||||
} else {
|
||||
print!("queued cmd {:?}", self.queued_cmd);
|
||||
println!("going to send response {}", res.encode());
|
||||
// Print debug info outside the lock
|
||||
if let Some((queued_info, response_info)) = debug_info {
|
||||
if let Some((_, response)) = response_info.split_once("going to send response ") {
|
||||
if queued_info.contains("\x1b[34;1m") {
|
||||
println!("\x1b[34;1m{}\x1b[0m", queued_info);
|
||||
println!("\x1b[32;1mgoing to send response {}\x1b[0m", response);
|
||||
} else {
|
||||
println!("{}", queued_info);
|
||||
println!("going to send response {}", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ = stream.write(res.encode().as_bytes()).await?;
|
||||
|
@@ -1,4 +1,6 @@
|
||||
use herodb::{server::Server, options::DBOption};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
@@ -29,17 +31,20 @@ async fn debug_hset_simple() {
|
||||
encryption_key: None,
|
||||
};
|
||||
|
||||
let mut server = Server::new(option).await;
|
||||
|
||||
let server = Arc::new(Mutex::new(Server::new(option).await));
|
||||
|
||||
// Start server in background
|
||||
tokio::spawn(async move {
|
||||
let listener = tokio::net::TcpListener::bind(format!("127.0.0.1:{}", port))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let server_clone = Arc::clone(&server);
|
||||
tokio::spawn(async move {
|
||||
let _ = Server::handle(server_clone, stream).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -3,6 +3,8 @@ use std::time::Duration;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::time::sleep;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
#[tokio::test]
|
||||
async fn debug_hset_return_value() {
|
||||
@@ -20,17 +22,20 @@ async fn debug_hset_return_value() {
|
||||
encryption_key: None,
|
||||
};
|
||||
|
||||
let mut server = Server::new(option).await;
|
||||
|
||||
let server = Arc::new(Mutex::new(Server::new(option).await));
|
||||
|
||||
// Start server in background
|
||||
tokio::spawn(async move {
|
||||
let listener = tokio::net::TcpListener::bind("127.0.0.1:16390")
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let server_clone = Arc::clone(&server);
|
||||
tokio::spawn(async move {
|
||||
let _ = Server::handle(server_clone, stream).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -1,21 +1,23 @@
|
||||
use herodb::{server::Server, options::DBOption};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::time::sleep;
|
||||
|
||||
// Helper function to start a test server
|
||||
async fn start_test_server(test_name: &str) -> (Server, u16) {
|
||||
async fn start_test_server(test_name: &str) -> (Arc<Mutex<Server>>, u16) {
|
||||
use std::sync::atomic::{AtomicU16, Ordering};
|
||||
static PORT_COUNTER: AtomicU16 = AtomicU16::new(16379);
|
||||
|
||||
|
||||
let port = PORT_COUNTER.fetch_add(1, Ordering::SeqCst);
|
||||
let test_dir = format!("/tmp/herodb_test_{}", test_name);
|
||||
|
||||
|
||||
// Clean up and create test directory
|
||||
let _ = std::fs::remove_dir_all(&test_dir);
|
||||
std::fs::create_dir_all(&test_dir).unwrap();
|
||||
|
||||
|
||||
let option = DBOption {
|
||||
dir: test_dir,
|
||||
port,
|
||||
@@ -23,8 +25,8 @@ async fn start_test_server(test_name: &str) -> (Server, u16) {
|
||||
encrypt: false,
|
||||
encryption_key: None,
|
||||
};
|
||||
|
||||
let server = Server::new(option).await;
|
||||
|
||||
let server = Arc::new(Mutex::new(Server::new(option).await));
|
||||
(server, port)
|
||||
}
|
||||
|
||||
@@ -54,7 +56,7 @@ async fn send_command(stream: &mut TcpStream, command: &str) -> String {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_basic_ping() {
|
||||
let (mut server, port) = start_test_server("ping").await;
|
||||
let (server, port) = start_test_server("ping").await;
|
||||
|
||||
// Start server in background
|
||||
tokio::spawn(async move {
|
||||
@@ -64,7 +66,7 @@ async fn test_basic_ping() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -78,7 +80,7 @@ async fn test_basic_ping() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_string_operations() {
|
||||
let (mut server, port) = start_test_server("string").await;
|
||||
let (server, port) = start_test_server("string").await;
|
||||
|
||||
// Start server in background
|
||||
tokio::spawn(async move {
|
||||
@@ -88,7 +90,7 @@ async fn test_string_operations() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -120,7 +122,7 @@ async fn test_string_operations() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_incr_operations() {
|
||||
let (mut server, port) = start_test_server("incr").await;
|
||||
let (server, port) = start_test_server("incr").await;
|
||||
|
||||
tokio::spawn(async move {
|
||||
let listener = tokio::net::TcpListener::bind(format!("127.0.0.1:{}", port))
|
||||
@@ -129,7 +131,7 @@ async fn test_incr_operations() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -154,7 +156,7 @@ async fn test_incr_operations() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_hash_operations() {
|
||||
let (mut server, port) = start_test_server("hash").await;
|
||||
let (server, port) = start_test_server("hash").await;
|
||||
|
||||
tokio::spawn(async move {
|
||||
let listener = tokio::net::TcpListener::bind(format!("127.0.0.1:{}", port))
|
||||
@@ -163,7 +165,7 @@ async fn test_hash_operations() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -229,7 +231,7 @@ async fn test_expiration() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -277,7 +279,7 @@ async fn test_scan_operations() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -313,7 +315,7 @@ async fn test_hscan_operations() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -345,7 +347,7 @@ async fn test_transaction_operations() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -388,7 +390,7 @@ async fn test_discard_transaction() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -425,7 +427,7 @@ async fn test_type_command() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -460,7 +462,7 @@ async fn test_config_commands() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -491,7 +493,7 @@ async fn test_info_command() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -520,7 +522,7 @@ async fn test_error_handling() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -558,7 +560,7 @@ async fn test_list_operations() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -1,23 +1,25 @@
|
||||
use herodb::{server::Server, options::DBOption};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
use tokio::time::sleep;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
|
||||
// Helper function to start a test server with clean data directory
|
||||
async fn start_test_server(test_name: &str) -> (Server, u16) {
|
||||
async fn start_test_server(test_name: &str) -> (Arc<Mutex<Server>>, u16) {
|
||||
use std::sync::atomic::{AtomicU16, Ordering};
|
||||
static PORT_COUNTER: AtomicU16 = AtomicU16::new(17000);
|
||||
|
||||
|
||||
// Get a unique port for this test
|
||||
let port = PORT_COUNTER.fetch_add(1, Ordering::SeqCst);
|
||||
|
||||
|
||||
let test_dir = format!("/tmp/herodb_test_{}", test_name);
|
||||
|
||||
|
||||
// Clean up any existing test data
|
||||
let _ = std::fs::remove_dir_all(&test_dir);
|
||||
std::fs::create_dir_all(&test_dir).unwrap();
|
||||
|
||||
|
||||
let option = DBOption {
|
||||
dir: test_dir,
|
||||
port,
|
||||
@@ -25,8 +27,8 @@ async fn start_test_server(test_name: &str) -> (Server, u16) {
|
||||
encrypt: false,
|
||||
encryption_key: None,
|
||||
};
|
||||
|
||||
let server = Server::new(option).await;
|
||||
|
||||
let server = Arc::new(Mutex::new(Server::new(option).await));
|
||||
(server, port)
|
||||
}
|
||||
|
||||
@@ -42,7 +44,7 @@ async fn send_redis_command(port: u16, command: &str) -> String {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_basic_redis_functionality() {
|
||||
let (mut server, port) = start_test_server("basic").await;
|
||||
let (server, port) = start_test_server("basic").await;
|
||||
|
||||
// Start server in background with timeout
|
||||
let server_handle = tokio::spawn(async move {
|
||||
@@ -53,7 +55,7 @@ async fn test_basic_redis_functionality() {
|
||||
// Accept only a few connections for testing
|
||||
for _ in 0..10 {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -111,7 +113,7 @@ async fn test_basic_redis_functionality() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_hash_operations() {
|
||||
let (mut server, port) = start_test_server("hash_ops").await;
|
||||
let (server, port) = start_test_server("hash_ops").await;
|
||||
|
||||
// Start server in background with timeout
|
||||
let server_handle = tokio::spawn(async move {
|
||||
@@ -122,7 +124,7 @@ async fn test_hash_operations() {
|
||||
// Accept only a few connections for testing
|
||||
for _ in 0..5 {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -165,7 +167,7 @@ async fn test_hash_operations() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_transaction_operations() {
|
||||
let (mut server, port) = start_test_server("transactions").await;
|
||||
let (server, port) = start_test_server("transactions").await;
|
||||
|
||||
// Start server in background with timeout
|
||||
let server_handle = tokio::spawn(async move {
|
||||
@@ -176,7 +178,7 @@ async fn test_transaction_operations() {
|
||||
// Accept only a few connections for testing
|
||||
for _ in 0..5 {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let _ = Server::handle(Arc::clone(&server), stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -1,21 +1,23 @@
|
||||
use herodb::{server::Server, options::DBOption};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::time::sleep;
|
||||
|
||||
// Helper function to start a test server with clean data directory
|
||||
async fn start_test_server(test_name: &str) -> (Server, u16) {
|
||||
async fn start_test_server(test_name: &str) -> (Arc<Mutex<Server>>, u16) {
|
||||
use std::sync::atomic::{AtomicU16, Ordering};
|
||||
static PORT_COUNTER: AtomicU16 = AtomicU16::new(16500);
|
||||
|
||||
|
||||
let port = PORT_COUNTER.fetch_add(1, Ordering::SeqCst);
|
||||
let test_dir = format!("/tmp/herodb_simple_test_{}", test_name);
|
||||
|
||||
|
||||
// Clean up any existing test data
|
||||
let _ = std::fs::remove_dir_all(&test_dir);
|
||||
std::fs::create_dir_all(&test_dir).unwrap();
|
||||
|
||||
|
||||
let option = DBOption {
|
||||
dir: test_dir,
|
||||
port,
|
||||
@@ -23,8 +25,8 @@ async fn start_test_server(test_name: &str) -> (Server, u16) {
|
||||
encrypt: false,
|
||||
encryption_key: None,
|
||||
};
|
||||
|
||||
let server = Server::new(option).await;
|
||||
|
||||
let server = Arc::new(Mutex::new(Server::new(option).await));
|
||||
(server, port)
|
||||
}
|
||||
|
||||
@@ -54,7 +56,7 @@ async fn connect_to_server(port: u16) -> TcpStream {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_basic_ping_simple() {
|
||||
let (mut server, port) = start_test_server("ping").await;
|
||||
let (server, port) = start_test_server("ping").await;
|
||||
|
||||
// Start server in background
|
||||
tokio::spawn(async move {
|
||||
@@ -64,7 +66,8 @@ async fn test_basic_ping_simple() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let server_clone = Arc::clone(&server);
|
||||
let _ = Server::handle(server_clone, stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -78,7 +81,7 @@ async fn test_basic_ping_simple() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_hset_clean_db() {
|
||||
let (mut server, port) = start_test_server("hset_clean").await;
|
||||
let (server, port) = start_test_server("hset_clean").await;
|
||||
|
||||
// Start server in background
|
||||
tokio::spawn(async move {
|
||||
@@ -88,7 +91,8 @@ async fn test_hset_clean_db() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let server_clone = Arc::clone(&server);
|
||||
let _ = Server::handle(server_clone, stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -110,7 +114,7 @@ async fn test_hset_clean_db() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_type_command_simple() {
|
||||
let (mut server, port) = start_test_server("type").await;
|
||||
let (server, port) = start_test_server("type").await;
|
||||
|
||||
// Start server in background
|
||||
tokio::spawn(async move {
|
||||
@@ -120,7 +124,8 @@ async fn test_type_command_simple() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let server_clone = Arc::clone(&server);
|
||||
let _ = Server::handle(server_clone, stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -149,7 +154,7 @@ async fn test_type_command_simple() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_hexists_simple() {
|
||||
let (mut server, port) = start_test_server("hexists").await;
|
||||
let (server, port) = start_test_server("hexists").await;
|
||||
|
||||
// Start server in background
|
||||
tokio::spawn(async move {
|
||||
@@ -159,7 +164,8 @@ async fn test_hexists_simple() {
|
||||
|
||||
loop {
|
||||
if let Ok((stream, _)) = listener.accept().await {
|
||||
let _ = server.handle(stream).await;
|
||||
let server_clone = Arc::clone(&server);
|
||||
let _ = Server::handle(server_clone, stream).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -2,12 +2,14 @@ use herodb::{options::DBOption, server::Server};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::time::{sleep, Duration};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
// =========================
|
||||
// Helpers
|
||||
// =========================
|
||||
|
||||
async fn start_test_server(test_name: &str) -> (Server, u16) {
|
||||
async fn start_test_server(test_name: &str) -> (Arc<Mutex<Server>>, u16) {
|
||||
use std::sync::atomic::{AtomicU16, Ordering};
|
||||
static PORT_COUNTER: AtomicU16 = AtomicU16::new(17100);
|
||||
let port = PORT_COUNTER.fetch_add(1, Ordering::SeqCst);
|
||||
@@ -24,11 +26,11 @@ async fn start_test_server(test_name: &str) -> (Server, u16) {
|
||||
encryption_key: None,
|
||||
};
|
||||
|
||||
let server = Server::new(option).await;
|
||||
let server = Arc::new(Mutex::new(Server::new(option).await));
|
||||
(server, port)
|
||||
}
|
||||
|
||||
async fn spawn_listener(server: Server, port: u16) {
|
||||
async fn spawn_listener(server: Arc<Mutex<Server>>, port: u16) {
|
||||
tokio::spawn(async move {
|
||||
let listener = tokio::net::TcpListener::bind(format!("127.0.0.1:{}", port))
|
||||
.await
|
||||
@@ -36,9 +38,9 @@ async fn spawn_listener(server: Server, port: u16) {
|
||||
loop {
|
||||
match listener.accept().await {
|
||||
Ok((stream, _)) => {
|
||||
let mut s_clone = server.clone();
|
||||
let server_clone = Arc::clone(&server);
|
||||
tokio::spawn(async move {
|
||||
let _ = s_clone.handle(stream).await;
|
||||
let _ = Server::handle(server_clone, stream).await;
|
||||
});
|
||||
}
|
||||
Err(_e) => break,
|
||||
|
Reference in New Issue
Block a user