Skip to content
New issue

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

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

Already on GitHub? # to your account

futures::join! two Futures from api #558

Closed
lx38 opened this issue Jun 4, 2022 · 5 comments · Fixed by #561
Closed

futures::join! two Futures from api #558

lx38 opened this issue Jun 4, 2022 · 5 comments · Fixed by #561
Assignees
Milestone

Comments

@lx38
Copy link

lx38 commented Jun 4, 2022

Trying to understand how to make parallel calls , just like I can do via polkadotjs/api via Promises.all()

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>>{

    let api = ClientBuilder::new()
        .set_url("wss://rpc.polkadot.io:443")
        .build()
        .await?
        .to_runtime_api::<polkadot::api::RuntimeApi<DefaultConfig, SubstrateExtrinsicParams<DefaultConfig>>>();


    let addr = AccountId32::from_str("13Ybj8CPEArUee78DxUAP9yX3ABmFNVQME1ZH4w8HVncHGzc").unwrap();

    let controller = api.storage().staking().bonded(&addr, None);
    let ledger = api.storage().staking().ledger(&addr, None);

    let (a, b) = join!(controller, ledger);

    Ok(())
}

What I get is the following:

22 |     let controller = api.storage().staking().bonded(&addr, None);
   |                      ^^^^^^^^^^^^^^^^^^^^^^^                    - temporary value is freed at the end of this statement
   |                      |
   |                      creates a temporary which is freed while still in use
...
25 |     let (a, b) = join!(controller, ledger);
   |                        ---------- borrow later used here

I can extract staking and ledger as variables, but maybe I do something wrong? probably I do not understand the concept.

@lx38
Copy link
Author

lx38 commented Jun 4, 2022

PS. extracting vars does not help too much. I doing lotsa requests for multiple accounts and Rust code operates 2 times slower than equivalent Nodejs code..

@jsdw
Copy link
Collaborator

jsdw commented Jun 6, 2022

Your above example doesn't work becuase the bonded()/ledger() calls are both async functions that borrow self (eg borrow the thing returned from staking(). Extracting that variable out so that it lives long enough makes it compile:

use subxt::sp_core::crypto::AccountId32;
use futures::join;
use std::str::FromStr;
use subxt::{
    PolkadotExtrinsicParams,
    ClientBuilder,
    DefaultConfig,
};

#[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata.scale")]
pub mod polkadot {}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>>{

    let api = ClientBuilder::new()
        .set_url("wss://rpc.polkadot.io:443")
        .build()
        .await?
        .to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, PolkadotExtrinsicParams<DefaultConfig>>>();


    let addr = AccountId32::from_str("13Ybj8CPEArUee78DxUAP9yX3ABmFNVQME1ZH4w8HVncHGzc").unwrap();

    let staking = api.storage().staking();
    let controller = staking.bonded(&addr, None);
    let ledger = staking.ledger(&addr, None);

    let (a, b) = join!(controller, ledger);

    Ok(())
}

We might be able to improve the ergonomics here by, instead of having async fns, being a bit more explicit and generating code like:

fn bonded(&self, ...) -> impl Future<Item=Foo> + 'a {
    let client = &self.client;
    async move {
        // take ownership of client, not all of self in the future, so that we dont rely on borrow,
        // and put rest of generated logic in here.
    }
}

@jsdw
Copy link
Collaborator

jsdw commented Jun 7, 2022

The above PR should make what you originally tried to do work (although note that you should use PolkadotExtrinsicParams, not SubstrateExtrinsicParams really if you're connecting to a polkadot node (for accessing storage items it makes no difference, but you'd run into issues trying to submit transactions)

@jsdw jsdw self-assigned this Jun 7, 2022
@lx38
Copy link
Author

lx38 commented Jun 10, 2022

@jsdw thanks for clarification/example on usage. I can use features w/o any issues now. Thanks for spotting incorrect struct usage. This was taken from README.md, where it uses SubstrateExtrinsicParams instead of PolkadotExtrinsicParams, so I think you shall amend it too..

@jsdw
Copy link
Collaborator

jsdw commented Jun 13, 2022

Ah you're right; I'll tweak the README to fix that error :)

@jsdw jsdw closed this as completed in #561 Jun 14, 2022
@jsdw jsdw added this to the Release 0.22 milestone Jun 14, 2022
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants