-
Notifications
You must be signed in to change notification settings - Fork 77
Open
Description
I'm planning to write the equivalent of webdis, but implemented in rust as a dynamic module.
Here is a tiny example that seems to work just fine. I'd love to hear your thoughts on the drawbacks of this approach.
Expand to see the Code:
use axum::{routing::get, Router};
use lazy_static::lazy_static;
use redis_module::{redis_module, Context, RedisString, Status, ThreadSafeContext};
use tokio::sync::oneshot;
use std::{
sync::Mutex,
thread::{self, JoinHandle},
};
lazy_static! {
static ref SERVER_THREAD: Mutex<Option<ServerHandle>> = Mutex::new(None);
}
struct ServerHandle {
handle: JoinHandle<()>,
shutdown_tx: oneshot::Sender<()>,
}
fn init(_ctx: &Context, _args: &[RedisString]) -> Status {
let (shutdown_tx, shutdown_rx) = oneshot::channel::<()>();
let handle = thread::spawn(move || {
let runtime = tokio::runtime::Runtime::new().unwrap();
runtime.block_on(async {
let app = Router::new().route("/", get(root));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app)
.with_graceful_shutdown(async {
shutdown_rx.await.unwrap();
})
.await
.unwrap();
});
});
let mut server_thread = SERVER_THREAD.lock().unwrap();
*server_thread = Some(ServerHandle {
handle,
shutdown_tx,
});
Status::Ok
}
fn deinit(_ctx: &Context) -> Status {
let mut server_thread = SERVER_THREAD.lock().unwrap();
if let Some(ServerHandle {
shutdown_tx,
handle,
}) = server_thread.take()
{
let _ = shutdown_tx.send(());
handle.join().unwrap();
}
Status::Ok
}
async fn root() -> String {
let ctx = ThreadSafeContext::new();
let version = ctx.lock().get_redis_version().unwrap();
format!("{}.{}.{}", version.major, version.minor, version.patch)
}
//////////////////////////////////////////////////////
redis_module! {
name: "hello",
version: 1,
allocator: (redis_module::alloc::RedisAlloc, redis_module::alloc::RedisAlloc),
data_types: [],
init: init,
deinit: deinit,
commands: [
],
}I'm able to LOAD and UNLOAD the module.
127.0.0.1:6379> MODULE LOAD /Users/user/axredis/target/release/libaxredis.dylib
OK
127.0.0.1:6379> MODULE UNLOAD hello
OK
While the module is loaded, I can get the redis/valkey version over HTTP.
$ curl 127.0.0.1:3000
8.0.1
Metadata
Metadata
Assignees
Labels
No labels