edgedb / edgedb-rust

The official Rust binding for EdgeDB
https://edgedb.com
Apache License 2.0
215 stars 26 forks source link

the trait `std::marker::Sync` is not implemented for `dyn StdError` error when using transactions inside `tokio::spawn` #227

Closed westernwontons closed 1 year ago

westernwontons commented 1 year ago

Describe the bug A clear and concise description of what the bug is. Axum application, State has a Database that uses the edgedb_tokio::Client. Running a transaction causes a compile error: the trait std::marker::Sync is not implemented for dyn StdError

Reproduction

pub struct Database {
    client: Client
}
// self refers to a Database instance

         let result = self
            .client
            .clone()
            .transaction(|mut tx| async move {
                let customer = tx
                    .query_required_single::<String, _>(
                        r#"
                        insert Customer {
                            customer_id := $customer_id,
                            name := $name
                        };
                        "#,
                        customer_params
                    )
                    .await;
                let address = tx
                    .query_required_single::<String, _>(
                        r#"
                        update Customer
                        filter .customer_id := $customer_id
                        set {
                            address := (
                                insert Address {
                                    county := $county,
                                    street := $street,
                                    number := $number,
                                    additional := $additional
                                }
                            )
                        };
                        "#,
                        address_params
                    )
                    .await;
                let appliance = tx
                    .query_required_single::<String, _>(
                        r#"
                        update Customer
                        filter .customer_id = $customer_id
                        set {
                            appliance := (
                                insert Appliance {
                                    manufacturer := $manufacturer,
                                    year_of_manufacture := $year_of_manufacture,
                                    model := $model,
                                    type := $type,
                                    warranty := $warranty,
                                    operation_performed := $operation_performed,
                                    number := $number,
                                    date := $date,
                                    expiration_date := $expiration_date
                                }
                            )
                        };
                        "#,
                        appliance_params
                    )
                    .await;
                customer
            })
            .await;

Expected behavior I expect to be able to run transactions inside a tokio task.

Versions (please complete the following information):

Additional context This is the entire error copied from the terminal:

RUST_LOG="tower_http=info" cargo run
   Compiling delivery-backend v0.0.0 (.../delivery-srl/delivery-backend)
error: future cannot be sent between threads safely
   --> src/routes/customer.rs:22:22
    |
22  |         tokio::spawn(async move { db.create_customer(customer).await })
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
    |
    = help: the trait `std::marker::Sync` is not implemented for `dyn StdError`
note: future is not `Send` as this value is used across an await
   --> .../cargo/registry/src/index.crates.io-6f17d22bba15001f/edgedb-tokio-0.3.0/src/transaction.rs:93:21
    |
    = note: has type `&dyn StdError` which is not `Send`
   ::: .../.cargo/registry/src/index.crates.io-6f17d22bba15001f/edgedb-tokio-0.3.0/src/transaction.rs:101:65
    |
    = note: await occurs here, with the value maybe used later
   ::: .../.cargo/registry/src/index.crates.io-6f17d22bba15001f/edgedb-tokio-0.3.0/src/transaction.rs:106:17
    |
    = note: the value is later dropped here
note: required by a bound in `tokio::spawn`
   --> .../.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.26.0/src/task/spawn.rs:163:21
    |
163 |         T: Future + Send + 'static,
    |                     ^^^^ required by this bound in `spawn`

error: could not compile `delivery-backend` (lib) due to 2 previous errors
error: Recipe `run` failed on line 5 with exit code 101
tailhook commented 1 year ago

Fixed in #199