Skip to content

Commit 56e60a3

Browse files
feat: add merge_if_module_configured_with that accepts a closure (#20158)
1 parent 193af22 commit 56e60a3

File tree

1 file changed

+55
-0
lines changed
  • crates/rpc/rpc-builder/src

1 file changed

+55
-0
lines changed

crates/rpc/rpc-builder/src/lib.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,6 +1665,27 @@ impl TransportRpcModules {
16651665
Ok(())
16661666
}
16671667

1668+
/// Merge the given [`Methods`] in all configured transport modules if the given
1669+
/// [`RethRpcModule`] is configured for the transport, using a closure to lazily
1670+
/// create the methods only when needed.
1671+
///
1672+
/// The closure is only called if at least one transport has the module configured.
1673+
/// Fails if any of the methods in the closure result is present already.
1674+
pub fn merge_if_module_configured_with<F>(
1675+
&mut self,
1676+
module: RethRpcModule,
1677+
f: F,
1678+
) -> Result<(), RegisterMethodError>
1679+
where
1680+
F: FnOnce() -> Methods,
1681+
{
1682+
// Early return if module not configured for any transport
1683+
if !self.module_config().contains_any(&module) {
1684+
return Ok(());
1685+
}
1686+
self.merge_if_module_configured(module, f())
1687+
}
1688+
16681689
/// Merge the given [Methods] in the configured http methods.
16691690
///
16701691
/// Fails if any of the methods in other is present already.
@@ -2593,4 +2614,38 @@ mod tests {
25932614
assert!(ipc.method("eth_existing").is_none());
25942615
assert!(ipc.method("eth_new").is_none());
25952616
}
2617+
2618+
#[test]
2619+
fn test_merge_if_module_configured_with_lazy_evaluation() {
2620+
// Create a config that enables RethRpcModule::Eth for HTTP only
2621+
let config = TransportRpcModuleConfig::default().with_http([RethRpcModule::Eth]);
2622+
2623+
let mut modules =
2624+
TransportRpcModules { config, http: Some(RpcModule::new(())), ws: None, ipc: None };
2625+
2626+
// Track whether closure was called
2627+
let mut closure_called = false;
2628+
2629+
// Test with configured module - closure should be called
2630+
let result = modules.merge_if_module_configured_with(RethRpcModule::Eth, || {
2631+
closure_called = true;
2632+
let mut methods = RpcModule::new(());
2633+
methods.register_method("eth_test", |_, _, _| "test").unwrap();
2634+
methods.into()
2635+
});
2636+
2637+
assert!(result.is_ok());
2638+
assert!(closure_called, "Closure should be called when module is configured");
2639+
assert!(modules.http.as_ref().unwrap().method("eth_test").is_some());
2640+
2641+
// Reset and test with unconfigured module - closure should NOT be called
2642+
closure_called = false;
2643+
let result = modules.merge_if_module_configured_with(RethRpcModule::Debug, || {
2644+
closure_called = true;
2645+
RpcModule::new(()).into()
2646+
});
2647+
2648+
assert!(result.is_ok());
2649+
assert!(!closure_called, "Closure should NOT be called when module is not configured");
2650+
}
25962651
}

0 commit comments

Comments
 (0)