use std::cell::Cell;
use tokio::task_local;
task_local! {
static BATCH_MODE: Cell<bool>;
}
#[allow(dead_code)]
pub fn is_batch_mode() -> bool {
BATCH_MODE.try_with(|cell| cell.get()).unwrap_or(false)
}
pub async fn with_batch_mode<F, T>(future: F) -> T
where
F: std::future::Future<Output = T>,
{
BATCH_MODE.scope(Cell::new(true), future).await
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_batch_mode_not_set_by_default() {
let result = is_batch_mode();
assert!(!result, "batch mode should be false by default");
}
#[tokio::test]
async fn test_with_batch_mode_sets_flag() {
let result = with_batch_mode(async { is_batch_mode() }).await;
assert!(result, "batch mode should be true inside with_batch_mode");
}
#[tokio::test]
async fn test_batch_mode_scoped_to_future() {
assert!(!is_batch_mode(), "batch mode should be false before");
with_batch_mode(async {
assert!(is_batch_mode(), "batch mode should be true inside");
})
.await;
assert!(!is_batch_mode(), "batch mode should be false after future completes");
}
#[tokio::test]
async fn test_nested_batch_mode_calls() {
let result = with_batch_mode(async {
let outer = is_batch_mode();
let inner = with_batch_mode(async { is_batch_mode() }).await;
(outer, inner)
})
.await;
assert!(result.0, "outer batch mode should be true");
assert!(result.1, "inner batch mode should be true");
}
#[tokio::test]
async fn test_batch_mode_unaffected_after_with_batch_mode() {
with_batch_mode(async {
assert!(is_batch_mode(), "first call should set batch mode");
})
.await;
assert!(!is_batch_mode(), "batch mode should be false between calls");
with_batch_mode(async {
assert!(is_batch_mode(), "second call should set batch mode");
})
.await;
assert!(!is_batch_mode(), "batch mode should be false after all calls");
}
}