ars/src/garbage_collector.rs
2023-11-06 18:38:00 +01:00

65 lines
1.7 KiB
Rust

use std::{
collections::{BinaryHeap, HashMap},
sync::Arc,
time::{Duration, SystemTime, UNIX_EPOCH},
};
use tokio::sync::RwLock;
use crate::game::{Game, GameId};
pub fn start_gc(
game_expiry: Arc<RwLock<BinaryHeap<GarbageCollectorItem>>>,
games: Arc<RwLock<HashMap<GameId, Game>>>,
) {
let games = games.clone();
let game_expiry = game_expiry.clone();
tokio::spawn(async move {
tokio::time::sleep(Duration::from_secs(3600)).await;
if let Ok(now) = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|y| y.as_secs())
{
let mut game_expiry = game_expiry.write().await;
while let Some(gc) = game_expiry.peek() {
if gc.expires_at > now {
break;
} else if let Some(gc) = game_expiry.pop() {
let mut games = games.write().await;
games.remove(&gc.id);
}
}
}
});
}
#[derive(PartialEq, Eq)]
pub struct GarbageCollectorItem {
id: GameId,
expires_at: u64,
}
impl GarbageCollectorItem {
pub fn new_in(id: GameId, time: u64) -> Self {
Self {
id,
expires_at: SystemTime::now()
.checked_add(Duration::from_secs(time))
.and_then(|x| x.duration_since(UNIX_EPOCH).map(|y| y.as_secs()).ok())
.unwrap_or_default(),
}
}
}
impl PartialOrd for GarbageCollectorItem {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for GarbageCollectorItem {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.expires_at.cmp(&other.expires_at).reverse()
}
}