1
Fork 0
generated from lucas/rust-template
Code Issues 1 Pull requests 9 Activity
Var Dump:
dumpVar: only available in dev mode
Mailing List
ntfy-collector/src/main.rs

101 lines
3.3 KiB
Rust

use std::fs;
use std::thread::{self, JoinHandle};
use color_eyre::eyre::{eyre, Context as _};
use color_eyre::Result;
use tracing_error::ErrorLayer;
use tracing_subscriber::layer::SubscriberExt as _;
use tracing_subscriber::util::SubscriberInitExt as _;
use tracing_subscriber::{fmt, EnvFilter};
pub(crate) mod types;
mod worker {
mod api;
mod lua;
mod sender;
mod server;
pub use api::worker as api;
pub use lua::worker as lua;
pub use sender::worker as sender;
pub use server::worker as server;
}
pub(crate) static APP_USER_AGENT: &str =
concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),);
fn spawn<T, F>(name: &'static str, task: F) -> Result<JoinHandle<Result<T>>>
where
F: FnOnce() -> Result<T> + Send + 'static,
T: Send + 'static,
{
thread::Builder::new()
.name(name.to_string())
.spawn(move || {
let res = task();
if let Err(err) = &res {
tracing::error!("Thread '{}' errored: {:?}", name, err);
}
res
})
.wrap_err_with(|| format!("Failed to create thread '{}'", name))
}
// TODO: Don't put the entire app into a Tokio runtime.
// Instead, run single-threaded runtimes off of those threads where I need
// Tokio.
// - Axum server
// - API query scheduler
// - Ntfy sender
// TODO: Find a way to communicate between them, in a way that works for both the non-Tokio
// Lua thread and the various other threads.
fn main() -> Result<()> {
color_eyre::install()?;
tracing_subscriber::registry()
.with(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()))
.with(fmt::layer().compact())
.with(ErrorLayer::new(fmt::format::Pretty::default()))
.init();
// TODO: Create a separate, fixed thread to run Lua on
// TODO: Create a channel to send events to Lua
// TODO: Create another thread that periodically checks
// service APIs. The Lua thread should be able to send
// configurations here
// TODO: Create another thread that handles sending data to
// Ntfy. Most importantly the Lua thread needs to send events here.
// Could be consolidated with the service API thread, since it's all HTTP requests.
let config_path = std::env::var("CONFIG_PATH").wrap_err("Missing variable 'CONFIG_PATH'")?;
let (ntfy_tx, ntfy_rx) = tokio::sync::mpsc::unbounded_channel();
let (event_tx, event_rx) = std::sync::mpsc::channel();
// A channel that lets other threads, mostly the Lua code, register
// a task with the API fetcher.
let (api_tx, api_rx) = tokio::sync::mpsc::unbounded_channel();
{
let code = fs::read_to_string(&config_path)
.wrap_err_with(|| format!("Failed to read config from '{}'", config_path))?;
spawn("lua", move || worker::lua(code, event_rx, api_tx, ntfy_tx))?;
}
{
let event_tx = event_tx.clone();
spawn("api", move || worker::api(api_rx, event_tx))?;
}
{
let event_tx = event_tx.clone();
spawn("sender", move || worker::sender(event_tx, ntfy_rx))?;
}
let server_worker = spawn("server", move || worker::server(event_tx))?;
server_worker
.join()
.map_err(|err| eyre!("Thread 'server' panicked: {:?}", err))
.and_then(|res| res)
}