use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DiagnosticsStrategy {
Version,
TokenMonitor,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ActivityState {
Active,
Idle,
Dead,
}
pub trait ProgressMonitor {
fn poll(&mut self) -> ActivityState;
}
pub struct TokenMonitor {
lifecycle: Arc<std::sync::Mutex<crate::lsp::state::ServerLifecycle>>,
alive: Arc<std::sync::atomic::AtomicBool>,
}
impl TokenMonitor {
pub const fn new(
lifecycle: Arc<std::sync::Mutex<crate::lsp::state::ServerLifecycle>>,
alive: Arc<std::sync::atomic::AtomicBool>,
) -> Self {
Self { lifecycle, alive }
}
}
impl ProgressMonitor for TokenMonitor {
fn poll(&mut self) -> ActivityState {
use std::sync::atomic::Ordering;
if !self.alive.load(Ordering::SeqCst) {
return ActivityState::Dead;
}
let lifecycle = self
.lifecycle
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
match *lifecycle {
crate::lsp::state::ServerLifecycle::Busy(_) => ActivityState::Active,
crate::lsp::state::ServerLifecycle::Failed
| crate::lsp::state::ServerLifecycle::Dead => ActivityState::Dead,
_ => ActivityState::Idle,
}
}
}
#[cfg(test)]
#[allow(
clippy::expect_used,
reason = "tests use expect for readable assertions"
)]
mod tests {
use super::*;
use crate::lsp::state::ServerLifecycle;
use std::sync::atomic::AtomicBool;
#[test]
fn token_monitor_idle_when_healthy() {
let lifecycle = Arc::new(std::sync::Mutex::new(ServerLifecycle::Healthy));
let alive = Arc::new(AtomicBool::new(true));
let mut monitor = TokenMonitor::new(lifecycle, alive);
assert_eq!(monitor.poll(), ActivityState::Idle);
}
#[test]
fn token_monitor_active_when_busy() {
let lifecycle = Arc::new(std::sync::Mutex::new(ServerLifecycle::Busy(1)));
let alive = Arc::new(AtomicBool::new(true));
let mut monitor = TokenMonitor::new(lifecycle, alive);
assert_eq!(monitor.poll(), ActivityState::Active);
}
#[test]
fn token_monitor_idle_when_initializing() {
let lifecycle = Arc::new(std::sync::Mutex::new(ServerLifecycle::Initializing));
let alive = Arc::new(AtomicBool::new(true));
let mut monitor = TokenMonitor::new(lifecycle, alive);
assert_eq!(monitor.poll(), ActivityState::Idle);
}
#[test]
fn token_monitor_dead_when_not_alive() {
let lifecycle = Arc::new(std::sync::Mutex::new(ServerLifecycle::Healthy));
let alive = Arc::new(AtomicBool::new(false));
let mut monitor = TokenMonitor::new(lifecycle, alive);
assert_eq!(monitor.poll(), ActivityState::Dead);
}
#[test]
fn token_monitor_dead_when_failed() {
let lifecycle = Arc::new(std::sync::Mutex::new(ServerLifecycle::Failed));
let alive = Arc::new(AtomicBool::new(true));
let mut monitor = TokenMonitor::new(lifecycle, alive);
assert_eq!(monitor.poll(), ActivityState::Dead);
}
}