1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5use crate::storage::{StorageBackend, StorageEntry, StorageError};
6
7const LEASE_PREFIX: &str = "sys/leases/";
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct Lease {
11 pub id: Uuid,
12 pub token_id_hash: String,
13 pub engine_mount: String,
16 pub internal_data: serde_json::Value,
17 pub issued_at: DateTime<Utc>,
18 pub expires_at: DateTime<Utc>,
19}
20
21pub async fn store_lease(storage: &dyn StorageBackend, lease: &Lease) -> Result<(), StorageError> {
22 let path = format!("{LEASE_PREFIX}{}", lease.id);
23 let value = serde_json::to_vec(lease).map_err(|e| StorageError::Backend(e.to_string()))?;
24 storage
25 .put(
26 &path,
27 StorageEntry {
28 value,
29 expires_at: Some(lease.expires_at),
30 },
31 )
32 .await
33}
34
35pub async fn get_lease(storage: &dyn StorageBackend, id: Uuid) -> Result<Option<Lease>, StorageError> {
36 let path = format!("{LEASE_PREFIX}{id}");
37 let Some(entry) = storage.get(&path).await? else {
38 return Ok(None);
39 };
40 let lease: Lease =
41 serde_json::from_slice(&entry.value).map_err(|e| StorageError::Backend(e.to_string()))?;
42 Ok(Some(lease))
43}
44
45pub async fn list_expired_leases(
48 storage: &dyn StorageBackend,
49 now: DateTime<Utc>,
50) -> Result<Vec<Lease>, StorageError> {
51 let keys = storage.list_expired(LEASE_PREFIX, now).await?;
52 let mut leases = Vec::with_capacity(keys.len());
53 for key in keys {
54 if let Some(entry) = storage.get(&key).await?
55 && let Ok(lease) = serde_json::from_slice::<Lease>(&entry.value)
56 {
57 leases.push(lease);
58 }
59 }
60 Ok(leases)
61}
62
63pub async fn delete_lease(storage: &dyn StorageBackend, id: Uuid) -> Result<(), StorageError> {
64 storage.delete(&format!("{LEASE_PREFIX}{id}")).await
65}
66
67pub async fn list_leases(storage: &dyn StorageBackend) -> Result<Vec<Lease>, StorageError> {
71 let keys = storage.list(LEASE_PREFIX).await?;
72 let mut leases = Vec::with_capacity(keys.len());
73 for key in keys {
74 if let Some(entry) = storage.get(&key).await?
75 && let Ok(lease) = serde_json::from_slice::<Lease>(&entry.value)
76 {
77 leases.push(lease);
78 }
79 }
80 Ok(leases)
81}