Search code examples
databaserustunsafesurrealdb

Rust store DB connection globally


I want to use surrealdb in my rust code without needing a static mut (unsafe code) and without creating a new connection for everything. For example, using static mut:

static mut db: Option<Surreal> = None

#[tokio::main]
async fn main() {
  unsafe {db = Surreal::new("0.0.0.0:8080")}
  unsafe { db.as_ref() }.get("user", "whynotdogie")
  unsafe { db.as_ref() }.create::<User>("nothendev")
}

And connecting every time speaks for itself. Is there any way to do this without unsafe code or creating a new connection every time?

I tried with static muts, but i need unsafe, and i tried connecting every time, but i dont think that is very performant and i think it uses a lot of bandwidth.


Solution

  • Do not write this code. It is highly unidiomatic and very dangerous. If you need some globally visible state consider using something like Once cell. And don't forget to wrap your type in some sort of synchronization primitive such as Mutex if you want to mutate it from different threads.

    For example:

    use std::sync::Mutex;
    use once_cell::sync::Lazy;
    
    static GLOBAL_CONNECTION: Lazy<Mutex<Surreal>> = Lazy::new(|| {
        let db = Surreal::new("0.0.0.0:8080");
        Mutex::new(db)
    });
    
    fn main() {
        // Use here db
        GLOBAL_CONNECTION.lock().unwrap()...
    }
    

    This will initialize GLOBAL_CONNECTION the first time you use it, and after that you will be able to access it.

    However consider simpler and more idiomatic approach to just pass your database connection as a part of your program's state. For example

    use std::sync::{Arc, Mutex};
    
    fn main() {
        let connection = Arc::new(Mutex::new(Surreal::new("0.0.0.0:8080")));
    
        // pass this to functions that need db connection
    }