lean_ctx/core/intelligence_runtime/
lease.rs1use std::sync::{Arc, RwLock};
12
13#[derive(Clone, PartialEq, Eq)]
15pub struct RuntimeLeaseV1(Vec<u8>);
16
17impl RuntimeLeaseV1 {
18 pub fn from_bytes(bytes: Vec<u8>) -> Self {
19 Self(bytes)
20 }
21
22 pub(crate) fn as_bytes(&self) -> &[u8] {
23 &self.0
24 }
25}
26
27impl std::fmt::Debug for RuntimeLeaseV1 {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 write!(f, "RuntimeLeaseV1({} bytes)", self.0.len())
31 }
32}
33
34pub trait LeaseSource: Send + Sync {
36 fn current(&self) -> Option<RuntimeLeaseV1>;
38}
39
40static SOURCE: RwLock<Option<Arc<dyn LeaseSource>>> = RwLock::new(None);
41
42pub fn set_lease_source(source: Box<dyn LeaseSource>) {
44 let source: Arc<dyn LeaseSource> = Arc::from(source);
45 *SOURCE
46 .write()
47 .unwrap_or_else(std::sync::PoisonError::into_inner) = Some(source);
48}
49
50pub(crate) fn current_lease() -> Option<RuntimeLeaseV1> {
52 let source = SOURCE
54 .read()
55 .unwrap_or_else(std::sync::PoisonError::into_inner)
56 .clone()?;
57 source.current()
58}
59
60pub(crate) fn current_lease_b64() -> Option<String> {
62 use base64::Engine as _;
63 let lease = current_lease()?;
64 Some(base64::engine::general_purpose::STANDARD.encode(lease.as_bytes()))
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 struct Fixed(Option<Vec<u8>>);
72
73 impl LeaseSource for Fixed {
74 fn current(&self) -> Option<RuntimeLeaseV1> {
75 self.0.clone().map(RuntimeLeaseV1::from_bytes)
76 }
77 }
78
79 struct Reentrant;
82
83 impl LeaseSource for Reentrant {
84 fn current(&self) -> Option<RuntimeLeaseV1> {
85 set_lease_source(Box::new(Fixed(Some(b"after".to_vec()))));
86 Some(RuntimeLeaseV1::from_bytes(b"during".to_vec()))
87 }
88 }
89
90 #[test]
92 fn the_registered_source_decides_and_a_later_one_replaces_it() {
93 set_lease_source(Box::new(Fixed(None)));
94 assert_eq!(current_lease(), None);
95
96 set_lease_source(Box::new(Fixed(Some(b"lease-1".to_vec()))));
97 let lease = current_lease().expect("registered lease");
98 assert_eq!(lease.as_bytes(), b"lease-1");
99 assert_eq!(format!("{lease:?}"), "RuntimeLeaseV1(7 bytes)");
100
101 set_lease_source(Box::new(Reentrant));
102 assert_eq!(current_lease().expect("lease").as_bytes(), b"during");
103 assert_eq!(current_lease().expect("lease").as_bytes(), b"after");
104 }
105}