* Made todo added responses ephemeral if /settings ephemeral is on
* Enabled systemd watchdog
* Move metrics to rocket
This commit is contained in:
jude 2024-06-04 18:24:24 +01:00
parent 064efd4386
commit f84d517eae
15 changed files with 84 additions and 110 deletions

87
Cargo.lock generated
View File

@ -127,9 +127,9 @@ dependencies = [
[[package]] [[package]]
name = "anstyle-query" name = "anstyle-query"
version = "1.0.3" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
dependencies = [ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
@ -222,61 +222,6 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" 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]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.72" version = "0.3.72"
@ -1399,7 +1344,6 @@ dependencies = [
"http 1.1.0", "http 1.1.0",
"http-body 1.0.0", "http-body 1.0.0",
"httparse", "httparse",
"httpdate",
"itoa", "itoa",
"pin-project-lite", "pin-project-lite",
"smallvec", "smallvec",
@ -1709,12 +1653,6 @@ dependencies = [
"regex-automata 0.1.10", "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]] [[package]]
name = "md-5" name = "md-5"
version = "0.10.6" version = "0.10.6"
@ -2493,9 +2431,8 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]] [[package]]
name = "reminder-rs" name = "reminder-rs"
version = "1.7.18" version = "1.7.19"
dependencies = [ dependencies = [
"axum",
"base64 0.22.1", "base64 0.22.1",
"chrono", "chrono",
"chrono-tz", "chrono-tz",
@ -2518,6 +2455,7 @@ dependencies = [
"rmp-serde", "rmp-serde",
"rocket", "rocket",
"rocket_dyn_templates", "rocket_dyn_templates",
"sd-notify",
"secrecy", "secrecy",
"serde", "serde",
"serde_json", "serde_json",
@ -2556,7 +2494,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"sync_wrapper 0.1.2", "sync_wrapper",
"system-configuration", "system-configuration",
"tokio", "tokio",
"tokio-rustls 0.24.1", "tokio-rustls 0.24.1",
@ -2601,7 +2539,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"sync_wrapper 0.1.2", "sync_wrapper",
"system-configuration", "system-configuration",
"tokio", "tokio",
"tokio-native-tls", "tokio-native-tls",
@ -2911,6 +2849,12 @@ dependencies = [
"untrusted", "untrusted",
] ]
[[package]]
name = "sd-notify"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "621e3680f3e07db4c9c2c3fb07c6223ab2fab2e54bd3c04c3ae037990f428c32"
[[package]] [[package]]
name = "secrecy" name = "secrecy"
version = "0.8.0" version = "0.8.0"
@ -3484,12 +3428,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "sync_wrapper"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
[[package]] [[package]]
name = "system-configuration" name = "system-configuration"
version = "0.5.1" version = "0.5.1"
@ -3775,7 +3713,6 @@ dependencies = [
"tokio", "tokio",
"tower-layer", "tower-layer",
"tower-service", "tower-service",
"tracing",
] ]
[[package]] [[package]]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "reminder-rs" name = "reminder-rs"
version = "1.7.18" version = "1.7.19"
authors = ["Jude Southworth <judesouthworth@pm.me>"] authors = ["Jude Southworth <judesouthworth@pm.me>"]
edition = "2021" edition = "2021"
license = "AGPL-3.0 only" 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"] } serenity = { version = "0.12", default-features = false, features = ["builder", "cache", "client", "gateway", "http", "model", "utils", "rustls_backend"] }
oauth2 = "4" oauth2 = "4"
csv = "1.2" csv = "1.2"
axum = "0.7" sd-notify = "0.4.1"
[dependencies.extract_derive] [dependencies.extract_derive]
path = "extract_derive" path = "extract_derive"

View File

@ -22,9 +22,9 @@ impl Recordable for Options {
CreateEmbed::new() CreateEmbed::new()
.title("Confirmations ephemeral") .title("Confirmations ephemeral")
.description(concat!( .description(concat!(
"Reminder confirmations will be sent privately, and removed when your client", "Reminder and todo confirmations will be sent privately, and removed when ",
" restarts." "your client restarts."
)) ))
.color(*THEME_COLOR), .color(*THEME_COLOR),
), ),
) )

View File

@ -22,8 +22,8 @@ impl Recordable for Options {
CreateEmbed::new() CreateEmbed::new()
.title("Confirmations public") .title("Confirmations public")
.description(concat!( .description(concat!(
"Reminder confirmations will be sent as regular messages, and won't be ", "Reminder and todo confirmations will be sent as regular messages, and",
"removed automatically." " won't be removed automatically."
)) ))
.color(*THEME_COLOR), .color(*THEME_COLOR),
), ),

View File

@ -1,3 +1,4 @@
use poise::CreateReply;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
@ -33,7 +34,13 @@ impl Recordable for Options {
.await .await
.unwrap(); .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(()) Ok(())
} }

View File

@ -1,6 +1,8 @@
use poise::CreateReply;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
models::CtxData,
utils::{Extract, Recordable}, utils::{Extract, Recordable},
Context, Error, Context, Error,
}; };
@ -26,7 +28,13 @@ impl Recordable for Options {
.await .await
.unwrap(); .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(()) Ok(())
} }

