use axum::{
extract::State,
response::{IntoResponse, Redirect, Response},
};
use serde::Deserialize;
use tracing::info;
use crate::web::{AppState, auth::CurrentUser};
const MAX_PAUSE_MINUTES: i64 = 24 * 60;
#[derive(Debug, Deserialize)]
pub struct PauseForm {
pub minutes: i64,
}
impl AppState {
pub async fn blocking_pause(
_user: CurrentUser,
State(state): State<AppState>,
axum::Form(form): axum::Form<PauseForm>,
) -> Response {
let minutes = form.minutes.clamp(1, MAX_PAUSE_MINUTES);
state.resolver.pause_for_secs(minutes * 60);
info!(minutes, "blocking paused");
Redirect::to("/").into_response()
}
pub async fn blocking_resume(_user: CurrentUser, State(state): State<AppState>) -> Response {
state.resolver.resume();
info!("blocking resumed");
Redirect::to("/").into_response()
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
async fn state() -> (TempDir, AppState) {
let (dir, db) = crate::test_support::temp_db().await;
let st = AppState::for_test(db).await;
(dir, st)
}
#[tokio::test]
async fn pause_clamps_and_sets_deadline() {
let (_d, st) = state().await;
assert!(!st.resolver.blocking_paused());
st.resolver.pause_for_secs(5 * 60);
assert!(st.resolver.blocking_paused());
let remaining = st.pause_remaining().expect("paused");
assert!(remaining > 0 && remaining <= 5 * 60);
}
#[tokio::test]
async fn resume_clears_the_deadline() {
let (_d, st) = state().await;
st.resolver.pause_for_secs(30 * 60);
assert!(st.resolver.blocking_paused());
st.resolver.resume();
assert!(!st.resolver.blocking_paused());
assert_eq!(st.pause_remaining(), None);
}
}