use crate::RullstValue;
use std::future::Future;
tokio::task_local! {
pub static CURRENT_TENANT: RullstValue;
}
pub async fn with_tenant<T, F, R>(tenant_id: T, f: F) -> R
where
T: Into<RullstValue>,
F: Future<Output = R>,
{
CURRENT_TENANT.scope(tenant_id.into(), f).await
}
pub fn get_tenant_id() -> Option<RullstValue> {
CURRENT_TENANT.try_with(|t| t.clone()).ok()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_tenant_id_returns_none_outside_scope() {
let id = get_tenant_id();
assert!(id.is_none(), "Expected None outside a tenant scope");
}
#[tokio::test]
async fn test_with_tenant_sets_and_restores() {
let result = with_tenant("acme", async { get_tenant_id() }).await;
assert!(matches!(result, Some(RullstValue::String(ref s)) if s == "acme"));
assert!(get_tenant_id().is_none());
}
#[tokio::test]
async fn test_nested_tenant_scopes() {
let _ = with_tenant("outer", async {
let outer_id = get_tenant_id();
assert!(matches!(outer_id, Some(RullstValue::String(ref s)) if s == "outer"));
let _ = with_tenant("inner", async {
let inner_id = get_tenant_id();
assert!(matches!(inner_id, Some(RullstValue::String(ref s)) if s == "inner"));
})
.await;
let restored_outer_id = get_tenant_id();
assert!(matches!(restored_outer_id, Some(RullstValue::String(ref s)) if s == "outer"));
})
.await;
}
}