diff --git a/examples/leaderboard.rs b/examples/leaderboard.rs index 25795a6..40ae039 100644 --- a/examples/leaderboard.rs +++ b/examples/leaderboard.rs @@ -1,5 +1,6 @@ use anyhow::{Result, bail}; use jiff::Zoned; +use job_watcher::axum::{Router, extract::State, routing::get}; use job_watcher::{ AppBuilder, Heartbeat, TaskLabel, WatchedTask, WatchedTaskOutput, WatcherAppContext, config::{Delay, TaskConfig, WatcherConfig}, @@ -83,6 +84,24 @@ impl WatcherAppContext for DummyApp { fn title(&self) -> String { "Example application Status".to_owned() } + + fn extend_router(&self, router: Router) -> Router + where + S: Clone + Send + Sync + 'static, + { + let custom_router = Router::new() + .route("/", get(hello_handler)) + .with_state(HelloState(self.0.clone())); + + router.nest_service("/hello", custom_router) + } +} + +#[derive(Clone)] +struct HelloState(Zoned); + +async fn hello_handler(State(state): State) -> String { + format!("Hello from custom route! App live since {}", state.0) } impl WatchedTask for LeaderBoard { diff --git a/src/config.rs b/src/config.rs index b192ce6..6773e0b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,4 +1,3 @@ -use crate::defaults; use std::collections::HashMap; #[derive(serde::Deserialize, serde::Serialize, Clone, Copy, Debug)] @@ -13,17 +12,24 @@ pub enum Delay { #[derive(serde::Deserialize, serde::Serialize, Clone, Copy, Debug)] #[serde(rename_all = "kebab-case", deny_unknown_fields)] pub struct TaskConfig { - /// Delay between runs + /// Delay between successful task executions. pub delay: Delay, - /// How many seconds before we should consider the result out of date + /// Number of seconds a task can run before it is considered "out of date". /// - /// This does not include the delay time + /// If a task's execution time exceeds this value, its status will be flagged + /// accordingly. This is useful for monitoring tasks that might be stuck. + /// + /// Setting this also enables a hard timeout on task execution. If a task + /// runs for longer than `MAX_TASK_SECONDS` (180 seconds), it will be + /// cancelled. pub out_of_date: Option, - /// How many times to retry before giving up, overriding the general watcher - /// config + /// Number of times to retry a failing task before giving up. + /// + /// This overrides the global `retries` setting in `WatcherConfig`. pub retries: Option, - /// How many seconds to delay between retries, overriding the general - /// watcher config + /// Delay in seconds between retries of a failing task. + /// + /// This overrides the global `delay_between_retries` setting in `WatcherConfig`. pub delay_between_retries: Option, } @@ -31,20 +37,17 @@ pub struct TaskConfig { #[serde(rename_all = "kebab-case", deny_unknown_fields)] pub struct WatcherConfig { /// How many times to retry before giving up - #[serde(default = "defaults::retries")] pub retries: usize, /// How many seconds to delay between retries - #[serde(default = "defaults::delay_between_retries")] pub delay_between_retries: u32, - #[serde(default)] pub tasks: HashMap, } impl Default for WatcherConfig { fn default() -> Self { Self { - retries: defaults::retries(), - delay_between_retries: defaults::delay_between_retries(), + retries: 6, + delay_between_retries: 20, tasks: Default::default(), } } diff --git a/src/defaults.rs b/src/defaults.rs deleted file mode 100644 index 60c1cf3..0000000 --- a/src/defaults.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub(super) fn retries() -> usize { - 6 -} - -pub(super) fn delay_between_retries() -> u32 { - 20 -} diff --git a/src/lib.rs b/src/lib.rs index 342996e..07a6844 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,9 +22,9 @@ mod rest_api; pub mod config; -mod defaults; use anyhow::{Context, Result}; +pub use axum; use axum::{ Json, http::{self, HeaderValue}, @@ -45,6 +45,12 @@ pub trait WatcherAppContext { fn watcher_config(&self) -> WatcherConfig; fn triggers_alert(&self, label: &TaskLabel, selected_label: Option<&TaskLabel>) -> bool; fn show_output(&self, label: &TaskLabel) -> bool; + fn extend_router(&self, router: axum::Router) -> axum::Router + where + S: Clone + Send + Sync + 'static, + { + router + } } #[derive( diff --git a/src/rest_api.rs b/src/rest_api.rs index 95a96b5..a2a5827 100644 --- a/src/rest_api.rs +++ b/src/rest_api.rs @@ -1,9 +1,9 @@ -use std::{convert::Infallible, sync::Arc}; +use std::{convert::Infallible, sync::Arc, time::Duration}; use anyhow::Result; use axum::{ extract::{Path, State}, - http::{self, HeaderMap, header}, + http::{self, HeaderMap, StatusCode, header}, response::IntoResponse, routing::get, }; @@ -12,6 +12,7 @@ use tower::ServiceBuilder; use tower_http::{ cors::CorsLayer, limit::RequestBodyLimitLayer, + timeout::TimeoutLayer, trace::{self, TraceLayer}, }; use tracing::Level; @@ -40,9 +41,10 @@ pub(crate) async fn start_rest_api