- 
                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