#Having issues setting up the database in Tauri

14 messages · Page 1 of 1 (latest)

mint merlin
#

I'm migrating to Tauri and coming across an error while setting up the database within tauri::Builder.
This is the error I get: thread 'main' panicked at /home/user/.cargo/registry/src/index.crates.io-6er47d384he001f/tokio-1.43.0/src/runtime/scheduler/multi_thread/mod.rs:86:9:
Cannot start a runtime from within a runtime. This happens because a function (like block_on) attempted to block the current thread while the thread is being used to drive asynchronous tasks.
Should I jsut remove tokio::main or just set up the database differently? Appreciate the help. I also included main.rs which has the full code

tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![])
        .setup(move |app| {
            tauri::async_runtime::block_on(async move { //This gives me an error
                let db = setup_db(&app).await;
                app.manage(AppState { db });
            });

            tauri::async_runtime::spawn(async move { axum::serve(listener, start_app) });
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("Error while running tauri application");
lean venture
#

Should I jsut remove tokio::main or just set up the database differently?
where do you even use this? i don't see it in your code. Generally though, if you use tauri::async_runtime there's rarely a need for tokio::main. If there is for some reason, you need to give tauri a handle to your runtime via https://docs.rs/tauri/latest/tauri/async_runtime/fn.set.html

mint merlin
#

It's jsut above the main function

lean venture
#

ah lol, i missed the 53 lines left part of the preview

#

but what i said still stands. if you want to use tokio::main for that one await line instead of async_runtime you'll need to use set

dusky dust
#

I have some Tauri apps where I do something very similar to what you're doing: spawn an Axum server and a database connection at app startup. What I usually do is start Tauri as usual, and then spawn regular os threads inside the setup function. In each of these threads, I call async_runtime::block_on to start both Axum and the database.

mint merlin
mint merlin
# dusky dust no async

Something like this? ```rust
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![])
.setup(move |app| {
std::thread::scope(|app_threads| {
app_threads.spawn(|| {
tauri::async_runtime::block_on(async move {
let db = setup_db(&app).await;
app.manage(AppState { db });
});
});
app_threads.spawn(|| {
tauri::async_runtime::block_on(async move {
setup_app(&app).await;
})
})
})
.join()
.unwrap();

        tauri::async_runtime::spawn(async move {
        
        });
        Ok(())
    })
    .run(tauri::generate_context!())
    .expect("Error while running tauri application");
#

Also, did you wrap the db in an Arc, Mutex, or tauri::State?

#

Thanks for the help btw

dusky dust
#

Hm, not exactly. I was thinking something more like this:

pub fn run() {
    tauri::Builder::default()
        .setup(|_| {
            tauri::async_runtime::spawn(async move {
                example1().await;
            });

            std::thread::spawn(move || {
                tauri::async_runtime::block_on(async move {
                    example2().await;
                });
            });

            Ok(())
        })
        .run(tauri::generate_context!())
        .unwrap();
}

But we might be overthinking it. Try using only normal tasks without a tokio::main. I realize now that I may have confused you more than helped, sorry.

Also, did you wrap the db in an Arc, Mutex, or tauri::State?
Those are not mutually exclusive. State is used to retrieve what is being managed by Tauri. Arc allows for shared ownership, while Mutex provides interior mutability.

Let's say we have a type called Foo. I want to eventually use the same instance of Foo across various tasks, but there's no need to mutate it. In this scenario, Arc could be useful. Now, consider Bar. I also want to pass Bar around different tasks, but I need it to be mutable. In that case, I should wrap it in both a Mutex and an Arc (like Arc<Mutex<Bar>>).

In my specific use case, I always use Diesel, which is synchronous. So I spawn it in a dedicated thread and communicate with it using channels (actor pattern). Since only the channel sender needs to be managed by Tauri, neither Arc nor Mutex is required.

mint merlin
# dusky dust Hm, not exactly. I was thinking something more like this: ```rust pub fn run() ...

No problem bro. I appreciate you taking your time to help me out. Just one more question. To set up the app and database I used an async function with &tauri::App. Here's what they look like: async fn setup_app(app: &tauri::App) -> Result<(), Box<dyn std::error::Error>> {...} and async fn setup_db(app: &tauri::App) -> Db. But since I'm using threads should I use AppHandle instead?