---- Update ----
Change to std-futures
branch, but not works...
---- Origin ----
Hi, I found that async-trait
macro will throw dyn tokio_postgres::types::ToSql cannot be shared between threads safely
when I use tokio-postgres
with it together. A demo behind:
Dependencies:
[dependencies]
futures-preview = { version = "=0.3.0-alpha.18", features = ["async-await", "nightly"] }
async-trait = "~0.1.13"
tokio-postgres = { git = "https://github.com/sfackler/rust-postgres", branch="std-futures", features = ["with-uuid-0_7", "with-chrono-0_4", "with-serde_json-1"] }
tokio = "=0.2.0-alpha.4"
extern crate async_trait;
use async_trait::async_trait;
use tokio_postgres::{Client, NoTls, Row};
use futures::{FutureExt, TryStreamExt};
use std::error::Error;
pub struct Thing<'a>(pub &'a str);
#[async_trait]
pub trait Repository {
async fn get_by_id() -> Option<()>;
}
pub struct RealRepo();
#[async_trait]
impl <'a> Repository for RealRepo {
async fn get_by_id() -> Option<()> {
let (mut client, conn) = tokio_postgres::connect("postgres://postgres@localhost", NoTls).await.ok()?;
let conn = conn.map(|r| {
if let Err(e) = r {
eprintln!("connection error: {}", e);
}
});
tokio::spawn(conn);
let stmt = client.prepare("SELECT * FROM blogs").await.ok()?;
let res: Vec<&'a str> = client
.query(&stmt, &[])
.map_ok(|row: Row| row.get::<usize, &'a str>(0))
.try_collect()
.await
.ok()?;
Some(())
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let thing = RealRepo::get_by_id().await;
Ok(())
}
The Error info:
error[E0277]: `dyn tokio_postgres::types::ToSql` cannot be shared between threads safely
--> src\main.rs:18:1
|
18 | #[async_trait]
| ^^^^^^^^^^^^^^ `dyn tokio_postgres::types::ToSql` cannot be shared between threads safely
|
= help: the trait `std::marker::Sync` is not implemented for `dyn tokio_postgres::types::ToSql`
= note: required because of the requirements on the impl of `std::marker::Send` for `&dyn tokio_postgres::types::ToSql`
= note: required because it appears within the type `[&dyn tokio_postgres::types::ToSql; 0]`
= note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7, 't8, 't9, 't10, 't11, 't12, 't13, 't14, 't15, 't16, 't17, 't18, 't19, 't20, 't21, 't22, 't23, 't24, 't25, 't26, 't27, 't28, 't29> {f
n(std::option::Option<(tokio_postgres::client::Client, tokio_postgres::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>)>) -> std::result::Result<<std::option::Option<(tokio_postgres::client::Client,
tokio_postgres::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>)> as std::ops::Try>::Ok, <std::option::Option<(tokio_postgres::client::Client, tokio_postgres::connection::Connection<tokio_postgres::s
ocket::Socket, tokio_postgres::tls::NoTlsStream>)> as std::ops::Try>::Error> {<std::option::Option<(tokio_postgres::client::Client, tokio_postgres::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>)> a
s std::ops::Try>::into_result}, for<'_> fn(&str, tokio_postgres::tls::NoTls) -> impl core::future::future::Future {tokio_postgres::connect::<tokio_postgres::tls::NoTls>}, &'r str, str, &'s str, tokio_postgres::tls::NoTls, impl core::future:
:future::Future, impl core::future::future::Future, (), tokio_postgres::client::Client, tokio_postgres::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>, futures_util::future::map::Map<tokio_postgres:
:connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>, [closure@src\main.rs:22:29: 26:10]>, fn(std::option::Option<tokio_postgres::statement::Statement>) -> std::result::Result<<std::option::Option<tokio_
postgres::statement::Statement> as std::ops::Try>::Ok, <std::option::Option<tokio_postgres::statement::Statement> as std::ops::Try>::Error> {<std::option::Option<tokio_postgres::statement::Statement> as std::ops::Try>::into_result}, &'t3 mu
t tokio_postgres::client::Client, &'t4 str, impl core::future::future::Future, tokio_postgres::statement::Statement, fn(std::option::Option<std::vec::Vec<&'t5 str>>) -> std::result::Result<<std::option::Option<std::vec::Vec<&'t5 str>> as st
d::ops::Try>::Ok, <std::option::Option<std::vec::Vec<&'t5 str>> as std::ops::Try>::Error> {<std::option::Option<std::vec::Vec<&'t5 str>> as std::ops::Try>::into_result}, &'t6 mut tokio_postgres::client::Client, &'t7 tokio_postgres::statemen
t::Statement, &'t8 tokio_postgres::statement::Statement, [&'t9 (dyn tokio_postgres::types::ToSql + 't10); 0], &'t11 [&'t12 (dyn tokio_postgres::types::ToSql + 't13); 0], &'t14 [&'t15 (dyn tokio_postgres::types::ToSql + 't16); 0], &'t17 [&'t
18 (dyn tokio_postgres::types::ToSql + 't19)], impl futures_core::stream::Stream, [closure@src\main.rs:33:21: 33:60], futures_util::try_stream::map_ok::MapOk<impl futures_core::stream::Stream, [closure@src\main.rs:33:21: 33:60]>, futures_ut
il::try_stream::try_collect::TryCollect<futures_util::try_stream::map_ok::MapOk<impl futures_core::stream::Stream, [closure@src\main.rs:33:21: 33:60]>, std::vec::Vec<&'t26 str>>, futures_util::try_stream::try_collect::TryCollect<futures_uti
l::try_stream::map_ok::MapOk<impl futures_core::stream::Stream, [closure@src\main.rs:33:21: 33:60]>, std::vec::Vec<&'t29 str>>}`
= note: required because it appears within the type `[static generator@src\main.rs:20:40: 39:6 for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7, 't8, 't9, 't10, 't11, 't12, 't13, 't14, 't15, 't16, 't17, 't18, 't19, 't20, 't21, 't22, 't
23, 't24, 't25, 't26, 't27, 't28, 't29> {fn(std::option::Option<(tokio_postgres::client::Client, tokio_postgres::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>)>) -> std::result::Result<<std::option
::Option<(tokio_postgres::client::Client, tokio_postgres::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>)> as std::ops::Try>::Ok, <std::option::Option<(tokio_postgres::client::Client, tokio_postgres
::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>)> as std::ops::Try>::Error> {<std::option::Option<(tokio_postgres::client::Client, tokio_postgres::connection::Connection<tokio_postgres::socket::Soc
ket, tokio_postgres::tls::NoTlsStream>)> as std::ops::Try>::into_result}, for<'_> fn(&str, tokio_postgres::tls::NoTls) -> impl core::future::future::Future {tokio_postgres::connect::<tokio_postgres::tls::NoTls>}, &'r str, str, &'s str, toki
o_postgres::tls::NoTls, impl core::future::future::Future, impl core::future::future::Future, (), tokio_postgres::client::Client, tokio_postgres::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>, futu
res_util::future::map::Map<tokio_postgres::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>, [closure@src\main.rs:22:29: 26:10]>, fn(std::option::Option<tokio_postgres::statement::Statement>) -> std::
result::Result<<std::option::Option<tokio_postgres::statement::Statement> as std::ops::Try>::Ok, <std::option::Option<tokio_postgres::statement::Statement> as std::ops::Try>::Error> {<std::option::Option<tokio_postgres::statement::Statement
> as std::ops::Try>::into_result}, &'t3 mut tokio_postgres::client::Client, &'t4 str, impl core::future::future::Future, tokio_postgres::statement::Statement, fn(std::option::Option<std::vec::Vec<&'t5 str>>) -> std::result::Result<<std::opt
ion::Option<std::vec::Vec<&'t5 str>> as std::ops::Try>::Ok, <std::option::Option<std::vec::Vec<&'t5 str>> as std::ops::Try>::Error> {<std::option::Option<std::vec::Vec<&'t5 str>> as std::ops::Try>::into_result}, &'t6 mut tokio_postgres::cli
ent::Client, &'t7 tokio_postgres::statement::Statement, &'t8 tokio_postgres::statement::Statement, [&'t9 (dyn tokio_postgres::types::ToSql + 't10); 0], &'t11 [&'t12 (dyn tokio_postgres::types::ToSql + 't13); 0], &'t14 [&'t15 (dyn tokio_post
gres::types::ToSql + 't16); 0], &'t17 [&'t18 (dyn tokio_postgres::types::ToSql + 't19)], impl futures_core::stream::Stream, [closure@src\main.rs:33:21: 33:60], futures_util::try_stream::map_ok::MapOk<impl futures_core::stream::Stream, [clos
ure@src\main.rs:33:21: 33:60]>, futures_util::try_stream::try_collect::TryCollect<futures_util::try_stream::map_ok::MapOk<impl futures_core::stream::Stream, [closure@src\main.rs:33:21: 33:60]>, std::vec::Vec<&'t26 str>>, futures_util::try_s
tream::try_collect::TryCollect<futures_util::try_stream::map_ok::MapOk<impl futures_core::stream::Stream, [closure@src\main.rs:33:21: 33:60]>, std::vec::Vec<&'t29 str>>}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@src\main.rs:20:40: 39:6 for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7, 't8, 't9, 't10, 't11, 't12, 't13, 't14, 't15, 't16, 't17, 't18, 't1
9, 't20, 't21, 't22, 't23, 't24, 't25, 't26, 't27, 't28, 't29> {fn(std::option::Option<(tokio_postgres::client::Client, tokio_postgres::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>)>) -> std::resu
lt::Result<<std::option::Option<(tokio_postgres::client::Client, tokio_postgres::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>)> as std::ops::Try>::Ok, <std::option::Option<(tokio_postgres::client:
:Client, tokio_postgres::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>)> as std::ops::Try>::Error> {<std::option::Option<(tokio_postgres::client::Client, tokio_postgres::connection::Connection<toki
o_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>)> as std::ops::Try>::into_result}, for<'_> fn(&str, tokio_postgres::tls::NoTls) -> impl core::future::future::Future {tokio_postgres::connect::<tokio_postgres::tls::NoTls>}, &'r
str, str, &'s str, tokio_postgres::tls::NoTls, impl core::future::future::Future, impl core::future::future::Future, (), tokio_postgres::client::Client, tokio_postgres::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::
tls::NoTlsStream>, futures_util::future::map::Map<tokio_postgres::connection::Connection<tokio_postgres::socket::Socket, tokio_postgres::tls::NoTlsStream>, [closure@src\main.rs:22:29: 26:10]>, fn(std::option::Option<tokio_postgres::statemen
t::Statement>) -> std::result::Result<<std::option::Option<tokio_postgres::statement::Statement> as std::ops::Try>::Ok, <std::option::Option<tokio_postgres::statement::Statement> as std::ops::Try>::Error> {<std::option::Option<tokio_postgre
s::statement::Statement> as std::ops::Try>::into_result}, &'t3 mut tokio_postgres::client::Client, &'t4 str, impl core::future::future::Future, tokio_postgres::statement::Statement, fn(std::option::Option<std::vec::Vec<&'t5 str>>) -> std::r
esult::Result<<std::option::Option<std::vec::Vec<&'t5 str>> as std::ops::Try>::Ok, <std::option::Option<std::vec::Vec<&'t5 str>> as std::ops::Try>::Error> {<std::option::Option<std::vec::Vec<&'t5 str>> as std::ops::Try>::into_result}, &'t6
mut tokio_postgres::client::Client, &'t7 tokio_postgres::statement::Statement, &'t8 tokio_postgres::statement::Statement, [&'t9 (dyn tokio_postgres::types::ToSql + 't10); 0], &'t11 [&'t12 (dyn tokio_postgres::types::ToSql + 't13); 0], &'t14
[&'t15 (dyn tokio_postgres::types::ToSql + 't16); 0], &'t17 [&'t18 (dyn tokio_postgres::types::ToSql + 't19)], impl futures_core::stream::Stream, [closure@src\main.rs:33:21: 33:60], futures_util::try_stream::map_ok::MapOk<impl futures_core
::stream::Stream, [closure@src\main.rs:33:21: 33:60]>, futures_util::try_stream::try_collect::TryCollect<futures_util::try_stream::map_ok::MapOk<impl futures_core::stream::Stream, [closure@src\main.rs:33:21: 33:60]>, std::vec::Vec<&'t26 str
>>, futures_util::try_stream::try_collect::TryCollect<futures_util::try_stream::map_ok::MapOk<impl futures_core::stream::Stream, [closure@src\main.rs:33:21: 33:60]>, std::vec::Vec<&'t29 str>>}]>`
= note: required because it appears within the type `impl core::future::future::Future`
= note: required because it appears within the type `impl core::future::future::Future`
= note: required for the cast to the object type `dyn core::future::future::Future<Output = std::option::Option<()>> + std::marker::Send`