use crate::commands::lib::run_query_in_picodata_admin;
use anyhow::{bail, Result};
use std::{path::Path, str::FromStr};
const GET_INSTANCE_NAME: &str = "\\lua\npico.instance_info().name";
const GET_INSTANCE_CURRENT_STATE: &str = "\\lua\npico.instance_info().current_state.variant";
#[derive(Clone, Copy, Debug)]
pub enum InstanceState {
Online,
Offline,
Expelled,
}
impl InstanceState {
pub fn is_online(self) -> bool {
matches!(self, InstanceState::Online)
}
}
impl FromStr for InstanceState {
type Err = anyhow::Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
let state = match s.to_ascii_lowercase().as_str() {
"online" => Self::Online,
"offline" => Self::Offline,
"expelled" => Self::Expelled,
unknown => bail!("Unknown instane state variant: '{unknown}'"),
};
Ok(state)
}
}
fn get_lua_single_line_output(
picodata_path: &Path,
socket_path: &Path,
lua_query: &str,
) -> Result<String> {
let stdout = run_query_in_picodata_admin(picodata_path, socket_path, lua_query)?;
let Some(output) = stdout.lines().find_map(|line| line.strip_prefix("- ")) else {
bail!("unable to extract single line from Lua query output '{stdout}'");
};
Ok(output.to_string())
}
pub fn get_instance_name(picodata_path: &Path, instance_data_dir: &Path) -> Result<String> {
let instance_socket = instance_data_dir.join("admin.sock");
get_lua_single_line_output(picodata_path, &instance_socket, GET_INSTANCE_NAME)
}
pub fn get_instance_current_state(
picodata_path: &Path,
instance_data_dir: &Path,
) -> Result<InstanceState> {
let instance_socket = instance_data_dir.join("admin.sock");
get_lua_single_line_output(picodata_path, &instance_socket, GET_INSTANCE_CURRENT_STATE)
.and_then(|state| state.parse())
}