66 lines
1.7 KiB
Rust
66 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;
|
||
|
|
||
|
pub fn start_gc(
|
||
|
game_expiry: Arc<RwLock<BinaryHeap<GarbageCollectorItem>>>,
|
||
|
games: Arc<RwLock<HashMap<String, 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: String,
|
||
|
expires_at: u64,
|
||
|
}
|
||
|
|
||
|
impl GarbageCollectorItem {
|
||
|
pub fn new_in(id: String, 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()
|
||
|
}
|
||
|
}
|