use serde::{Deserialize, Serialize};
#[derive(Serialize)]
pub(crate) struct LockAcquireRequest {
pub(crate) timeout_ms: u64,
}
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct LockAcquireResponse {
pub(crate) lock_id: Option<String>,
}
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct TtlResponse {
pub(crate) ttl: Option<u64>,
}
#[derive(Serialize)]
pub(crate) struct RefreshTtlRequest {
pub(crate) ttl: u64,
}
#[cfg(test)]
#[allow(clippy::expect_used)] mod tests {
use super::*;
#[test]
fn lock_acquire_request_is_snake_case_on_the_wire() {
let json =
serde_json::to_string(&LockAcquireRequest { timeout_ms: 5000 }).expect("serializes");
assert_eq!(json, r#"{"timeout_ms":5000}"#);
}
#[test]
fn lock_acquire_response_parses_acquired() {
let resp: LockAcquireResponse =
serde_json::from_str(r#"{"lock_id":"a1b2c3d4-uuid"}"#).expect("parses");
assert_eq!(resp.lock_id.as_deref(), Some("a1b2c3d4-uuid"));
}
#[test]
fn lock_acquire_response_parses_contested_null() {
let resp: LockAcquireResponse =
serde_json::from_str(r#"{"lock_id":null}"#).expect("parses");
assert!(resp.lock_id.is_none());
}
#[test]
fn lock_acquire_response_rejects_camel_case() {
assert!(serde_json::from_str::<LockAcquireResponse>(r#"{"lockId":"x"}"#).is_err());
}
#[test]
fn ttl_response_parses_present_and_null() {
let some: TtlResponse = serde_json::from_str(r#"{"ttl":3542}"#).expect("parses");
assert_eq!(some.ttl, Some(3542));
let none: TtlResponse = serde_json::from_str(r#"{"ttl":null}"#).expect("parses");
assert!(none.ttl.is_none());
}
#[test]
fn refresh_ttl_request_is_snake_case_on_the_wire() {
let json = serde_json::to_string(&RefreshTtlRequest { ttl: 7200 }).expect("serializes");
assert_eq!(json, r#"{"ttl":7200}"#);
}
}