revolt_database/tasks/
mod.rs

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