memvid_cli/
ticket_cache.rs1use std::fs;
7use std::path::PathBuf;
8
9use anyhow::{Context, Result};
10use serde::{Deserialize, Serialize};
11use uuid::Uuid;
12
13use crate::config::CliConfig;
14
15const CACHE_DIR_NAME: &str = "tickets";
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct CachedTicket {
20 pub memory_id: Uuid,
21 pub issuer: String,
22 pub seq_no: i64,
23 pub expires_in: u64,
24 #[serde(default)]
25 pub capacity_bytes: Option<u64>,
26 pub signature: String,
27}
28
29pub fn store(config: &CliConfig, entry: &CachedTicket) -> Result<()> {
30 let path = cache_path(config, &entry.memory_id);
31 if let Some(parent) = path.parent() {
32 fs::create_dir_all(parent).with_context(|| {
33 format!(
34 "failed to create ticket cache directory: {}",
35 parent.display()
36 )
37 })?;
38 }
39 let tmp = path.with_extension("json.tmp");
40 let data = serde_json::to_vec_pretty(entry)?;
41 fs::write(&tmp, data)
42 .with_context(|| format!("failed to write ticket cache file: {}", tmp.display()))?;
43 fs::rename(&tmp, &path).with_context(|| {
44 format!(
45 "failed to atomically persist ticket cache file: {}",
46 path.display()
47 )
48 })?;
49 Ok(())
50}
51
52pub fn load(config: &CliConfig, memory_id: &Uuid) -> Result<CachedTicket> {
53 let path = cache_path(config, memory_id);
54 let data = fs::read(&path)
55 .with_context(|| format!("no cached ticket available for memory {}", memory_id))?;
56 let entry = serde_json::from_slice(&data)
57 .with_context(|| format!("failed to parse cached ticket: {}", path.display()))?;
58 Ok(entry)
59}
60
61fn cache_path(config: &CliConfig, memory_id: &Uuid) -> PathBuf {
62 config
63 .cache_dir
64 .join(CACHE_DIR_NAME)
65 .join(format!("{memory_id}.json"))
66}