Skip to main content

revolt_database/tasks/
mod.rs

1//! Semi-important background task management
2
3use crate::{Database, AMQP};
4
5use tokio::task;
6use std::time::Instant;
7
8const WORKER_COUNT: usize = 5;
9
10pub mod ack;
11pub mod last_message_id;
12pub mod process_embeds;
13
14/// Spawn background workers
15pub fn start_workers(db: Database, amqp: AMQP) {
16    for _ in 0..WORKER_COUNT {
17        task::spawn(ack::worker(db.clone(), amqp.clone()));
18        task::spawn(last_message_id::worker(db.clone()));
19        task::spawn(process_embeds::worker(db.clone()));
20    }
21}
22
23/// Task with additional information on when it should run
24pub struct DelayedTask<T> {
25    pub data: T,
26    run_now: bool,
27    last_updated: Instant,
28    first_seen: Instant,
29}
30
31/// Commit to database every 30 seconds if the task is particularly active.
32static EXPIRE_CONSTANT: u64 = 30;
33
34/// Otherwise, commit to database after 5 seconds.
35static SAVE_CONSTANT: u64 = 5;
36
37impl<T> DelayedTask<T> {
38    /// Create a new delayed task
39    pub fn new(data: T) -> Self {
40        DelayedTask {
41            data,
42            run_now: false,
43            last_updated: Instant::now(),
44            first_seen: Instant::now(),
45        }
46    }
47
48    /// Push a task further back in time
49    pub fn delay(&mut self) {
50        self.last_updated = Instant::now()
51    }
52
53    /// Flag the task to run right away, regardless of the time
54    pub fn run_immediately(&mut self) {
55        self.run_now = true
56    }
57
58    /// Check if a task should run yet
59    pub fn should_run(&self) -> bool {
60        self.run_now
61            || self.first_seen.elapsed().as_secs() > EXPIRE_CONSTANT
62            || self.last_updated.elapsed().as_secs() > SAVE_CONSTANT
63    }
64}