prepare for parallel tasks (race/stream announcing)

main
Joey Pollack 2 years ago
parent 6dc2052ce7
commit 8c77b9f059

@ -7,5 +7,5 @@ edition = "2021"
[dependencies]
rand = "0.8.5"
serenity = { version = "0.11.6", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] }
serenity = { version = "0.11.6", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "cache"] }
tokio = { version = "1.21.1", features = ["full"] }

@ -6,22 +6,28 @@ mod utils;
// use std::collections::HashSet;
use std::sync::Arc;
use std::sync::atomic::AtomicU64;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
use serenity::async_trait;
use serenity::prelude::*;
// use serenity::model::prelude::*;
use serenity::model::channel::Message;
use serenity::model::gateway::Ready;
use serenity::model::id::GuildId;
use serenity::http::Http;
struct Globals;
struct Owner;
impl TypeMapKey for Globals
impl TypeMapKey for Owner
{
type Value = Arc<AtomicU64>;
}
struct Handler;
struct Handler
{
is_loop_running: AtomicBool,
}
#[async_trait]
impl EventHandler for Handler
@ -43,9 +49,52 @@ impl EventHandler for Handler
// private channels, and more.
//
// In this case, just print what the current user's username is.
async fn ready(&self, _: Context, ready: Ready) {
async fn ready(&self, _: Context, ready: Ready)
{
println!("{} is connected!", ready.user.name);
}
// CODE TAKEN FROM EXAMPLE:
// https://github.com/serenity-rs/serenity/blob/current/examples/e13_parallel_loops/src/main.rs
// We use the cache_ready event just in case some cache operation is required in whatever use
// case you have for this.
async fn cache_ready(&self, ctx: Context, _guilds: Vec<GuildId>)
{
println!("Cache built successfully!");
// it's safe to clone Context, but Arc is cheaper for this use case.
// Untested claim, just theoretically. :P
let ctx = Arc::new(ctx);
// We need to check that the loop is not already running when this event triggers,
// as this event triggers every time the bot enters or leaves a guild, along every time the
// ready shard event triggers.
//
// An AtomicBool is used because it doesn't require a mutable reference to be changed, as
// we don't have one due to self being an immutable reference.
if !self.is_loop_running.load(Ordering::Relaxed) {
// We have to clone the Arc, as it gets moved into the new thread.
let ctx1 = Arc::clone(&ctx);
// tokio::spawn creates a new green thread that can run in parallel with the rest of
// the application.
tokio::spawn(async move {
loop {
// We clone Context again here, because Arc is owned, so it moves to the
// new function.
//log_system_load(Arc::clone(&ctx1)).await;
// TODO: function we want to run called here
// Run racetime.gg and twitch api checks
// Post new stuff to discord channel
tokio::time::sleep(Duration::from_secs(120)).await;
}
});
// Now that the loop is running, we set the bool to true
self.is_loop_running.swap(true, Ordering::Relaxed);
}
}
}
@ -78,7 +127,10 @@ async fn main()
// Create a new instance of the Client, logging in as a bot. This will
// automatically prepend your bot token with "Bot ", which is a requirement
// by Discord for bot users.
let mut client = Client::builder(&token, intents).event_handler(Handler).await.expect("Err creating client");
let mut client = Client::builder(&token, intents).event_handler(Handler
{
is_loop_running: AtomicBool::new(false),
}).await.expect("Err creating client");
// Set the global data
@ -87,9 +139,10 @@ async fn main()
// Open the data lock in write mode, so keys can be inserted to it.
let mut data = client.data.write().await;
data.insert::<Globals>(Arc::new(AtomicU64::new(owner.into())));
data.insert::<Owner>(Arc::new(AtomicU64::new(owner.into())));
}
// Finally, start a single shard, and start listening to events.
//
// Shards will automatically attempt to reconnect, and will perform

Loading…
Cancel
Save