caveman/src/world.rs
2022-11-02 21:12:26 +01:00

75 lines
2.0 KiB
Rust

use std::collections::{HashMap, BTreeMap};
use std::time::Duration;
use tokio::time::Instant;
const ERROR_INTERVAL: Duration = Duration::from_secs(86400u64);
pub struct Instance {
last_fetch: Option<Instant>,
error: bool,
}
pub struct World {
instances: HashMap<String, Instance>,
queue: BTreeMap<Instant, String>,
}
// TODO: self.queue.insert() with key collision avoidance
impl World {
pub fn new() -> Self {
World {
instances: HashMap::new(),
queue: BTreeMap::new(),
}
}
pub fn introduce(&mut self, host: String) {
let now = Instant::now();
if self.instances.get(&host).is_none() {
self.instances.insert(host.clone(), Instance {
last_fetch: None,
error: false,
});
self.queue.insert(now, host);
}
}
pub fn set_fetched(&mut self, host: String, next_interval: Duration) {
let now = Instant::now();
let instance = self.instances.get_mut(&host).unwrap();
instance.last_fetch = Some(now);
instance.error = false;
println!("enqueue at {:?}", now + next_interval);
self.queue.insert(now + next_interval, host);
}
pub fn set_error(&mut self, host: String) {
let now = Instant::now();
let instance = self.instances.get_mut(&host).unwrap();
instance.last_fetch = Some(now);
instance.error = true;
println!("enqueue at {:?}", now + ERROR_INTERVAL);
self.queue.insert(now + ERROR_INTERVAL, host);
}
pub fn dequeue(&mut self) -> Result<String, Instant> {
let now = Instant::now();
if let Some(time) = self.queue.keys().next().cloned() {
if time <= now {
self.queue.remove(&time)
.map(|host| Ok(host))
.unwrap_or(Err(now + Duration::from_secs(1)))
} else {
Err(time)
}
} else {
println!("empty queue");
Err(now + Duration::from_secs(60))
}
}
}