summaryrefslogtreecommitdiff
path: root/src/client/connector.rs
blob: d7f7b95d9795732e56a172f5a6a6aa4e95814813 (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
pub mod connectors;
pub mod manager;

use std::{thread::sleep, time::Duration};

use crate::executor::{Executor, tasks::IntoTask};

#[derive(Debug)]
pub enum Result<T: std::fmt::Display + IntoTask, E: std::fmt::Debug> {
    Ok(T),
    Err(E),
}

pub trait Connection {
    type Ok: std::fmt::Display + IntoTask + AsRef<str> = String;
    type Err: std::fmt::Debug;

    // should use channel to notify update
    fn update(&self) -> Result<Self::Ok, Self::Err>; // None if no update(content is same)

    // TODO: queue failed ntfy
    fn ntfy(&self, data: String) -> Result<Self::Ok, Self::Err>;

    fn is_prev(&mut self, str: &Self::Ok) -> bool;

    fn force_network(&mut self);

    fn reinit(&mut self) {
        sleep(Duration::from_millis(500));
        _ = Executor::new("network", ["on".to_string()]);
        self.force_network();
    }

    fn r#loop(&mut self) -> ! {
        loop {
            // tradeoff: if I put this at the ened of the loop, then the continue would just skip it, and continue doing update() until with no waiting, this wastes lot of cpu/IO
            // however, of course we can add a manual sleep before it continue and put this in the end, but that's code duplication
            // the cons of the current approch is that the first time we've entered, it would start sleeping
            self.reinit();

            match self.update() {
                Result::Ok(s) => {
                    if self.is_prev(&s) {
                        continue;
                    }

                    let mut it = s.as_ref().split_whitespace();
                    let task = match it.next() {
                        Some(t) => t,
                        None => continue,
                    };
                    // FIXME: handle the errors... peak prod code
                    self.ntfy(
                        Executor::new(task, it.map(str::to_string))
                            .unwrap()
                            .run()
                            .unwrap()
                            .clone()
                            .unwrap(),
                    ); //.unwrap()
                }
                Result::Err(e) => {
                    #[cfg(debug_assertions)]
                    std::eprintln!(
                        "[{}:{}:{}] {} = {:#?}",
                        std::file!(),
                        std::line!(),
                        std::column!(),
                        std::stringify!(e),
                        &&e as &dyn std::fmt::Debug,
                    );
                }
            }
        }
    }
}