1

I am attempting to use Tokio-Diesel to use async/await with my ORM. I am not able to use Diesel's belonging_to associations, as it complains that I need a static lifetime. I've tried async blocks but nothing changes the lifetime error.

Cargo.toml

[package]
name = "tokio_diesel"
version = "0.1.0"
authors = ["servonlewis"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
diesel = { version = "1.4.3", features = ["postgres", "r2d2", "serde_json", "chrono", "uuid"] }
r2d2 = "0.8.8"
tokio = { version = "0.2", features = ["full"] }
tokio-diesel = "0.3.0"
uuid = { version = "0.6.5", features = ["serde", "v4"] }

main.rs

#[macro_use]
extern crate diesel;
use diesel::prelude::*;
use tokio_diesel::*;

table! {
    articles (id) {
        id -> Integer,
        title -> Text,
    }
}

table! {
    articles_visible_to_groups (id) {
        id -> Integer,
        article_id -> Integer,
        groups_id -> Integer,
    }
}

table! {
    groups (id) {
        id -> Integer,
        name -> Varchar,
    }
}

joinable!(articles_visible_to_groups -> articles (article_id));
joinable!(articles_visible_to_groups -> groups (groups_id));

allow_tables_to_appear_in_same_query!(articles, articles_visible_to_groups, groups,);

use crate::articles::dsl::*;
use crate::groups::dsl::*;
use diesel::pg::PgConnection;
use diesel::r2d2::{ConnectionManager, Pool};

pub type PostgresPool = Pool<ConnectionManager<PgConnection>>;

pub fn get_pool() -> PostgresPool {
    let url = "postgres://actix:actix@localhost:5432/actix".to_string();
    let mgr = ConnectionManager::<PgConnection>::new(url);
    r2d2::Pool::builder()
        .build(mgr)
        .expect("could not build connection pool")
}

#[derive(Queryable, Identifiable, Associations, Debug)]
#[table_name = "articles"]
pub struct Article {
    pub id: i32,
    pub title: String,
}

#[derive(Identifiable, Queryable, Associations, Debug, PartialEq)]
#[belongs_to(Group, foreign_key = "groups_id")]
#[belongs_to(Article)]
#[table_name = "articles_visible_to_groups"]
pub struct ArticleVisibleToGroup {
    pub id: i32,
    pub article_id: i32,
    pub groups_id: i32,
}

#[derive(Queryable, Identifiable, Associations, Debug, PartialEq)]
pub struct Group {
    pub id: i32,
    pub name: String,
}

pub async fn groups_who_can_see(conn: &PostgresPool, an_id: i32) -> Vec<Group> {
    use diesel::pg::expression::dsl::any;

    let record = articles
        .find(an_id)
        .load_async::<Article>(conn)
        .await
        .unwrap();

    let list = ArticleVisibleToGroup::belonging_to(&record)
        .select(articles_visible_to_groups::groups_id)
        .load_async::<i32>(conn)
        .await
        .unwrap();

    groups
        .filter(groups::id.eq_all(any(list)))
        .load_async::<Group>(conn)
        .await
        .unwrap()
}

#[tokio::main]
async fn main() {
    println!("Hello, world!");
    // pool.get_ref().to_owned(),

    let pool = get_pool();
    let res = groups_who_can_see(&pool, 1).await;

    println!("{:#?}", res);
}
error[E0597]: `record` does not live long enough
  --> src/main.rs:80:52
   |
80 |     let list = ArticleVisibleToGroup::belonging_to(&record)
   |                ------------------------------------^^^^^^^-
   |                |                                   |
   |                |                                   borrowed value does not live long enough
   |                argument requires that `record` is borrowed for `'static`
...
91 | }
   | - `record` dropped here while still borrowed
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
TheServ
  • 21
  • 4
  • Pretty sure this will be [a limitation of tokio-diesel](https://docs.rs/tokio-diesel/0.3.0/tokio_diesel/trait.AsyncRunQueryDsl.html#tymethod.load_async), which has some `'static` bounds on it. – Shepmaster Aug 05 '20 at 12:56
  • Can you explain that a little please? – TheServ Aug 05 '20 at 13:11
  • I’m wondering if I should use blocking code for these belonging to functions and have the rest be async. Would be weird but do I have a choice? – TheServ Aug 05 '20 at 13:13
  • I do see that belonging to asks for ‘a Parent but Tokio-diesel returns ‘static result. I guess I may need to try something else ? – TheServ Aug 05 '20 at 13:29

1 Answers1

1

Looks like i was able to get around this issue by just not using belonging_to and instead using filter.

Instead of the example above, this one works asyncronously.

    pub async fn groups_who_can_see(
        conn: &PostgresPool,
        an_id: String,
    ) -> FieldResult<Vec<Group>> {
        use diesel::pg::expression::dsl::any;
        let my_id = uuid::Uuid::parse_str(&an_id)?;

        let list = articles_visible_to_groups
            .filter(article_id.eq_all(my_id))
            .select(articles_visible_to_groups::groups_id)
            .load_async::<uuid::Uuid>(&conn)
            .await?;

        let data = groups
            .filter(groups::id.eq_all(any(list)))
            .load_async::<Group>(&conn)
            .await;

        graphql_translate(data)
    }
TheServ
  • 21
  • 4