summaryrefslogtreecommitdiffstats
path: root/src/service.rs
blob: 9ca9fc6a74c7fe20293e1c00a12ebcfdf53df737 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use std::collections::HashMap;

use futures::{StreamExt, TryStreamExt};
use serde::Deserialize;
use tokio_stream::{Stream, StreamMap};

use crate::Status;

pub mod command;
pub mod http;
pub mod tcp;

pub type ServiceHandles = HashMap<String, Status>;

pub trait IntoService {
    type Error: std::error::Error + Sync + Send + Sized;

    fn into_service(self) -> impl Stream<Item = Result<(), Self::Error>> + Send;
}

pub trait IntoServiceMap<K> {
    type Error: std::error::Error + Sync + Send + Sized;

    fn into_service_map(self) -> impl Stream<Item = (K, Result<(), Self::Error>)> + Send;
}

impl<T, K, V> IntoServiceMap<K> for T
where
    T: IntoIterator<Item = (K, V)>,
    V: IntoService,
    K: std::hash::Hash + std::cmp::Eq + std::clone::Clone + std::marker::Unpin + std::marker::Send,
{
    type Error = V::Error;

    fn into_service_map(self) -> impl Stream<Item = (K, Result<(), Self::Error>)> + Send {
        let mut map = StreamMap::new();
        for (name, srv) in self.into_iter() {
            map.insert(name, Box::pin(srv.into_service()));
        }
        map
    }
}

pub fn default_interval() -> std::time::Duration {
    std::time::Duration::from_secs(5)
}

#[derive(Debug, Clone, Deserialize)]
pub struct ServiceConfig {
    pub name: String,
    #[serde(flatten)]
    pub kind: ServiceKind,
}

#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ServiceKind {
    Http(http::Http),
    Tcp(tcp::Tcp),
    Exec(command::Command),
}

#[derive(Debug, thiserror::Error)]
pub enum ServiceError {
    #[error(transparent)]
    Http(#[from] http::Error),
    #[error(transparent)]
    Tcp(#[from] tcp::Error),
    #[error(transparent)]
    Command(#[from] command::Error),
}

impl IntoService for ServiceKind {
    type Error = ServiceError;

    fn into_service(self) -> impl Stream<Item = Result<(), Self::Error>> + Send {
        match self {
            ServiceKind::Http(h) => h.into_service().map_err(ServiceError::from).boxed(),
            ServiceKind::Tcp(t) => t.into_service().map_err(ServiceError::from).boxed(),
            ServiceKind::Exec(c) => c.into_service().map_err(ServiceError::from).boxed(),
        }
    }
}