diff --git a/plugins/examples/cln-plugin-startup.rs b/plugins/examples/cln-plugin-startup.rs index a377d81d6..a1b2f2a4f 100644 --- a/plugins/examples/cln-plugin-startup.rs +++ b/plugins/examples/cln-plugin-startup.rs @@ -13,15 +13,15 @@ async fn main() -> Result<(), anyhow::Error> { options::Value::Integer(42), "a test-option with default 42", )) - .rpcmethod("testmethod", "This is a test", Box::new(testmethod)) + .rpcmethod("testmethod", "This is a test", testmethod) .subscribe("connect", Box::new(connect_handler)) - .hook("peer_connected", Box::new(peer_connected_handler)) + //.hook("peer_connected", Box::new(peer_connected_handler)) .start() .await?; plugin.join().await } -fn testmethod(_p: Plugin<()>, _v: &serde_json::Value) -> Result { +async fn testmethod(_p: Plugin<()>, _v: serde_json::Value) -> Result { Ok(json!("Hello")) } diff --git a/plugins/src/lib.rs b/plugins/src/lib.rs index b77064995..9f8bb777a 100644 --- a/plugins/src/lib.rs +++ b/plugins/src/lib.rs @@ -4,6 +4,8 @@ use futures::sink::SinkExt; extern crate log; use log::trace; use std::collections::HashMap; +use std::future::Future; +use std::pin::Pin; use std::sync::Arc; use tokio::io::{AsyncRead, AsyncWrite}; use tokio::sync::Mutex; @@ -84,18 +86,18 @@ where /// Register a custom RPC method for the RPC passthrough from the /// main daemon - pub fn rpcmethod( - mut self, - name: &str, - description: &str, - callback: Callback, - ) -> Builder { + pub fn rpcmethod(mut self, name: &str, description: &str, callback: C) -> Builder + where + C: Send + Sync + 'static, + C: Fn(Plugin, Request) -> F + 'static, + F: Future + Send + Sync + 'static, + { self.rpcmethods.insert( name.to_string(), RpcMethod { name: name.to_string(), description: description.to_string(), - callback, + callback: Box::new(move |p, r| Box::pin(callback(p, r))), }, ); self @@ -171,9 +173,10 @@ where // TODO Split the two hashmaps once we fill in the hook // payload structs in messages.rs - let mut rpcmethods: HashMap> = + let mut rpcmethods: HashMap> = HashMap::from_iter(self.rpcmethods.drain().map(|(k, v)| (k, v.callback))); - rpcmethods.extend(self.hooks.clone().drain().map(|(k, v)| (k, v.callback))); + // TODO re-enable once hooks are async again + //rpcmethods.extend(self.hooks.clone().drain().map(|(k, v)| (k, v.callback))); // Start the PluginDriver to handle plugin IO tokio::spawn( @@ -237,8 +240,14 @@ where } } -type Callback = Box, &serde_json::Value) -> Result>; -type NotificationCallback = Box, &serde_json::Value) -> Result<(), Error>>; +// Just some type aliases so we don't get confused in a lisp-like sea +// of parentheses. +type Request = serde_json::Value; +type Response = Result; +type Callback = Box, &Request) -> Response>; +type AsyncCallback = + Box, Request) -> Pin + Send>> + Send + Sync>; +type NotificationCallback = Box, &Request) -> Result<(), Error>>; /// A struct collecting the metadata required to register a custom /// rpcmethod with the main daemon upon init. It'll get deconstructed @@ -247,7 +256,7 @@ struct RpcMethod where S: Clone + Send, { - callback: Callback, + callback: AsyncCallback, description: String, name: String, } @@ -291,9 +300,8 @@ struct PluginDriver where S: Send + Clone, { - plugin: Plugin, - rpcmethods: HashMap>, + rpcmethods: HashMap>, #[allow(dead_code)] // Unused until we fill in the Hook structs. hooks: HashMap>, @@ -420,7 +428,7 @@ where method, params ); - callback(plugin.clone(), params) + callback(plugin.clone(), params.clone()).await } async fn dispatch_custom_notification( diff --git a/tests/test_cln_rs.py b/tests/test_cln_rs.py index 5c2d89108..fa8840f1f 100644 --- a/tests/test_cln_rs.py +++ b/tests/test_cln_rs.py @@ -55,5 +55,5 @@ def test_plugin_start(node_factory): assert l1.rpc.testmethod() == "Hello" l1.connect(l2) - l1.daemon.wait_for_log(r'Got a connect hook call') + #l1.daemon.wait_for_log(r'Got a connect hook call') l1.daemon.wait_for_log(r'Got a connect notification')