mirror of
https://github.com/pcvolkmer/checkbar.git
synced 2025-04-19 19:16:50 +00:00
Use numbers or parseable string for config property interval
This commit is contained in:
parent
813ebc7a24
commit
5cc33c983e
@ -35,7 +35,12 @@ The value for `interval` can be set by using plain seconds or using units of `h`
|
|||||||
default to 60 seconds.
|
default to 60 seconds.
|
||||||
|
|
||||||
----
|
----
|
||||||
# Update interval using value with units. Default value if not set is 60 sec.
|
# Update interval using seconds as number.
|
||||||
|
interval = 60
|
||||||
|
|
||||||
|
# or ...
|
||||||
|
|
||||||
|
# Update interval using value with units.
|
||||||
interval = "2m 30s"
|
interval = "2m 30s"
|
||||||
----
|
----
|
||||||
|
|
||||||
|
147
src/config.rs
147
src/config.rs
@ -1,11 +1,15 @@
|
|||||||
use regex::Regex;
|
use std::fmt::Formatter;
|
||||||
use serde::Deserialize;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{env, fs};
|
use std::{env, fs};
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
use serde::de::{Error, Visitor};
|
||||||
|
use serde::{Deserialize, Deserializer};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub interval: Option<String>,
|
#[serde(default, deserialize_with = "deserialize_duration")]
|
||||||
|
pub interval: Option<Duration>,
|
||||||
pub colors: Option<ColorConfig>,
|
pub colors: Option<ColorConfig>,
|
||||||
pub checks: Vec<CheckConfig>,
|
pub checks: Vec<CheckConfig>,
|
||||||
}
|
}
|
||||||
@ -60,15 +64,42 @@ pub fn get_config() -> Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_duration(value: Option<String>) -> Duration {
|
fn deserialize_duration<'de, D>(d: D) -> Result<Option<Duration>, D::Error>
|
||||||
let mut result = 0;
|
where
|
||||||
let value = match &value {
|
D: Deserializer<'de>,
|
||||||
Some(value) => {
|
{
|
||||||
let result = value;
|
struct StringVisitor;
|
||||||
result.as_str()
|
|
||||||
|
impl<'de> Visitor<'de> for StringVisitor {
|
||||||
|
type Value = String;
|
||||||
|
|
||||||
|
fn expecting(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||||
|
f.write_str("a number or string with parsable duration")
|
||||||
}
|
}
|
||||||
_ => return Duration::from_secs(60),
|
|
||||||
};
|
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
Ok(format!("{}", v))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
Ok(v.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match d.deserialize_string(StringVisitor) {
|
||||||
|
Ok(value) => Ok(parse_duration(value.as_str())),
|
||||||
|
Err(err) => Err(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_duration(value: &str) -> Option<Duration> {
|
||||||
|
let mut result = 0;
|
||||||
if let Ok(re) =
|
if let Ok(re) =
|
||||||
Regex::new(r"^((?P<hours>\d+)h\s*)?((?P<minutes>\d+)m\s*)?((?P<seconds>\d+)s?\s*)?$")
|
Regex::new(r"^((?P<hours>\d+)h\s*)?((?P<minutes>\d+)m\s*)?((?P<seconds>\d+)s?\s*)?$")
|
||||||
{
|
{
|
||||||
@ -93,59 +124,81 @@ pub fn parse_duration(value: Option<String>) -> Duration {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Duration::from_secs(60);
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Duration::from_secs(result)
|
Some(Duration::from_secs(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::config::parse_duration;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::config::{parse_duration, Config};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_should_parse_config_with_number_interval() {
|
||||||
|
let config: Config = toml::from_str(
|
||||||
|
r#"
|
||||||
|
interval = 123
|
||||||
|
|
||||||
|
[[checks]]
|
||||||
|
name = "example"
|
||||||
|
url = "https://example.com"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(config.interval, Some(Duration::from_secs(123)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_should_parse_config_with_parsed_interval() {
|
||||||
|
let config: Config = toml::from_str(
|
||||||
|
r#"
|
||||||
|
interval = "2m 3s"
|
||||||
|
|
||||||
|
[[checks]]
|
||||||
|
name = "example"
|
||||||
|
url = "https://example.com"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(config.interval, Some(Duration::from_secs(123)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_should_parse_config_without_interval() {
|
||||||
|
let config: Config = toml::from_str(
|
||||||
|
r#"
|
||||||
|
[[checks]]
|
||||||
|
name = "example"
|
||||||
|
url = "https://example.com"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(config.interval, None);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_should_parse_durations() {
|
fn test_should_parse_durations() {
|
||||||
assert_eq!(
|
assert_eq!(parse_duration("1m30s"), Some(Duration::from_secs(90)));
|
||||||
parse_duration(Some("1m30s".to_string())),
|
assert_eq!(parse_duration("2m"), Some(Duration::from_secs(120)));
|
||||||
Duration::from_secs(90)
|
assert_eq!(parse_duration("1h1m1s"), Some(Duration::from_secs(3661)));
|
||||||
);
|
assert_eq!(parse_duration("90"), Some(Duration::from_secs(90)));
|
||||||
assert_eq!(
|
|
||||||
parse_duration(Some("2m".to_string())),
|
|
||||||
Duration::from_secs(120)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
parse_duration(Some("1h1m1s".to_string())),
|
|
||||||
Duration::from_secs(3661)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
parse_duration(Some("90".to_string())),
|
|
||||||
Duration::from_secs(90)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_should_parse_durations_with_whitespaces() {
|
fn test_should_parse_durations_with_whitespaces() {
|
||||||
assert_eq!(
|
assert_eq!(parse_duration("1m 30s"), Some(Duration::from_secs(90)));
|
||||||
parse_duration(Some("1m 30s".to_string())),
|
assert_eq!(parse_duration("1h 1m 1s"), Some(Duration::from_secs(3661)));
|
||||||
Duration::from_secs(90)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
parse_duration(Some("1h 1m 1s".to_string())),
|
|
||||||
Duration::from_secs(3661)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_should_return_default_for_unparseable_durations() {
|
fn test_should_return_default_for_unparseable_durations() {
|
||||||
assert_eq!(parse_duration(None), Duration::from_secs(60));
|
assert_eq!(parse_duration("invalid"), None);
|
||||||
assert_eq!(
|
assert_eq!(parse_duration("1x30m10q"), None);
|
||||||
parse_duration(Some("invalid".to_string())),
|
|
||||||
Duration::from_secs(60)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
parse_duration(Some("1x30m10q".to_string())),
|
|
||||||
Duration::from_secs(60)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
src/main.rs
15
src/main.rs
@ -1,14 +1,15 @@
|
|||||||
mod checker;
|
|
||||||
mod config;
|
|
||||||
|
|
||||||
use std::process;
|
use std::process;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
|
|
||||||
use crate::checker::{ActuatorChecker, CheckResult, HttpChecker, TcpChecker};
|
use crate::checker::{ActuatorChecker, CheckResult, HttpChecker, TcpChecker};
|
||||||
use crate::config::{get_config, parse_duration, CheckConfig, CheckType};
|
use crate::config::{get_config, CheckConfig, CheckType};
|
||||||
|
|
||||||
|
mod checker;
|
||||||
|
mod config;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct ClickEvent {
|
struct ClickEvent {
|
||||||
@ -101,7 +102,11 @@ async fn main() {
|
|||||||
loop {
|
loop {
|
||||||
let config = get_config();
|
let config = get_config();
|
||||||
print_states(&config.checks).await;
|
print_states(&config.checks).await;
|
||||||
std::thread::sleep(parse_duration(config.interval));
|
let interval = match config.interval {
|
||||||
|
Some(value) => value,
|
||||||
|
_ => Duration::from_secs(60),
|
||||||
|
};
|
||||||
|
std::thread::sleep(interval);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user