#Future cannot be sent between threads safely

8 messages · Page 1 of 1 (latest)

severe nexus
#

Error I got:

future cannot be sent between threads safely
within `tendril::tendril::NonAtomic`, the trait `Sync` is not implemented for `Cell<usize>`
required for the cast from `impl std::future::Future<Output = ()>` to the object type `dyn std::future::Future<Output = ()> + std::marker::Send`

Code where error is thrown

#[async_trait]
impl EventHandler for Handler {
    async fn message(&self, ctx: Context, msg: Message) {
        onmessage(&ctx, &msg).await;
    }
}

function used:

pub async fn onmessage(ctx: &Context, msg: &Message){
          let letterboxlink;
        let document;
        let imdb_link = if msg.content.starts_with(&"https://letterboxd.com/") {
            let response = reqwest::get(&msg.content).await.unwrap();
            letterboxlink = if response.status().is_success() {
                let body = response.text().await.unwrap();
                document = scraper::Html::parse_document(&body);
                let selector = scraper::Selector::parse(r#"a[data-track-action="IMDb"]"#).unwrap();
                document
                    .select(&selector)
                    .map(|x| x.value().attr("href"))
                    .next()
                    .unwrap()
                    .unwrap()
            } else {
                &msg.content
            };
            letterboxlink
        } else {
            &msg.content
        };
        if msg.content.contains(&"imdb.com") {
            imdb(ctx, msg, imdb_link).await;
        }
}

Hello. I'm having a problem with asynchronous Rust.
I don't really even understand what's going on 😅
I tried Internet, but it didn't really helped me to fix or understand my problem

slender hound
#

what is the "stuff" in onmessage ?

#

the error seems to say you are using a type from the tendril library which cannot be used in threads

severe nexus
#

Updated Original Post
Here is that imdb function. This one is not completely done. Still needs some tweaks

    async fn imdb(ctx: &Context, msg: &Message, imdb_link: &str) {
        let regex =
            Regex::new(r"^(?:http://|https://)?(?:www\.|m\.)?(?:imdb.com/title/)?(tt[0-9]*)")
                .unwrap();

        let result = regex.captures(imdb_link);

        let link = &result.unwrap()[1];

        let mut headers: RaxiosHeaders = RaxiosHeaders::new();
        headers.insert(String::from("imdbId"), String::from(link));
        let uri = env::var("API_URL").unwrap() + "/suggestions";
        let client = Raxios::new("", None).ok();

        let options: RaxiosOptions = RaxiosOptions {
            headers: Option::from(headers),
            accept: Option::from(ContentType::Json),
            content_type: Option::from(ContentType::Json),
            params: None,
            deserialize_body: true,
        };

        let response = client
            .unwrap()
            .post::<u32, &str>(&uri, Option::from(link), Option::from(options))
            .await
            .unwrap();
        let reaction_emoji = match response.status.as_u16() {
            201 => '💾',
            400 => '🚨',
            _ => '🥵',
        };
        msg.react(ctx, reaction_emoji).await.ok();
    }
light onyx
#

Maybe this:

use html5ever::driver::{self, ParseOpts};
use scraper::Html;
use tendril::{TendrilSink, Atomic};

let parser = driver::parse_document(Html::new_document(), ParseOpts::default());
document = TendrilSink::<_, Atomic>::one(&body);
#

That would replace this line:

document = scraper::Html::parse_document(&body);