View File

@ -1,6 +1,8 @@
use poise::CreateReply;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
models::CtxData,
utils::{Extract, Recordable}, utils::{Extract, Recordable},
Context, Error, Context, Error,
}; };
@ -27,7 +29,13 @@ impl Recordable for Options {
.await .await
.unwrap(); .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(()) Ok(())
} }

View File

@ -212,7 +212,6 @@ async fn _main(tx: Sender<()>) -> Result<(), Box<dyn StdError + Send + Sync>> {
// Start metrics // Start metrics
init_metrics(); init_metrics();
tokio::spawn(async { metrics::serve().await });
let database = let database =
Pool::connect(&env::var("DATABASE_URL").expect("No database URL provided")).await.unwrap(); Pool::connect(&env::var("DATABASE_URL").expect("No database URL provided")).await.unwrap();

View File

@ -1,6 +1,4 @@
use axum::{routing::get, Router};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use log::warn;
use prometheus::{IntCounterVec, Opts, Registry}; use prometheus::{IntCounterVec, Opts, Registry};
lazy_static! { lazy_static! {
@ -26,21 +24,3 @@ pub fn init_metrics() {
REGISTRY.register(Box::new(REMINDER_FAIL_COUNTER.clone())).unwrap(); REGISTRY.register(Box::new(REMINDER_FAIL_COUNTER.clone())).unwrap();
REGISTRY.register(Box::new(COMMAND_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(&REGISTRY.gather());
res_custom.unwrap_or_else(|e| {
warn!("Error encoding metrics: {:?}", e);
String::new()
})
}

View File

@ -4,6 +4,7 @@ use std::env;
use log::{info, warn}; use log::{info, warn};
use poise::serenity_prelude::client::Context; use poise::serenity_prelude::client::Context;
use sd_notify::{self, NotifyState};
use sqlx::{Executor, MySql}; use sqlx::{Executor, MySql};
use tokio::{ use tokio::{
sync::broadcast::Receiver, sync::broadcast::Receiver,
@ -33,6 +34,16 @@ async fn _initialize(ctx: Context, pool: impl Executor<'_, Database = Database>
.flatten() .flatten()
.unwrap_or(10); .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 { loop {
let sleep_to = Instant::now() + Duration::from_secs(remind_interval); let sleep_to = Instant::now() + Duration::from_secs(remind_interval);
let reminders = sender::Reminder::fetch_reminders(pool).await; 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; sleep_until(sleep_to).await;
let _ = sd_notify::notify(false, &[NotifyState::Watchdog]);
} }
} }

1
src/web/fairings/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod metrics;

View File

@ -2,9 +2,10 @@ mod consts;
#[macro_use] #[macro_use]
mod macros; mod macros;
mod catchers; mod catchers;
mod fairings;
mod guards; mod guards;
mod metrics;
mod routes; mod routes;
pub mod string { pub mod string {
use std::{fmt::Display, str::FromStr}; use std::{fmt::Display, str::FromStr};
@ -79,7 +80,7 @@ use sqlx::{MySql, Pool};
use crate::web::{ use crate::web::{
consts::{CNC_GUILD, DISCORD_OAUTH_AUTHORIZE, DISCORD_OAUTH_TOKEN, SUBSCRIPTION_ROLES}, consts::{CNC_GUILD, DISCORD_OAUTH_AUTHORIZE, DISCORD_OAUTH_TOKEN, SUBSCRIPTION_ROLES},
metrics::MetricProducer, fairings::metrics::MetricProducer,
}; };
type Database = MySql; type Database = MySql;
@ -149,6 +150,7 @@ pub async fn initialize(
routes::report::report_error, routes::report::report_error,
routes::return_to_same_site, routes::return_to_same_site,
routes::terms, routes::terms,
routes::metrics,
], ],
) )
.mount( .mount(

View File

@ -2,11 +2,14 @@ pub mod dashboard;
pub mod login; pub mod login;
pub mod report; 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::{get, request::FlashMessage, serde::json::Value as JsonValue};
use rocket_dyn_templates::Template; use rocket_dyn_templates::Template;
use crate::metrics::REGISTRY;
pub type JsonResult = Result<JsonValue, JsonValue>; pub type JsonResult = Result<JsonValue, JsonValue>;
#[get("/")] #[get("/")]
@ -107,3 +110,19 @@ pub async fn help_iemanager() -> Template {
let map: HashMap<&str, String> = HashMap::new(); let map: HashMap<&str, String> = HashMap::new();
Template::render("support/iemanager", &map) 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(&REGISTRY.gather());
res_custom.unwrap_or_else(|e| {
warn!("Error encoding metrics: {:?}", e);
String::new()
})
}
}

View File

@ -7,8 +7,9 @@ Type=simple
ExecStart=/usr/bin/reminder-rs ExecStart=/usr/bin/reminder-rs
WorkingDirectory=/etc/reminder-rs WorkingDirectory=/etc/reminder-rs
Restart=always Restart=always
RestartSec=4 RestartSec=10
Environment="reminder_rs=warn,postman=warn" Environment="reminder_rs=warn,postman=warn"
WatchdogSec=60
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target