2022-11-02 21:12:16 +01:00
|
|
|
use std::collections::{HashMap, BTreeMap};
|
|
|
|
use std::time::Duration;
|
2022-11-02 23:10:59 +01:00
|
|
|
use chrono::{DateTime, FixedOffset};
|
2022-11-02 21:12:16 +01:00
|
|
|
use tokio::time::Instant;
|
|
|
|
|
|
|
|
pub struct Instance {
|
|
|
|
last_fetch: Option<Instant>,
|
2022-11-02 23:10:59 +01:00
|
|
|
latest_timestamp: Option<DateTime<FixedOffset>>,
|
|
|
|
no_updates: u32,
|
2022-11-02 21:12:16 +01:00
|
|
|
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(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-02 22:06:43 +01:00
|
|
|
pub fn size(&self) -> usize {
|
|
|
|
self.instances.len()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn queue_len(&self) -> usize {
|
|
|
|
self.queue.len()
|
|
|
|
}
|
|
|
|
|
2022-11-02 21:12:16 +01:00
|
|
|
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,
|
2022-11-02 23:10:59 +01:00
|
|
|
latest_timestamp: None,
|
|
|
|
no_updates: 0,
|
2022-11-02 21:12:16 +01:00
|
|
|
error: false,
|
|
|
|
});
|
|
|
|
self.queue.insert(now, host);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-02 23:10:59 +01:00
|
|
|
pub fn enqueue(&mut self, host: String, next_interval: Duration, latest_timestamp: Option<DateTime<FixedOffset>>) {
|
2022-11-02 21:12:16 +01:00
|
|
|
let now = Instant::now();
|
|
|
|
|
|
|
|
let instance = self.instances.get_mut(&host).unwrap();
|
|
|
|
instance.last_fetch = Some(now);
|
|
|
|
instance.error = false;
|
2022-11-02 23:10:59 +01:00
|
|
|
if latest_timestamp.is_none() || latest_timestamp == instance.latest_timestamp {
|
|
|
|
instance.no_updates += 1;
|
|
|
|
} else {
|
|
|
|
instance.no_updates = 0;
|
|
|
|
instance.latest_timestamp = latest_timestamp;
|
|
|
|
}
|
|
|
|
let next = now + (1 + instance.no_updates) * next_interval;
|
|
|
|
self.queue.insert(next, host);
|
2022-11-02 21:12:16 +01:00
|
|
|
}
|
|
|
|
|
2022-11-02 22:06:43 +01:00
|
|
|
pub fn dequeue(&mut self) -> Result<String, Duration> {
|
2022-11-02 21:12:16 +01:00
|
|
|
let now = Instant::now();
|
|
|
|
|
|
|
|
if let Some(time) = self.queue.keys().next().cloned() {
|
|
|
|
if time <= now {
|
|
|
|
self.queue.remove(&time)
|
|
|
|
.map(|host| Ok(host))
|
2022-11-02 22:06:43 +01:00
|
|
|
.unwrap_or(Err(Duration::from_secs(1)))
|
2022-11-02 21:12:16 +01:00
|
|
|
} else {
|
2022-11-02 22:06:43 +01:00
|
|
|
Err(time - now)
|
2022-11-02 21:12:16 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
println!("empty queue");
|
2022-11-02 22:06:43 +01:00
|
|
|
Err(Duration::from_secs(60))
|
2022-11-02 21:12:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|