#Connecting to postgresql_embedded from a sidecar (or the host in general)

5 messages · Page 1 of 1 (latest)

smoky swallow
#

My goal: Launch Postgres (via postgresql_embedded) inside tauri::Builder.setup, and connect to it either from a sidecar or the host (e.g., with psql).

How I've succeeded so far:
I can initialize postgres outside of the tauri::Builder chain and then connect to it from a Tauri sidecar or psql.

Where I'm stuck:
When I put Postgres initialization inside tauri::Builder.setup, I am able to interact with it (e.g., using sqlx) inside my Tauri app, but not from a sidecar or the host. I would like to start it inside setup because I access some app configuration properties during Postgres initialization. The database URL that I pass to either the sidecar or psql for testing looks like this: postgresql://postgres:REDACTED@localhost:40255/postgres

smoky swallow
#

My current workaround is this:

#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

mod database;
mod util;

use postgresql_embedded::PostgreSQL;
use std::env;
use tauri::{
    api::process::{Command, CommandEvent},
    App as TauriApp, Manager,
};
use tauri_plugin_log::LogTarget;

struct PgConnection {
    db: Option<PostgreSQL>,
}

fn set_up_tauri_app(app: &mut TauriApp) -> Result<(), Box<dyn std::error::Error>> {
    if let Some(db) = &app.state::<PgConnection>().db {
        let (mut rx, mut child) = Command::new_sidecar("nodejs-app")
            .expect("Failed to create `nodejs-app` binary command")
            .args([
                "--database-url",
                &db.settings().url(database::DATABASE_NAME),
            ])
            .spawn()
            .expect("Failed to spawn nodejs-app");

        // sidecar logging code truncated to satisfy Discord message length limit
    } else {
        panic!("Cannot access database.");
    }

    Ok(())
}

fn main() {
    let tauri_ctx = tauri::generate_context!();
    let project_directories = util::project_directories(tauri_ctx.config().clone())
        .expect("Unable to determine project directories");
    let postgres = database::start_postgres(project_directories.clone()).unwrap();

    tauri::Builder::default()
        .manage(PgConnection { db: Some(postgres) })
        .plugin(
            tauri_plugin_log::Builder::default()
                .targets([LogTarget::LogDir, LogTarget::Stdout])
                .build(),
        )
        .setup(set_up_tauri_app)
        .run(tauri_ctx)
        .expect("error while running app");
}

This allows me to access Postgres externally because its initialization happens outside of the tauri::Builder code (as opposed to inside set_up_tauri_app), but I think the downside is now that I cannot stop/start Postgres from within the app.

tawny flax
#

but I think the downside is now that I cannot stop/start Postgres from within the app.
Why not? (genuine question, i think i'm missing something)

smoky swallow
#

The problem I'm anticipating, if I do try to stop/restart Postgres from the app, is that I also still won't be able to connect to Postgres from a sidecar. I haven't verified this yet.

Here's an example of how I'm trying to start Postgres during setup but, unlike the previous code example, now I can't connect to Postgres from outside of the Tauri app.

fn set_up_tauri_app<'a>(app: &'a mut TauriApp) -> Result<(), Box<dyn std::error::Error>> {
    let handle = app.handle();

    match tauri::async_runtime::block_on(async {
        let pg_settings = database::settings(handle.clone()).unwrap();
        database::initialize_postgres(handle, pg_settings).await
    }) {
        Ok(pg) => app.manage(database::PgConnection {
            db: Some(pg.clone()),
            settings: Some(pg.settings().clone()),
        }),
        Err(e) => panic!("Cannot start database: {e:?}"),
    };

    if let Some(db) = &app.state::<PgConnection>().db {
        let (mut rx, mut child) = Command::new_sidecar("nodejs-app")
            .expect("Failed to create `nodejs-app` binary command")
            .args([
                "--database-url",
                &db.settings().url(database::DATABASE_NAME),
            ])
            .spawn()
            .expect("Failed to spawn nodejs-app");

        // sidecar logging code truncated to satisfy Discord message length limit
    } else {
        panic!("Cannot access database.");
    }

    Ok(())
}

fn main() {
    tauri::Builder::default()
        .manage(database::PgConnection {
            db: Default::default(),
            settings: Default::default(),
        })
        .plugin(
            tauri_plugin_log::Builder::default()
                .targets([LogTarget::LogDir, LogTarget::Stdout])
                .build(),
        )
        .setup(set_up_tauri_app)
        .run(tauri::generate_context!())
        .expect("error while running Ambient Node");
}
#

I think getting this to work blocks me from testing stopping/restarting Postgres.