* 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 de4ecf8dd6
15 changed files with 83 additions and 110 deletions

87
Cargo.lock generated
View File

@ -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]]

View File

@ -1,6 +1,6 @@
[package]
name = "reminder-rs"
version = "1.7.18"
version = "1.7.19"
authors = ["Jude Southworth <judesouthworth@pm.me>"]
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"

View File

@ -22,8 +22,8 @@ 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),
),

View File

@ -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),
),

View File

@ -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(())
}

View File

@ -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(())
}

View File

@ -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(())
}

View File

@ -212,7 +212,6 @@ async fn _main(tx: Sender<()>) -> Result<(), Box<dyn StdError + Send + Sync>> {
// 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();

View File

@ -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(&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 poise::serenity_prelude::client::Context;
use sd_notify::{self, NotifyState};
use sqlx::{Executor, MySql};
use tokio::{
sync::broadcast::Receiver,
@ -33,6 +34,15 @@ async fn _initialize(ctx: Context, pool: impl Executor<'_, Database = Database>
.flatten()
.unwrap_or(10);
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 +56,6 @@ async fn _initialize(ctx: Context, pool: impl Executor<'_, Database = Database>
}
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]
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(

View File

@ -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<JsonValue, JsonValue>;
#[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(&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
WorkingDirectory=/etc/reminder-rs
Restart=always
RestartSec=4
RestartSec=10
Environment="reminder_rs=warn,postman=warn"
WatchdogSec=60
[Install]
WantedBy=multi-user.target