diff --git a/settings.mainnet.toml b/settings.mainnet.toml index fce017f..a848391 100644 --- a/settings.mainnet.toml +++ b/settings.mainnet.toml @@ -19,6 +19,9 @@ dobs_cache_directory = "cache/dobs" # expiration time indicator for cleaning whole dobs cache, zero means never clean dobs_cache_expiration_sec = 300 +# expiration time in minutes dedicated for type_id and type_script decoder cache, zero means always update +decoders_cache_expiration_minutes = 1440 + # all deployed on-chain Spore contracts binary hash (order from new to old) # refer to: https://github.com/sporeprotocol/spore-contract/blob/master/docs/VERSIONS.md [[available_spores]] diff --git a/settings.toml b/settings.toml index 028c208..a9d5207 100644 --- a/settings.toml +++ b/settings.toml @@ -11,7 +11,7 @@ ckb_rpc = "https://testnet.ckbapp.dev/" rpc_server_address = "0.0.0.0:8090" # directory that stores decoders on hard-disk, including on-chain and off-chain binary files -decoders_cache_directory = "cache/decoders" +decoders_cache_directory = "cache/decoders/testnet" # directory that stores DOBs rendering results on hard-disk dobs_cache_directory = "cache/dobs" @@ -19,6 +19,9 @@ dobs_cache_directory = "cache/dobs" # expiration time indicator for cleaning whole dobs cache, zero means never clean dobs_cache_expiration_sec = 300 +# expiration time in minutes dedicated for type_id and type_script decoder cache, zero means always update +decoders_cache_expiration_minutes = 1440 + # all deployed on-chain Spore contracts binary hash (order from new to old) # refer to: https://github.com/sporeprotocol/spore-contract/blob/master/docs/VERSIONS.md [[available_spores]] diff --git a/src/decoder/helpers.rs b/src/decoder/helpers.rs index 4755b1f..3db9581 100644 --- a/src/decoder/helpers.rs +++ b/src/decoder/helpers.rs @@ -32,6 +32,26 @@ fn build_type_script_search_option(type_script: Script) -> CellQueryOptions { CellQueryOptions::new_type(type_script) } +fn file_older_than_minutes(file_path: &PathBuf, minutes: u64) -> bool { + if minutes == 0 { + return true; + } + let metadata = match std::fs::metadata(file_path) { + Ok(m) => m, + Err(_) => return true, // File doesn't exist or we can't access it, so it's "old". + }; + + let file_time = match metadata.modified().or_else(|_| metadata.created()) { + Ok(time) => time, + Err(_) => return true, // Can't get a timestamp, assume it's old. + }; + + match file_time.elapsed() { + Ok(elapsed) => elapsed.as_secs() >= minutes * 60, + Err(_) => true, // System clock is earlier than file time, assume it's old to be safe. + } +} + fn build_batch_search_options( type_args: &[u8; 32], available_script_ids: &[ScriptId], @@ -267,7 +287,7 @@ pub async fn parse_decoder_path( DecoderLocationType::TypeId => { let hash = decoder.hash.as_ref().ok_or(Error::DecoderHashNotFound)?; decoder_path.push(format!("type_id_{}.bin", hex::encode(hash))); - if !decoder_path.exists() { + if file_older_than_minutes(&decoder_path, settings.decoders_cache_expiration_minutes) { let decoder_search_option = build_type_id_search_option(hash.clone().into()); let decoder_binary = fetch_decoder_binary(rpc, decoder_search_option).await?; std::fs::write(decoder_path.clone(), decoder_binary) @@ -284,7 +304,7 @@ pub async fn parse_decoder_path( "type_script_{}.bin", hex::encode(script.calc_script_hash().raw_data()) )); - if !decoder_path.exists() { + if file_older_than_minutes(&decoder_path, settings.decoders_cache_expiration_minutes) { let decoder_search_option = build_type_script_search_option(script); let decoder_binary = fetch_decoder_binary(rpc, decoder_search_option).await?; std::fs::write(decoder_path.clone(), decoder_binary) diff --git a/src/main.rs b/src/main.rs index 375225f..cd6a5ef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,18 @@ async fn main() { "server settings: {}", serde_json::to_string_pretty(&settings).unwrap() ); + + tracing::info!("ensuring cache directories exist"); + fs::create_dir_all(&settings.decoders_cache_directory) + .expect("failed to create decoders cache directory"); + fs::create_dir_all(&settings.dobs_cache_directory) + .expect("failed to create DOBs cache directory"); + tracing::info!( + "decoders cache directory: {:?}", + settings.decoders_cache_directory + ); + tracing::info!("DOBs cache directory: {:?}", settings.dobs_cache_directory); + let rpc_server_address = settings.rpc_server_address.clone(); let cache_expiration = settings.dobs_cache_expiration_sec; let decoder = decoder::DOBDecoder::new(settings); diff --git a/src/types.rs b/src/types.rs index fb72861..b389faf 100644 --- a/src/types.rs +++ b/src/types.rs @@ -94,6 +94,7 @@ impl From for ErrorObjectOwned { #[derive(Deserialize)] #[cfg_attr(test, derive(serde::Serialize, PartialEq, Debug))] pub struct ClusterDescriptionField { + #[allow(dead_code)] pub description: String, pub dob: DOBClusterFormat, } @@ -257,6 +258,7 @@ pub struct Settings { pub decoders_cache_directory: PathBuf, pub dobs_cache_directory: PathBuf, pub dobs_cache_expiration_sec: u64, + pub decoders_cache_expiration_minutes: u64, pub onchain_decoder_deployment: Vec, pub available_spores: Vec, pub available_clusters: Vec,