-
Notifications
You must be signed in to change notification settings - Fork 6
feat: make decoders cache refreshable by adding a new setting option #36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,14 +11,17 @@ 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" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| # directory that stores DOBs rendering results on hard-disk | ||
| 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]] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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. | ||
| } | ||
|
Comment on lines
+39
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error handling in this function consistently returns |
||
| } | ||
|
Comment on lines
+35
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function is logically correct. However, it can be made more concise and idiomatic by chaining fn file_older_than_minutes(file_path: &PathBuf, minutes: u64) -> bool {
if minutes == 0 {
return true;
}
let threshold = std::time::Duration::from_secs(minutes * 60);
// Treat the file as "old" (return true) if metadata can't be read,
// timestamps are unavailable, or if the system clock is behind the file time.
std::fs::metadata(file_path)
.and_then(|m| m.modified().or_else(|_| m.created()))
.map(|time| {
time.elapsed()
.map(|elapsed| elapsed >= threshold)
.unwrap_or(true) // System clock is earlier than file time, assume old.
})
.unwrap_or(true) // File doesn't exist or timestamps unavailable, assume old.
} |
||
|
|
||
| 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) | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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"); | ||||||||||||||||||
|
Comment on lines
+30
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using
Comment on lines
+30
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using
Suggested change
|
||||||||||||||||||
| 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); | ||||||||||||||||||
|
|
||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a good practice to namespace the cache directory for testnet to avoid conflicts. For consistency and to prevent any potential confusion when switching between environments, you might consider also namespacing the mainnet cache directory in
settings.mainnet.toml(e.g., tocache/decoders/mainnet).