Initial commit

main
Dustin 2024-07-24 21:33:58 -05:00
commit f1160846db
4 changed files with 1443 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

1331
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

10
Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "luci"
version = "0.1.0"
edition = "2021"
[dependencies]
etcd-client = { version = "0.14.0", features = ["tls"] }
tokio = { version = "1.39.1", default-features = false, features = ["rt", "macros", "rt-multi-thread", "signal"] }
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }

101
src/main.rs Normal file
View File

@ -0,0 +1,101 @@
use std::sync::Arc;
use std::time::Duration;
use etcd_client::Client;
use tokio::sync::Notify;
use tokio::signal::unix::SignalKind;
use tracing::{debug, info, error, trace};
#[tokio::main]
async fn main() {
tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.with_writer(std::io::stderr)
.init();
let stop = Arc::new(Notify::new());
let my_stop = stop.clone();
let task = tokio::spawn(async move {
run(&stop).await
});
if let Err(e) = wait_signal().await {
error!("Failed to set up signal handler: {}", e);
std::process::exit(1);
};
my_stop.notify_waiters();
if let Err(e) = task.await {
error!("{}", e);
std::process::exit(1);
}
}
async fn run(stop: &Notify) {
loop {
let mut client = tokio::select! {
c = connect() => c,
_ = stop.notified() => return
};
let (_, mut stream) = match client.watch("dustin", None).await {
Ok((w, s)) => (w, s),
Err(e) => {
error!("Error setting up watch: {}", e);
continue;
}
};
info!("Watch stream established");
tokio::select! {
m = stream.message() => {
trace!("{:?}", m);
}
_ = stop.notified() => break,
};
}
info!("Shutting down");
}
async fn connect() -> Client {
let mut duration = Duration::from_millis(250);
let addrs = [
"http://127.0.0.1:2379",
];
loop {
let mut client = match Client::connect(&addrs, None).await {
Ok(c) => c,
Err(e) => {
error!("Failed to connect to etcd: {}", e);
tokio::time::sleep(duration).await;
if duration.as_secs() < 300 {
duration *= 2;
}
continue;
}
};
// Client::connect() always succeeds?
match client.status().await {
Ok(s) => info!("Connected: {:?}", s),
Err(e) => {
error!("Failed to connect to etcd: {}", e);
tokio::time::sleep(duration).await;
if duration.as_secs() < 300 {
duration *= 2;
}
continue;
}
}
return client;
}
}
async fn wait_signal() -> std::io::Result<()> {
let mut sigterm = tokio::signal::unix::signal(SignalKind::terminate())?;
let mut sigint = tokio::signal::unix::signal(SignalKind::interrupt())?;
tokio::select! {
_ = sigterm.recv() => {
debug!("Got signal SIGTERM");
}
_ = sigint.recv() => {
debug!("Got signal SIGINT");
}
}
Ok(())
}