cetra3 / tmq

Rust ZeroMQ bindings for Tokio
151 stars 28 forks source link

tmq::request_reply::RequestSender does not implement Copy? #27

Closed ghost closed 3 years ago

ghost commented 3 years ago

I'm a Rust beginner so I may have missed something basic, but:

I'm using a different crate that gives me events in this format:

while let Some((_, event)) = events.next().await {
    // do something with event
}

I would like to send the event data to the message queue, however if I try to use the send_sock inside the loop I get this error:

use of moved value: `send_sock`

value moved here, in previous iteration of looprustc(E0382)
main.rs(12, 9): move occurs because `send_sock` has type `tmq::request_reply::RequestSender`, which does not implement the `Copy` trait

I have tried wrapping it in an Arc but I get a similar error.

What am I missing here?

Kobzol commented 3 years ago

This struct definitely cannot implement Copy. You have to use the sender in a different way.

Please send the code that produces the error (or ideally the whole project), otherwise we won't know where the problem is.

ghost commented 3 years ago

Sure. Here is the full code:

Expand ```rs use std::{env, error::Error, sync::Arc}; use futures::stream::StreamExt; use twilight_cache_inmemory::{InMemoryCache, ResourceType}; use twilight_gateway::{cluster::{Cluster, ShardScheme}, Event, EventTypeFlags}; use twilight_http::Client as HttpClient; use twilight_model::gateway::Intents; #[tokio::main] async fn main() -> Result<(), Box> { let token = env::var("DISCORD_TOKEN")?; let mut send_sock = tmq::request(&tmq::Context::new()).connect("tcp://127.0.0.1:7897")?; // This is the default scheme. It will automatically create as many // shards as is suggested by Discord. let scheme = ShardScheme::Auto; // Use intents to only receive guild message events. let (cluster, mut events) = Cluster::builder(token.to_owned(), Intents::GUILD_MESSAGES) .event_types( EventTypeFlags::SHARD_PAYLOAD | EventTypeFlags::MESSAGE_CREATE ) .shard_scheme(scheme) .build() .await?; let cluster = Arc::new(cluster); // Start up the cluster. let cluster_spawn = Arc::clone(&cluster); // Start all shards in the cluster in the background. tokio::spawn(async move { cluster_spawn.up().await; }); // HTTP is separate from the gateway, so create a new client. let http = Arc::new(HttpClient::new(token)); // Since we only care about new messages, make the cache only // cache new messages. let cache = InMemoryCache::builder() .resource_types(ResourceType::MESSAGE) .build(); // Process each event as they come in. let mq = Arc::new(send_sock); while let Some((shard_id, event)) = events.next().await { // Update the cache with the event. cache.update(&event); match event { Event::MessageCreate(msg) if msg.content == "rs;test" => { http.create_message(msg.channel_id) .content("meow")? .exec() .await?; } Event::ShardPayload(mut payload) => { match serde_json::from_slice::(payload.bytes.as_mut_slice()) { Ok(data) => { match data.t { Some(t) => { let message: tmq::Message = "hi".as_bytes().into(); Arc::clone(&mq).send(message.into()).await?; // println!("t {} c {}", t, data.d["channel_id"]); match t.as_str() { "MESSAGE_CREATE" => { if data.d["channel_id"] == "471388251102380042" { println!("content {} author {}", data.d["content"], data.d["author"]["id"]); } } _ => { println!("unknown op {}", t); } } } None => {} } } Err(err) => { println!("Could not deserialize payload: {}", err); } } } Event::ShardConnected(_) => { println!("Connected on shard {}", shard_id); } // Other events here... _ => {} } // Ok(()) // tokio::spawn(handle_event(shard_id, event, Arc::clone(&http), Arc::clone(&mq))); } Ok(()) } #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct PayloadInfo { pub op: i32, pub t: Option, pub d: serde_json::Value, } ```
ghost commented 3 years ago

Oops, I completely missed the part of the example where it assigns back to send_sock. Doing that fixed the issue.