File size: 3,504 Bytes
17f328f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | use std::path::PathBuf;
use serde::Deserialize;
use serde::Serialize;
use sha1::Digest;
use sha1::Sha1;
use tracing::warn;
use crate::AppInfo;
use crate::ConnectorDirectoryCacheKey;
pub(crate) const CONNECTOR_DIRECTORY_DISK_CACHE_SCHEMA_VERSION: u8 = 1;
const CONNECTOR_DIRECTORY_DISK_CACHE_DIR: &str = "cache/codex_app_directory";
#[derive(Clone)]
pub struct ConnectorDirectoryCacheContext {
pub(crate) codex_home: PathBuf,
pub(crate) cache_key: ConnectorDirectoryCacheKey,
}
impl ConnectorDirectoryCacheContext {
pub fn new(codex_home: PathBuf, cache_key: ConnectorDirectoryCacheKey) -> Self {
Self {
codex_home,
cache_key,
}
}
/// Returns the persisted connector directory cache path for this identity.
pub fn cache_path(&self) -> PathBuf {
let cache_key_json = serde_json::to_string(&self.cache_key).unwrap_or_default();
let cache_key_hash = sha1_hex(&cache_key_json);
self.codex_home
.join(CONNECTOR_DIRECTORY_DISK_CACHE_DIR)
.join(format!("{cache_key_hash}.json"))
}
}
pub(crate) enum CachedConnectorDirectoryDiskLoad {
Hit { connectors: Vec<AppInfo> },
Missing,
Invalid,
}
pub(crate) fn load_cached_directory_connectors_from_disk(
cache_context: &ConnectorDirectoryCacheContext,
) -> CachedConnectorDirectoryDiskLoad {
let cache_path = cache_context.cache_path();
let bytes = match std::fs::read(&cache_path) {
Ok(bytes) => bytes,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
return CachedConnectorDirectoryDiskLoad::Missing;
}
Err(err) => {
warn!(
cache_path = %cache_path.display(),
"failed to read connector directory disk cache: {err}"
);
return CachedConnectorDirectoryDiskLoad::Invalid;
}
};
let cache: ConnectorDirectoryDiskCache = match serde_json::from_slice(&bytes) {
Ok(cache) => cache,
Err(err) => {
warn!(
cache_path = %cache_path.display(),
"failed to parse connector directory disk cache: {err}"
);
let _ = std::fs::remove_file(cache_path);
return CachedConnectorDirectoryDiskLoad::Invalid;
}
};
if cache.schema_version != CONNECTOR_DIRECTORY_DISK_CACHE_SCHEMA_VERSION {
let _ = std::fs::remove_file(cache_path);
return CachedConnectorDirectoryDiskLoad::Invalid;
}
CachedConnectorDirectoryDiskLoad::Hit {
connectors: cache.connectors,
}
}
pub(crate) fn write_cached_directory_connectors_to_disk(
cache_context: &ConnectorDirectoryCacheContext,
connectors: &[AppInfo],
) {
let cache_path = cache_context.cache_path();
if let Some(parent) = cache_path.parent()
&& std::fs::create_dir_all(parent).is_err()
{
return;
}
let Ok(bytes) = serde_json::to_vec_pretty(&ConnectorDirectoryDiskCache {
schema_version: CONNECTOR_DIRECTORY_DISK_CACHE_SCHEMA_VERSION,
connectors: connectors.to_vec(),
}) else {
return;
};
let _ = std::fs::write(cache_path, bytes);
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct ConnectorDirectoryDiskCache {
schema_version: u8,
connectors: Vec<AppInfo>,
}
fn sha1_hex(value: &str) -> String {
let mut hasher = Sha1::new();
hasher.update(value.as_bytes());
let sha1 = hasher.finalize();
format!("{sha1:x}")
}
|