I'm currently developing an app where it is necessary for the frontend to communicate with a PostgreSQL database. I'm using the postgres
package to do the PostgreSQL work on the Rust side.
Since I'm using Tauri here, I was building commands to create the connection and delivering data to the user when it's requested.
My problem here is, that I cannot share the PostgreSQL Client between the commands. I know that there is some sort of tauri::State
but that cannot handle the client.
Is there a way to share the postgres::Client
instance between multiple commands?
My current code looks something like this:
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use postgres::Client;
struct ClientState(Option<Client>);
#[tauri::command]
fn connect(client_state: tauri::State<ClientState>) { ... }
fn main() {
tauri::Builder::default()
.manage(ClientState(None))
.invoke_handler(tauri::generate_handler![connect])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
I want the code to share the instance of the client
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use postgres::Client;
struct ClientState(Option<Client>);
#[tauri::command]
fn connect(client_state: tauri::State<ClientState>) {
// initialize the client
}
#[tauri::command]
fn exists_user(id: &str, client_state: tauri::State<ClientState>) -> bool {
// check if a user with the given id exists for example
}
fn main() {
tauri::Builder::default()
.manage(ClientState(None))
.invoke_handler(tauri::generate_handler![connect, exists_user])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
Hopefully I am not too late for your use-case. I am building the exact same pattern that you are, and I had the same problem. I indeed ended up using
tauri::State
.Firstly, my original application uses
sqlx::PgConnection
and a bunch of async stuff, but I tested withpostgres
and it should actually end up simpler.After much trial and error, I now instantiate my global structs like this:
Afterwards, you can use your client like this:
Of course, this doesn't work without initialization. I prefer to not actually initialize the connection at start up, but use a separate function to do it.
I use
core::default
for setting default values in.manage()
, that will never be used, but are useful for going on with the initialization:and then in a function, that is actually another tauri command:
I wrote all this in my app, to see if it works, and it connected correctly, but I didn't test any actual sql. You can see my app here, for further inspiration.