What is the best practice to handle a data-base-connection-pool in Iced.rs?

I am building an ‘iced+sqlx’-app, which needs connections to a postgres db. Normally I would create a connection in main and pass it along as an argument to helper sql functions.

#[tokio::main]
async fn main() -> Result<(), IcedError> {
    // we need to activate the db pool
    let pool = PgPool::connect("postgres://alex:1234@localhost/kedoiced")
        .await
        .unwrap();
    //
    //
    iced::application("Experiment", Keto::update, Keto::view)
        .theme(Keto::theme)
        .run_with(Keto::new)
}

But I see no way to pass it along to the iced application?

The only solution I see now is to create a separate connection to the database in each async helper function, which handles sql. And just call it from Task::perform(… ).

 pub async fn save(&self) -> Result<uuid::Uuid, anyhow::Error> {
        let pool = PgPool::connect("postgres://alex:1234@localhost/ketoiced")
            .await
            .unwrap();
        let rec = sqlx::query!(
            r#"
INSERT INTO "macro_food"(name, protein, carbohydrates, fat, weight, kcalories)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING macro_id
"#,
            self.name,
            self.protein,
            self.carbohydrates,
            self.fat,
            self.weight,
            self.kcalories
        )
        .fetch_one(&pool)
        .await?;
        Ok(rec.macro_id)
    }

Is this the only way?

I would appreciate any help in this regard. I am still learning Rust/Iced/… but I can’t find any documentation specific to this.

Try storing it in your state, wrapped in an Arc.

1 Like

On my app, I use iced::application(...).run_with(App::new) and the task in the tupple execute a function

fn new() -> (Self, Task<Message>) {
        (
            Self {
                pool: None,
            },
            Task::perform(database::connect(), Message::Loaded),
        )
    }

pub async fn connect() -> Result<PgPool, Error> { ... }

fn update(&mut self, message: Message) -> Task<Message> {
        match message {
            Message::Loaded(Ok(pool)) => {
                self.pool = Some(pool);
                ...
            }
      ...
}
1 Like

Right, but the type of your App.pool field should be Option<Arc<PgPool>> instead of Option<PgPool>. That way, you can share references of the same pool to every async task, keeping in mind that reference-counted references are not completely equal to normal shares.

1 Like

Thank you @mytdragon ! Will try immediately:).