diff --git a/Cargo.lock b/Cargo.lock index 52c0533..7f910bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -127,9 +127,9 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] @@ -222,61 +222,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" -[[package]] -name = "axum" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" -dependencies = [ - "async-trait", - "axum-core", - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "http-body-util", - "hyper 1.3.1", - "hyper-util", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "tokio", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-core" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper 0.1.2", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "backtrace" version = "0.3.72" @@ -1399,7 +1344,6 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "httparse", - "httpdate", "itoa", "pin-project-lite", "smallvec", @@ -1709,12 +1653,6 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - [[package]] name = "md-5" version = "0.10.6" @@ -2493,9 +2431,8 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reminder-rs" -version = "1.7.18" +version = "1.7.19" dependencies = [ - "axum", "base64 0.22.1", "chrono", "chrono-tz", @@ -2518,6 +2455,7 @@ dependencies = [ "rmp-serde", "rocket", "rocket_dyn_templates", + "sd-notify", "secrecy", "serde", "serde_json", @@ -2556,7 +2494,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 0.1.2", + "sync_wrapper", "system-configuration", "tokio", "tokio-rustls 0.24.1", @@ -2601,7 +2539,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 0.1.2", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", @@ -2911,6 +2849,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sd-notify" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "621e3680f3e07db4c9c2c3fb07c6223ab2fab2e54bd3c04c3ae037990f428c32" + [[package]] name = "secrecy" version = "0.8.0" @@ -3484,12 +3428,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" -[[package]] -name = "sync_wrapper" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" - [[package]] name = "system-configuration" version = "0.5.1" @@ -3775,7 +3713,6 @@ dependencies = [ "tokio", "tower-layer", "tower-service", - "tracing", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b4d7ee3..008dbe2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "reminder-rs" -version = "1.7.18" +version = "1.7.19" authors = ["Jude Southworth "] edition = "2021" license = "AGPL-3.0 only" @@ -34,7 +34,7 @@ rocket_dyn_templates = { version = "0.1.0", features = ["tera"] } serenity = { version = "0.12", default-features = false, features = ["builder", "cache", "client", "gateway", "http", "model", "utils", "rustls_backend"] } oauth2 = "4" csv = "1.2" -axum = "0.7" +sd-notify = "0.4.1" [dependencies.extract_derive] path = "extract_derive" diff --git a/src/commands/settings/ephemeral_confirmations/set.rs b/src/commands/settings/ephemeral_confirmations/set.rs index eab4433..2e0d231 100644 --- a/src/commands/settings/ephemeral_confirmations/set.rs +++ b/src/commands/settings/ephemeral_confirmations/set.rs @@ -22,9 +22,9 @@ impl Recordable for Options { CreateEmbed::new() .title("Confirmations ephemeral") .description(concat!( - "Reminder confirmations will be sent privately, and removed when your client", - " restarts." - )) + "Reminder and todo confirmations will be sent privately, and removed when ", + "your client restarts." + )) .color(*THEME_COLOR), ), ) diff --git a/src/commands/settings/ephemeral_confirmations/unset.rs b/src/commands/settings/ephemeral_confirmations/unset.rs index 8f971fd..23ddc46 100644 --- a/src/commands/settings/ephemeral_confirmations/unset.rs +++ b/src/commands/settings/ephemeral_confirmations/unset.rs @@ -22,8 +22,8 @@ impl Recordable for Options { CreateEmbed::new() .title("Confirmations public") .description(concat!( - "Reminder confirmations will be sent as regular messages, and won't be ", - "removed automatically." + "Reminder and todo confirmations will be sent as regular messages, and", + " won't be removed automatically." )) .color(*THEME_COLOR), ), diff --git a/src/commands/todo/channel/add.rs b/src/commands/todo/channel/add.rs index de0fdbd..03335cb 100644 --- a/src/commands/todo/channel/add.rs +++ b/src/commands/todo/channel/add.rs @@ -1,3 +1,4 @@ +use poise::CreateReply; use serde::{Deserialize, Serialize}; use crate::{ @@ -33,7 +34,13 @@ impl Recordable for Options { .await .unwrap(); - ctx.say("Item added to todo list").await?; + let ephemeral = ctx + .guild_data() + .await + .map_or(false, |gr| gr.map_or(false, |g| g.ephemeral_confirmations)); + + ctx.send(CreateReply::default().content("Item added to todo list").ephemeral(ephemeral)) + .await?; Ok(()) } diff --git a/src/commands/todo/guild/add.rs b/src/commands/todo/guild/add.rs index aa2c370..6dcd4c6 100644 --- a/src/commands/todo/guild/add.rs +++ b/src/commands/todo/guild/add.rs @@ -1,6 +1,8 @@ +use poise::CreateReply; use serde::{Deserialize, Serialize}; use crate::{ + models::CtxData, utils::{Extract, Recordable}, Context, Error, }; @@ -26,7 +28,13 @@ impl Recordable for Options { .await .unwrap(); - ctx.say("Item added to todo list").await?; + let ephemeral = ctx + .guild_data() + .await + .map_or(false, |gr| gr.map_or(false, |g| g.ephemeral_confirmations)); + + ctx.send(CreateReply::default().content("Item added to todo list").ephemeral(ephemeral)) + .await?; Ok(()) } diff --git a/src/commands/todo/user/add.rs b/src/commands/todo/user/add.rs index 1797ffb..fc61e66 100644 --- a/src/commands/todo/user/add.rs +++ b/src/commands/todo/user/add.rs @@ -1,6 +1,8 @@ +use poise::CreateReply; use serde::{Deserialize, Serialize}; use crate::{ + models::CtxData, utils::{Extract, Recordable}, Context, Error, }; @@ -27,7 +29,13 @@ impl Recordable for Options { .await .unwrap(); - ctx.say("Item added to todo list").await?; + let ephemeral = ctx + .guild_data() + .await + .map_or(false, |gr| gr.map_or(false, |g| g.ephemeral_confirmations)); + + ctx.send(CreateReply::default().content("Item added to todo list").ephemeral(ephemeral)) + .await?; Ok(()) } diff --git a/src/main.rs b/src/main.rs index 52ebd4c..7835667 100644 --- a/src/main.rs +++ b/src/main.rs @@ -212,7 +212,6 @@ async fn _main(tx: Sender<()>) -> Result<(), Box> { // Start metrics init_metrics(); - tokio::spawn(async { metrics::serve().await }); let database = Pool::connect(&env::var("DATABASE_URL").expect("No database URL provided")).await.unwrap(); diff --git a/src/metrics.rs b/src/metrics.rs index 3ebfac5..dd17dcc 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -1,6 +1,4 @@ -use axum::{routing::get, Router}; use lazy_static::lazy_static; -use log::warn; use prometheus::{IntCounterVec, Opts, Registry}; lazy_static! { @@ -26,21 +24,3 @@ pub fn init_metrics() { REGISTRY.register(Box::new(REMINDER_FAIL_COUNTER.clone())).unwrap(); REGISTRY.register(Box::new(COMMAND_COUNTER.clone())).unwrap(); } - -pub async fn serve() { - let app = Router::new().route("/metrics", get(metrics)); - - let listener = tokio::net::TcpListener::bind("localhost:31756").await.unwrap(); - axum::serve(listener, app).await.unwrap(); -} - -async fn metrics() -> String { - let encoder = prometheus::TextEncoder::new(); - let res_custom = encoder.encode_to_string(®ISTRY.gather()); - - res_custom.unwrap_or_else(|e| { - warn!("Error encoding metrics: {:?}", e); - - String::new() - }) -} diff --git a/src/postman/mod.rs b/src/postman/mod.rs index 0a164ae..ad53d8a 100644 --- a/src/postman/mod.rs +++ b/src/postman/mod.rs @@ -4,6 +4,7 @@ use std::env; use log::{info, warn}; use poise::serenity_prelude::client::Context; +use sd_notify::{self, NotifyState}; use sqlx::{Executor, MySql}; use tokio::{ sync::broadcast::Receiver, @@ -33,6 +34,16 @@ async fn _initialize(ctx: Context, pool: impl Executor<'_, Database = Database> .flatten() .unwrap_or(10); + // Allow 10 skipped cycles + let mut watchdog_interval = 0; + let watchdog = sd_notify::watchdog_enabled(false, &mut watchdog_interval); + + if watchdog { + warn!("Watchdog enabled. Don't die!"); + } else { + warn!("No watchdog running") + } + loop { let sleep_to = Instant::now() + Duration::from_secs(remind_interval); let reminders = sender::Reminder::fetch_reminders(pool).await; @@ -46,5 +57,6 @@ async fn _initialize(ctx: Context, pool: impl Executor<'_, Database = Database> } sleep_until(sleep_to).await; + let _ = sd_notify::notify(false, &[NotifyState::Watchdog]); } } diff --git a/src/web/metrics.rs b/src/web/fairings/metrics.rs similarity index 100% rename from src/web/metrics.rs rename to src/web/fairings/metrics.rs diff --git a/src/web/fairings/mod.rs b/src/web/fairings/mod.rs new file mode 100644 index 0000000..e144883 --- /dev/null +++ b/src/web/fairings/mod.rs @@ -0,0 +1 @@ +pub mod metrics; diff --git a/src/web/mod.rs b/src/web/mod.rs index 864582a..31b1a87 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -2,9 +2,10 @@ mod consts; #[macro_use] mod macros; mod catchers; +mod fairings; mod guards; -mod metrics; mod routes; + pub mod string { use std::{fmt::Display, str::FromStr}; @@ -79,7 +80,7 @@ use sqlx::{MySql, Pool}; use crate::web::{ consts::{CNC_GUILD, DISCORD_OAUTH_AUTHORIZE, DISCORD_OAUTH_TOKEN, SUBSCRIPTION_ROLES}, - metrics::MetricProducer, + fairings::metrics::MetricProducer, }; type Database = MySql; @@ -149,6 +150,7 @@ pub async fn initialize( routes::report::report_error, routes::return_to_same_site, routes::terms, + routes::metrics, ], ) .mount( diff --git a/src/web/routes/mod.rs b/src/web/routes/mod.rs index 8a5ca7c..8bd3535 100644 --- a/src/web/routes/mod.rs +++ b/src/web/routes/mod.rs @@ -2,11 +2,14 @@ pub mod dashboard; pub mod login; pub mod report; -use std::collections::HashMap; +use std::{collections::HashMap, net::IpAddr}; +use log::warn; use rocket::{get, request::FlashMessage, serde::json::Value as JsonValue}; use rocket_dyn_templates::Template; +use crate::metrics::REGISTRY; + pub type JsonResult = Result; #[get("/")] @@ -107,3 +110,19 @@ pub async fn help_iemanager() -> Template { let map: HashMap<&str, String> = HashMap::new(); Template::render("support/iemanager", &map) } + +#[get("/metrics")] +pub async fn metrics(client_ip: IpAddr) -> String { + if !client_ip.is_loopback() { + String::new() + } else { + let encoder = prometheus::TextEncoder::new(); + let res_custom = encoder.encode_to_string(®ISTRY.gather()); + + res_custom.unwrap_or_else(|e| { + warn!("Error encoding metrics: {:?}", e); + + String::new() + }) + } +} diff --git a/systemd/reminder-rs.service b/systemd/reminder-rs.service index e44bdc3..8af4819 100644 --- a/systemd/reminder-rs.service +++ b/systemd/reminder-rs.service @@ -7,8 +7,9 @@ Type=simple ExecStart=/usr/bin/reminder-rs WorkingDirectory=/etc/reminder-rs Restart=always -RestartSec=4 +RestartSec=10 Environment="reminder_rs=warn,postman=warn" +WatchdogSec=60 [Install] WantedBy=multi-user.target