Skip to content

Commit

Permalink
Fix cache config (#102)
Browse files Browse the repository at this point in the history
* fix cache config

* fix

* add test
  • Loading branch information
ermalkaleci authored Sep 30, 2023
1 parent 7685e26 commit 7f38290
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 13 deletions.
30 changes: 30 additions & 0 deletions rpc_configs/ethereum.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
methods:
- method: eth_blockNumber
cache:
ttl_seconds: 1

- method: eth_chainId
cache:
Expand Down Expand Up @@ -43,21 +45,29 @@ methods:
ty: String

- method: eth_sendTransaction
cache:
size: 0
params:
- name: Transaction
ty: Bytes

- method: eth_sendRawTransaction
cache:
size: 0
params:
- name: transaction
ty: Bytes

- method: eth_call
cache:
ttl_seconds: 3
params:
- name: transaction
ty: Bytes

- method: eth_getTransactionCount
cache:
ttl_seconds: 3
params:
- name: address
ty: Bytes
Expand Down Expand Up @@ -102,6 +112,8 @@ methods:
inject: true

- method: eth_estimateGas
cache:
ttl_seconds: 3
params:
- name: transaction
ty: Bytes
Expand Down Expand Up @@ -131,41 +143,59 @@ methods:
ty: Bytes

- method: eth_isBlockFinalized
cache:
ttl_seconds: 3
params:
- name: block
ty: BlockTag
inject: true

- method: eth_isTransactionFinalized
cache:
ttl_seconds: 3
params:
- name: transactionHash
ty: Bytes

- method: eth_newFilter
cache:
size: 0
params:
- name: Filter
ty: Bytes

- method: eth_newBlockFilter
cache:
size: 0

- method: eth_newPendingTransactionFilter
cache:
size: 0

- method: eth_getFilterChanges
cache:
size: 0
params:
- name: address
ty: Bytes

- method: eth_getFilterLogs
cache:
size: 0
params:
- name: address
ty: Bytes

- method: eth_uninstallFilter
cache:
size: 0
params:
- name: FilterIdentifier
ty: Bytes

- method: eth_getLogs
cache:
size: 0
params:
- name: Filter
ty: Bytes
Expand Down
4 changes: 2 additions & 2 deletions src/config/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use serde::Deserialize;
#[derive(Clone, Deserialize, Debug, Eq, PartialEq)]
pub struct CacheParams {
#[serde(default)]
pub size: Option<u32>,
pub size: Option<usize>,
#[serde(default)]
pub ttl_seconds: Option<u32>,
pub ttl_seconds: Option<u64>,
}

#[derive(Clone, Deserialize, Debug, Eq, PartialEq)]
Expand Down
2 changes: 1 addition & 1 deletion src/extensions/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub struct CacheConfig {
// None means no cache expiration
#[serde(default)]
pub default_ttl_seconds: Option<u64>,
pub default_size: u32,
pub default_size: usize,
}

#[async_trait]
Expand Down
106 changes: 96 additions & 10 deletions src/middlewares/methods/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use jsonrpsee::{core::JsonValue, types::ErrorObjectOwned};
use opentelemetry::trace::FutureExt;

use crate::{
config::CacheParams,
extensions::cache::Cache as CacheExtension,
middleware::{Middleware, MiddlewareBuilder, NextFn, RpcMethod},
middlewares::{CallRequest, CallResult},
Expand All @@ -31,24 +32,34 @@ impl MiddlewareBuilder<RpcMethod, CallRequest, CallResult> for CacheMiddleware {
method: &RpcMethod,
extensions: &TypeRegistryRef,
) -> Option<Box<dyn Middleware<CallRequest, CallResult>>> {
let params = method.cache.as_ref()?;
if params.size == Some(0) {
return None;
}
let cache_ext = extensions
.read()
.await
.get::<CacheExtension>()
.expect("Cache extension not found");

let size =
NonZeroUsize::new(params.size.unwrap_or(cache_ext.config.default_size) as usize)?;
// do not cache if size is 0, otherwise use default size
let size = match method.cache {
Some(CacheParams { size: Some(0), .. }) => return None,
Some(CacheParams { size, .. }) => size.unwrap_or(cache_ext.config.default_size),
None => cache_ext.config.default_size,
};

let ttl_seconds = match method.cache {
// ttl zero means cache forever
Some(CacheParams {
ttl_seconds: Some(0),
..
}) => None,
Some(CacheParams { ttl_seconds, .. }) => {
ttl_seconds.or(cache_ext.config.default_ttl_seconds)
}
None => cache_ext.config.default_ttl_seconds,
};

let cache = Cache::new(
size,
params
.ttl_seconds
.map(|s| std::time::Duration::from_secs(s as u64)),
NonZeroUsize::new(size)?,
ttl_seconds.map(std::time::Duration::from_secs),
);

Some(Box::new(Self::new(cache)))
Expand Down Expand Up @@ -318,4 +329,79 @@ mod tests {
assert_eq!(res.unwrap(), json!(1));
assert_eq!(res2.unwrap(), json!(1));
}

#[tokio::test]
async fn cache_builder_works() {
let ext = crate::extensions::ExtensionsConfig {
cache: Some(crate::extensions::cache::CacheConfig {
default_size: 100,
default_ttl_seconds: Some(10),
}),
..Default::default()
}
.create_registry()
.await
.expect("Failed to create registry");

// disable cache with size = 0
let cache_middleware = CacheMiddleware::build(
&RpcMethod {
method: "foo".to_string(),
cache: Some(CacheParams {
size: Some(0),
ttl_seconds: None,
}),
params: vec![],
response: None,
},
&ext,
)
.await;
assert!(cache_middleware.is_none(), "Cache should be disabled");

// size none, use default size
let cache_middleware = CacheMiddleware::build(
&RpcMethod {
method: "foo".to_string(),
cache: Some(CacheParams {
size: None,
ttl_seconds: None,
}),
params: vec![],
response: None,
},
&ext,
)
.await;
assert!(cache_middleware.is_some(), "Cache should be enabled");

// custom size
let cache_middleware = CacheMiddleware::build(
&RpcMethod {
method: "foo".to_string(),
cache: Some(CacheParams {
size: Some(1),
ttl_seconds: None,
}),
params: vec![],
response: None,
},
&ext,
)
.await;
assert!(cache_middleware.is_some(), "Cache should be enabled");

// no cache params
let cache_middleware = CacheMiddleware::build(
&RpcMethod {
method: "foo".to_string(),
cache: None,
params: vec![],
response: None,
},
&ext,
)
.await;
assert!(cache_middleware.is_some(), "Cache should be enabled");
}
}

0 comments on commit 7f38290

Please sign in to comment.