use crate::session::id::SessionId;
pub(super) const DEFAULT_PREFIX: &str = "axess";
pub(super) const DEFAULT_MAX_PAYLOAD_BYTES: usize = 64 * 1024;
pub(super) fn session_key(prefix: &str, id: &SessionId) -> String {
format!("{prefix}:sess:{id}")
}
pub(super) fn registry_key(prefix: &str, user_id: &str) -> String {
format!("{prefix}:reg:{user_id}")
}
pub(super) fn revocation_session_channel(prefix: &str, session_id: &str) -> String {
format!("{prefix}:revoked-session:{session_id}")
}
pub(super) fn revocation_user_channel(prefix: &str, user_id: &str) -> String {
format!("{prefix}:revoked-user:{user_id}")
}
pub(super) const CYCLE_SCRIPT: &str = r#"
redis.call('SET', KEYS[2], ARGV[1], 'EX', tonumber(ARGV[2]))
if KEYS[1] ~= KEYS[2] then
redis.call('DEL', KEYS[1])
end
return 1
"#;
pub(super) fn script_unavailable(err: &fred::error::Error) -> bool {
let text = err.details().to_ascii_lowercase();
[
"crossslot",
"unknown command",
"noscript",
"scripting",
"noperm",
]
.iter()
.any(|needle| text.contains(needle))
}
use std::time::Duration;
pub(super) fn ex_seconds(ttl: Duration) -> Option<i64> {
if ttl.is_zero() {
return None;
}
Some(ttl.as_secs().clamp(1, i64::MAX as u64) as i64)
}
pub(super) fn registry_member_ttl_ms(ttl: Duration) -> i64 {
ttl.as_millis().min(i64::MAX as u128) as i64
}
pub(super) fn registry_member_live(score_ms: f64, now_ms: i64, member_ttl_ms: i64) -> bool {
score_ms + member_ttl_ms as f64 > now_ms as f64
}
pub(super) fn registry_cutoff_ms(now_ms: i64, member_ttl_ms: i64) -> f64 {
now_ms as f64 - member_ttl_ms as f64
}
pub(super) fn registry_key_ttl_secs(ttl: Duration) -> i64 {
let ms = registry_member_ttl_ms(ttl);
(ms / 1000 + i64::from(ms % 1000 != 0)).max(1)
}
#[derive(Debug, thiserror::Error)]
pub enum ValkeyStoreError {
#[error("connection error: {0}")]
Connection(#[source] fred::error::Error),
#[error("codec error: {0}")]
Codec(#[from] crate::session::storage::session_codec::SqlStoreError),
#[error("encoded session payload too large ({size} bytes, max {max} bytes)")]
PayloadTooLarge {
size: usize,
max: usize,
},
}
impl From<fred::error::Error> for ValkeyStoreError {
fn from(e: fred::error::Error) -> Self {
Self::Connection(e)
}
}