0

I am building a small app that's supposed to schedule two tasks (based on rusoto AWS SDK) at different intervals: every X seconds, run one task, and every Y seconds, run the other.

I found crate crossbeam that offers a tick timer and a select! macro and put them all together like this:

fn main() -> Result<(), Error> {
  let cloudwatch_client = rusoto_cloudwatch::CloudWatchClient::new();
  let rt = Runtime::new().unwrap();
  let tick_a = tick(Duration::from_secs(60));
  let tick_b = tick(Duration::from_secs(30));

  loop {
    select! {
      recv(tick_a) -> _ => {
        rt.block_on(cloudwatch_client.put_metric_data( /* ... */ ));
      },
      /* similar for tick_b */
    }
  }
}

This compiles, however the program panics with thread 'main' panicked at 'not currently running on the Tokio runtime.'. This seems to come from the Rusoto call, by analyzing the backtrace.

What am I missing here? Is there a way to make this work? Is there a better way to handle the scheduling of tasks at intervals in Rust?

Please note that this question does not seem to address my issue. That question starts out by using futures::executor::block_on function and is solved by using the block_on method implemented by the tokio Runtime. I am already using the block_on method in Runtime.

E_net4
  • 27,810
  • 13
  • 101
  • 139
Victor
  • 13,914
  • 19
  • 78
  • 147
  • 1
    Does this answer your question? [panic with "thread 'main' panicked at 'not currently running on the Tokio runtime](https://stackoverflow.com/questions/59763102/panic-with-thread-main-panicked-at-not-currently-running-on-the-tokio-runtim) – pretzelhammer Dec 25 '20 at 14:04
  • @pretzelhammer no, it does not. as you can see, I am already using the first method in the accepted answer of that question (by using the `block_on` function on the tokio Runtime instance). Please note that I have also tried using `#[tokio::main]` and `await` on my CloudWatch call and the result is the same. – Victor Dec 25 '20 at 14:25
  • 1
    Are you trying to use tokio 0.3? Note that rusoto might still be on 0.2, and the tokio versions are not compatible. If you use the wrong one, you will get this error. You will need to use tokio 0.2 then. – Matthias247 Dec 29 '20 at 05:16
  • 1
    Note that you can restructure the whole thing to run completely inside a tokio runtime. You can use `tokio::select!` and tokio timers for doing what you do with crossbeam here. That might however not fix your "not currently running on the Tokio runtime" issue. – Matthias247 Dec 29 '20 at 05:17
  • 1
    @Matthias247 I changed the version of toklo in my project to the one used by rusoto and it fixed the issue. Indeed the two versions were different. Could you please write this and your suggestion for `tokio::select!` in an answer? :) – Victor Dec 29 '20 at 09:04

3 Answers3

1

thread 'main' panicked at 'not currently running on the Tokio runtime.'

This error will show up if the version of the tokio runtime that is required by a particular library is not actively running - since each major version uses different thread-local variables and more than 1 major version of a library can be included in the same build.

In your case you might have a Tokio 0.3 runtime running, but rusoto expects a Tokio 0.2 runtime. When rusoto then tries to perform IO via Tokio 0.2 (which is also included in the build), that one detects that no runtime is active and yields the error.

To fix this, make sure to use just a single tokio version in your project. You likely need to downgrade tokio to 0.2 via Cargo.toml, since there might be no newer rusoto version available.

One more unrelated suggestion:

Instead of using crossbeam for timers, you can also run the "whole thing" inside a tokio runtime: You can use tokio::select! and tokio timers for doing what you do with crossbeam here.

See https://docs.rs/tokio/0.2.24/tokio/time/fn.interval.html and https://docs.rs/tokio/0.2.24/tokio/macro.select.html (which has examples similar to your use-case)

Matthias247
  • 9,836
  • 1
  • 20
  • 29
0

CloudWatchClient::put_metric_data returns a RusotoFuture which has a sync method does what you want. So instead of:

let cloudwatch_client = rusoto_cloudwatch::CloudWatchClient::new();
let rt = Runtime::new().unwrap();
rt.block_on(cloudwatch_client.put_metric_data(/* ... */));

You can do:

let cloudwatch_client = rusoto_cloudwatch::CloudWatchClient::new();
cloudwatch_client.put_metric_data(/* ... */).sync();

Which is also what the official docs recommend.

pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
  • 1
    I am using `rusoto_cloudwatch = { version = "0.45.0", default_features = false, features=["rustls"] }` in my Cargo.toml and I am getting: `no method named "sync" found for struct Pin>> + Send>> in the current scope` when trying to use the `sync()` method. I tried that one before asking the question. – Victor Dec 25 '20 at 14:42
  • Do you know why that method is missing in the crate I am using? – Victor Dec 25 '20 at 15:00
0

Please note:

Note that from v0.43.0 onward, Rusoto uses Rust's std::future::Future, and the Tokio 0.2 ecosystem. From v0.46.0 onward, Rusoto uses the Tokio 1.0 ecosystem.

I'd recommend the following dependencies for a simple S3 call:

[dependencies]  
rusoto_core = "0.46.0"                            
rusoto_s3 = "0.46.0"                                                    
tokio = {version = "1.0",  features = ["full"]}  

The call can be implemented like this:

use rusoto_core::Region;
use rusoto_s3::{S3, S3Client};

#[tokio::main]
async fn main() {
    let region = Region::UsEast1;
    let client = S3Client::new(region);

    match client.list_buckets().await {
        Ok(output) => match output.buckets {
            Some(bucket_list) => {
                println!("Buckets in S3:");

                for bucket in bucket_list {
                    println!("{:?}", bucket.name);
                }
            }
            None => println!("No buckets!"),
        },
        Err(error) => {
            println!("Error: {:?}", error);
        }
    }
}

Set credentials to avoid credentials error.

Leo Skhrnkv
  • 1,513
  • 16
  • 27