summaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2025-09-14 00:29:34 +0800
committerlittleblack111 <littleblack11111@gmail.com>2025-09-14 00:29:34 +0800
commit4f75bc1b3fd85a7b54cf6bbb6e895c2deb353299 (patch)
tree64f4724c1d5e19314e2f6e93448c295279e07896 /src/client
parentaf71458da96fdc7699bed2d04c677a352f5af5fe (diff)
feat(executor): integrate into httpconnector
cleanup: main
Diffstat (limited to 'src/client')
-rw-r--r--src/client/connector.rs41
-rw-r--r--src/client/connector/connectors/httpconnector.rs25
-rw-r--r--src/client/executor.rs10
-rw-r--r--src/client/executor/tasks.rs15
-rw-r--r--src/client/main.rs6
5 files changed, 59 insertions, 38 deletions
diff --git a/src/client/connector.rs b/src/client/connector.rs
index 709b91d..cae944b 100644
--- a/src/client/connector.rs
+++ b/src/client/connector.rs
@@ -1,30 +1,49 @@
pub(crate) mod connectors;
pub(crate) mod manager;
-use std::{thread::sleep, time};
+use std::{thread::sleep, time::Duration};
+
+use crate::executor::{Executor, tasks::IntoTask};
+
+pub(crate) enum Result<T: std::fmt::Display + IntoTask, E: std::fmt::Display> {
+ Ok(T),
+ Err(E),
+}
pub(crate) trait Connection {
+ type Ok: std::fmt::Display + IntoTask + AsRef<str> = String;
type Err: std::fmt::Display;
- type Success: std::fmt::Display = String;
// should use channel to notify update
- fn update(&self) -> Option<Result<Self::Success, Self::Err>>; // None if no update(content is same)
+ fn update(&self) -> Option<Result<Self::Ok, Self::Err>>; // None if no update(content is same)
+
+ fn ntfy(&self, data: String);
fn r#loop(&self) -> ! {
loop {
- // if let Some(Err(e)) = self.update() {
- // eprintln!("Error: {}", e)
- // }
match self.update() {
- Some(Ok(s)) => {
- // _ = self.channel.sender.send(res.clone()); // don't care if receiver is dropped
- // _ = executor::new(res.as_str());
+ Some(Result::Ok(s)) => {
+ let mut it = s.as_ref().split_whitespace();
+ let task = match it.next() {
+ Some(t) => t,
+ None => continue,
+ };
+ let args: String = it.collect();
+ // FIXME: handle the errors... peak prod code
+ self.ntfy(
+ Executor::new(task, args)
+ .unwrap()
+ .run()
+ .unwrap()
+ .clone()
+ .unwrap(),
+ );
}
- Some(Err(e)) => eprintln!("Error: {}", e),
+ Some(Result::Err(e)) => eprintln!("Error: {}", e),
_ => {}
}
- sleep(time::Duration::from_secs(1));
+ sleep(Duration::from_millis(500));
}
}
}
diff --git a/src/client/connector/connectors/httpconnector.rs b/src/client/connector/connectors/httpconnector.rs
index 2a7c0d8..923df94 100644
--- a/src/client/connector/connectors/httpconnector.rs
+++ b/src/client/connector/connectors/httpconnector.rs
@@ -1,4 +1,4 @@
-use reqwest::{Error, StatusCode, Url, blocking::get};
+use reqwest::{Error, StatusCode, Url, blocking::Client};
use crate::connector::*;
use std::{thread::sleep, time::Duration};
@@ -6,13 +6,16 @@ use std::{thread::sleep, time::Duration};
pub(crate) struct HTTPConnector {
prev: String,
url: Url,
+ client: Client,
}
impl HTTPConnector {
- pub fn new(url: &str) -> Result<Self, url::ParseError> {
+ pub fn new(url: &str) -> std::result::Result<Self, url::ParseError> {
Ok(Self {
prev: String::new(),
url: Url::parse(url)?,
+ // TODO: keep alive
+ client: Client::new(),
})
}
}
@@ -34,8 +37,8 @@ impl std::fmt::Display for Err {
impl Connection for HTTPConnector {
type Err = Err;
- fn update(&self) -> Option<Result<Self::Success, Self::Err>> {
- let res = match get(self.url.as_str()) {
+ fn update(&self) -> Option<Result<Self::Ok, Self::Err>> {
+ let resp = match self.client.get(self.url.as_str()).send() {
Ok(resp) => match resp.status() {
StatusCode::TOO_MANY_REQUESTS => {
sleep(Duration::from_secs(5));
@@ -43,23 +46,25 @@ impl Connection for HTTPConnector {
}
status => {
if !status.is_success() {
- return Some(Err(Err::StatusCode(status)));
+ return Some(Result::Err(Err::StatusCode(status)));
}
match resp.text() {
Ok(text) => text,
- Err(e) => return Some(Err(Err::Reqwest(e))),
+ Err(e) => return Some(Result::Err(Err::Reqwest(e))),
}
}
},
- Err(e) => return Some(Err(Err::Reqwest(e))),
+ Err(e) => return Some(Result::Err(Err::Reqwest(e))),
};
- if res == self.prev {
+ if resp == self.prev {
return None;
}
- Some(Ok(res))
+ Some(Result::Ok(resp))
}
- // fn ntfy<T>(&self, data: T) {}
+ fn ntfy(&self, data: String) {
+ println!("{}", data)
+ }
}
diff --git a/src/client/executor.rs b/src/client/executor.rs
index df22c57..5fbba0b 100644
--- a/src/client/executor.rs
+++ b/src/client/executor.rs
@@ -1,15 +1,15 @@
use crate::executor::tasks::{IntoTask, IntoTaskErr, Task};
-mod tasks;
+pub(crate) mod tasks;
-struct Executor<'a> {
+pub(crate) struct Executor<'a> {
task: &'a Task,
- args: Box<[&'a str]>,
+ args: Box<[String]>,
output: Option<Result<String, String>>,
}
impl<'a> Executor<'a> {
- fn new(task: impl IntoTask, args: &'a str) -> Result<Self, IntoTaskErr> {
+ pub(crate) fn new(task: impl IntoTask, args: String) -> Result<Self, IntoTaskErr> {
let task = task.into_task()?;
Ok(Self {
task: task,
@@ -18,7 +18,7 @@ impl<'a> Executor<'a> {
})
}
- fn run(&mut self) -> Option<&Result<String, String>> {
+ pub(crate) fn run(&mut self) -> Option<&Result<String, String>> {
self.output = Some((self.task.exec)(&self.args));
self.output.as_ref()
}
diff --git a/src/client/executor/tasks.rs b/src/client/executor/tasks.rs
index c69b310..4c8cdee 100644
--- a/src/client/executor/tasks.rs
+++ b/src/client/executor/tasks.rs
@@ -1,6 +1,6 @@
pub(crate) struct Task {
pub name: &'static str,
- pub exec: fn(&[&str]) -> Result<String, String>,
+ pub exec: fn(&[String]) -> Result<String, String>,
}
pub(crate) const TASKS: &[Task] = &[
@@ -14,14 +14,14 @@ pub(crate) const TASKS: &[Task] = &[
},
];
-fn no_op(_: &[&str]) -> Result<String, String> {
+fn no_op(_: &[String]) -> Result<String, String> {
Ok("".to_string())
}
-fn exec(cmds: &[&str]) -> Result<String, String> {
+fn exec(cmds: &[String]) -> Result<String, String> {
use std::process::Command;
// TODO: fmt and add exit code, and add support for both stdout and stderr, and support for no output
- match Command::new(cmds[0]).args(&cmds[1..]).output() {
+ match Command::new(cmds[0].as_str()).args(&cmds[1..]).output() {
Ok(o) => {
if o.status.success() {
Ok(String::from_utf8(o.stdout)
@@ -37,8 +37,9 @@ fn exec(cmds: &[&str]) -> Result<String, String> {
}
}
+#[derive(Debug)]
pub(crate) enum IntoTaskErr {
- NotFound,
+ NotFound(String),
}
pub(crate) trait IntoTask {
@@ -52,7 +53,7 @@ impl IntoTask for String {
return Ok(task);
}
}
- Err(IntoTaskErr::NotFound)
+ Err(IntoTaskErr::NotFound(self))
}
}
@@ -63,6 +64,6 @@ impl IntoTask for &str {
return Ok(task);
}
}
- Err(IntoTaskErr::NotFound)
+ Err(IntoTaskErr::NotFound(self.to_string()))
}
}
diff --git a/src/client/main.rs b/src/client/main.rs
index cada2f8..bceaa82 100644
--- a/src/client/main.rs
+++ b/src/client/main.rs
@@ -1,13 +1,9 @@
#![feature(associated_type_defaults, never_type)]
-use std::thread;
-
use crate::connector::{connectors::httpconnector::HTTPConnector, manager::ConnectorManager};
mod connector;
mod executor;
fn main() {
- ConnectorManager::new(HTTPConnector::new("https://example.com").unwrap()).enter_loop();
-
- thread::park();
+ ConnectorManager::new(HTTPConnector::new("http://127.0.0.1").unwrap()).enter_loop();
}