Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Having trouble using std::rc::Rc values within a Mutation object. #110

Closed
ruseinov opened this issue May 26, 2020 · 7 comments
Closed

Having trouble using std::rc::Rc values within a Mutation object. #110

ruseinov opened this issue May 26, 2020 · 7 comments

Comments

@ruseinov
Copy link
Contributor

Here's an example:

fn ipfs_client(ctx: &Context<'_>) -> Result<IpfsClient, InvalidUri> {
    let app_data = ctx.data::<AppData>();
    IpfsClient::from_str(&app_data.ipfs_url)
}
    async fn create_asset(
        &self,
        ctx: &Context<'_>,
        file: Upload,
    ) -> FieldResult<Asset> {

        if true {
            let reader = File::open(file.path)?;

            let ipfs_client = ipfs_client(ctx)?;

            let resp = ipfs_client.add(reader).await.map_err(|err| {
                ErrorKind::Fatal(format!("Failed to add a file to IPFS: {:?}", err))
            })?;

            ipfs_hash = resp.hash;
        }
}

The Object macro on MutationRoot

#[Object]
impl MutationRoot {

Would throw an error:

69  | #[Object]
    | ^^^^^^^^^ future returned by `__resolve_field` is not `Send`
    |
    = help: within `impl core::future::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<awc::ClientConfig>`

and also

   | `std::rc::Rc<std::cell::RefCell<actix_http::h1::payload::Inner>>` cannot be sent between threads safely

For the result of the add operation.

For the record: I'm not trying to pass the ipfs_client around, I instantiate it when it's needed, get a result and throw it away.

@ruseinov
Copy link
Contributor Author

I can't help but wonder why Rc is used there anyway as the library provides async api, I guess my best bet is to fork this and introduce an Arc instead. But if you have other suggestions - that'd be much appreciated!

@ruseinov
Copy link
Contributor Author

After digging deeper it seems like the library I mentioned is using awc::Client, which is always an Rc.

@sunli829
Copy link
Collaborator

Don't use awc, it is based on actix_rt, all its Future is !Send, because it is based on single-threaded runtime.

@sunli829
Copy link
Collaborator

I do not recommend the use of actix, which is incompatible with other asynchronous ecology.

@ruseinov
Copy link
Contributor Author

Yeah, I have figured as much. Learned the hard way:)

@ruseinov
Copy link
Contributor Author

I ended up using hyper, which works nicely with my actix-web runtime. Works like a charm now! I did not realize initially that the actix feature of the lib referred to actix actor framework.

@lastmjs
Copy link

lastmjs commented Apr 1, 2021

Hey, I'm running into a similar problem: Rc<RefCell<call::CallFutureState<std::vec::Vec<u8>>>> cannot be sent between threads safely. I'm developing for DFINITY's Internet Computer, which compiles to WebAssembly and thus (for now) is a single-threaded environment. I'm trying to use their ic_cdk::api::call::call function from within an async mutation resolver, and I'm getting all kinds of craziness. What should I do? Or what should I ask the implementers of ic-cdk to do? Here's a link to the ic-cdk crate: https://crates.io/crates/ic-cdk

Here is more error detail:

pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
   |                                           ------------------------------- within this `impl std::future::Future`
   |
   = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `Rc<RefCell<call::CallFutureState<std::vec::Vec<u8>>>>`
   = note: required because it appears within the type `call::CallFuture<std::vec::Vec<u8>>`
   = note: required because it appears within the type `impl std::future::Future`
   = note: required because it appears within the type `for<'r> {ResumeTy, sudograph::ic_cdk::export::Principal, &'r str, (), std::vec::Vec<u8>, i64, impl std::future::Future, ()}`
   = note: required because it appears within the type `[static generator@sudograph::ic_cdk::call<(), (std::vec::Vec<u8>,)>::{closure#0} for<'r> {ResumeTy, sudograph::ic_cdk::export::Principal, &'r str, (), std::vec::Vec<u8>, i64, impl std::future::Future, ()}]`
   = note: required because it appears within the type `from_generator::GenFuture<[static generator@sudograph::ic_cdk::call<(), (std::vec::Vec<u8>,)>::{closure#0} for<'r> {ResumeTy, sudograph::ic_cdk::export::Principal, &'r str, (), std::vec::Vec<u8>, i64, impl std::future::Future, ()}]>`
   = note: required because it appears within the type `impl std::future::Future`
   = note: required because it appears within the type `impl std::future::Future`
   = note: required because it appears within the type `for<'r, 's> {ResumeTy, sudograph::ic_cdk::export::Principal, &'r str, (), impl std::future::Future}`
   = note: required because it appears within the type `[static generator@canisters/graphql/src/graphql.rs:8:1: 8:59 for<'r, 's> {ResumeTy, sudograph::ic_cdk::export::Principal, &'r str, (), impl std::future::Future}]`
   = note: required because it appears within the type `for<'r, 's, 't0, 't1> {ResumeTy, &'r MutationGenerated, &'s ContextBase<'t0, &'t1 Positioned<sudograph::async_graphql::async_graphql_parser::types::Field>>, [static generator@canisters/graphql/src/graphql.rs:8:1: 8:59 for<'t2, 't3> {ResumeTy, sudograph::ic_cdk::export::Principal, &'t2 str, (), impl std::future::Future}], impl std::future::Future, ()}`
   = note: required because it appears within the type `[static generator@canisters/graphql/src/graphql.rs:8:1: 8:59 for<'r, 's, 't0, 't1> {ResumeTy, &'r MutationGenerated, &'s ContextBase<'t0, &'t1 Positioned<sudograph::async_graphql::async_graphql_parser::types::Field>>, [static generator@canisters/graphql/src/graphql.rs:8:1: 8:59 for<'t2, 't3> {ResumeTy, sudograph::ic_cdk::export::Principal, &'t2 str, (), impl std::future::Future}], impl std::future::Future, ()}]`
   = note: required because it appears within the type `from_generator::GenFuture<[static generator@canisters/graphql/src/graphql.rs:8:1: 8:59 for<'r, 's, 't0, 't1> {ResumeTy, &'r MutationGenerated, &'s ContextBase<'t0, &'t1 Positioned<sudograph::async_graphql::async_graphql_parser::types::Field>>, [static generator@canisters/graphql/src/graphql.rs:8:1: 8:59 for<'t2, 't3> {ResumeTy, sudograph::ic_cdk::export::Principal, &'t2 str, (), impl std::future::Future}], impl std::future::Future, ()}]>`
   = note: required because it appears within the type `impl std::future::Future`
   = note: required because it appears within the type `impl std::future::Future`
   = 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, 't30, 't31, 't32, 't33, 't34, 't35, 't36, 't37, 't38, 't39, 't40> {ResumeTy, &'r MutationGenerated, &'s ContextBase<'t0, &'t1 Positioned<sudograph::async_graphql::async_graphql_parser::types::Field>>, bool, ContextBase<'t2, &'t3 Positioned<SelectionSet>>, impl std::future::Future, (), &'t7 bool, &'t8 ContextBase<'t9, &'t10 Positioned<SelectionSet>>, ContextBase<'t11, &'t12 Positioned<sudograph::async_graphql::async_graphql_parser::types::Field>>, &'t13 Positioned<sudograph::async_graphql::async_graphql_parser::types::Field>, Pin<Box<(dyn std::future::Future<Output = std::result::Result<sudograph::async_graphql::Value, ServerError>> + std::marker::Send + 't14)>>, [closure@canisters/graphql/src/graphql.rs:8:1: 8:59], UpdateBlogPostInput, impl std::future::Future, std::vec::Vec<BlogPost>, &'t26 std::vec::Vec<BlogPost>, [closure@canisters/graphql/src/graphql.rs:8:1: 8:59], DeleteBlogPostInput, impl std::future::Future, impl std::future::Future}`
   = note: required because it appears within the type `[static generator@canisters/graphql/src/graphql.rs:8:1: 8:59 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, 't30, 't31, 't32, 't33, 't34, 't35, 't36, 't37, 't38, 't39, 't40> {ResumeTy, &'r MutationGenerated, &'s ContextBase<'t0, &'t1 Positioned<sudograph::async_graphql::async_graphql_parser::types::Field>>, bool, ContextBase<'t2, &'t3 Positioned<SelectionSet>>, impl std::future::Future, (), &'t7 bool, &'t8 ContextBase<'t9, &'t10 Positioned<SelectionSet>>, ContextBase<'t11, &'t12 Positioned<sudograph::async_graphql::async_graphql_parser::types::Field>>, &'t13 Positioned<sudograph::async_graphql::async_graphql_parser::types::Field>, Pin<Box<(dyn std::future::Future<Output = std::result::Result<sudograph::async_graphql::Value, ServerError>> + std::marker::Send + 't14)>>, [closure@canisters/graphql/src/graphql.rs:8:1: 8:59], UpdateBlogPostInput, impl std::future::Future, std::vec::Vec<BlogPost>, &'t26 std::vec::Vec<BlogPost>, [closure@canisters/graphql/src/graphql.rs:8:1: 8:59], DeleteBlogPostInput, impl std::future::Future, impl std::future::Future}]`
   = note: required because it appears within the type `from_generator::GenFuture<[static generator@canisters/graphql/src/graphql.rs:8:1: 8:59 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, 't30, 't31, 't32, 't33, 't34, 't35, 't36, 't37, 't38, 't39, 't40> {ResumeTy, &'r MutationGenerated, &'s ContextBase<'t0, &'t1 Positioned<sudograph::async_graphql::async_graphql_parser::types::Field>>, bool, ContextBase<'t2, &'t3 Positioned<SelectionSet>>, impl std::future::Future, (), &'t7 bool, &'t8 ContextBase<'t9, &'t10 Positioned<SelectionSet>>, ContextBase<'t11, &'t12 Positioned<sudograph::async_graphql::async_graphql_parser::types::Field>>, &'t13 Positioned<sudograph::async_graphql::async_graphql_parser::types::Field>, Pin<Box<(dyn std::future::Future<Output = std::result::Result<sudograph::async_graphql::Value, ServerError>> + std::marker::Send + 't14)>>, [closure@canisters/graphql/src/graphql.rs:8:1: 8:59], UpdateBlogPostInput, impl std::future::Future, std::vec::Vec<BlogPost>, &'t26 std::vec::Vec<BlogPost>, [closure@canisters/graphql/src/graphql.rs:8:1: 8:59], DeleteBlogPostInput, impl std::future::Future, impl std::future::Future}]>`
   = note: required because it appears within the type `impl std::future::Future`
   = note: required for the cast to the object type `dyn std::future::Future<Output = std::result::Result<std::option::Option<sudograph::async_graphql::Value>, ServerError>> + std::marker::Send`
   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0277`.
error: could not compile `graphql`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants