klieo_core/
server_outbound.rs1use async_trait::async_trait;
11use std::time::Duration;
12
13#[async_trait]
20pub trait ServerOutbound: Send + Sync {
21 async fn outbound_request(
24 &self,
25 method: &str,
26 params: serde_json::Value,
27 timeout: Duration,
28 ) -> Result<serde_json::Value, ServerOutboundError>;
29}
30
31#[derive(Debug, thiserror::Error)]
33#[non_exhaustive]
34pub enum ServerOutboundError {
35 #[error("outbound request timed out")]
37 Timeout,
38 #[error("peer returned error: code={code} message={message}")]
40 PeerError {
41 code: i64,
43 message: String,
45 },
46 #[error("transport closed")]
48 TransportClosed,
49 #[error("outbound channel unsupported on this transport")]
52 Unsupported,
53 #[error("outbound frame serialisation failed: {0}")]
56 Serialisation(#[source] serde_json::Error),
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn display_messages_are_stable() {
65 assert_eq!(
66 ServerOutboundError::Timeout.to_string(),
67 "outbound request timed out"
68 );
69 assert_eq!(
70 ServerOutboundError::PeerError {
71 code: -32601,
72 message: "Method not found".to_string(),
73 }
74 .to_string(),
75 "peer returned error: code=-32601 message=Method not found"
76 );
77 assert_eq!(
78 ServerOutboundError::TransportClosed.to_string(),
79 "transport closed"
80 );
81 assert_eq!(
82 ServerOutboundError::Unsupported.to_string(),
83 "outbound channel unsupported on this transport"
84 );
85 }
86
87 #[test]
88 fn serialisation_variant_display_starts_with_prefix() {
89 let serde_err = serde_json::from_str::<serde_json::Value>("{invalid}").unwrap_err();
90 let msg = ServerOutboundError::Serialisation(serde_err).to_string();
91 assert!(
92 msg.starts_with("outbound frame serialisation failed: "),
93 "unexpected display message: {msg}"
94 );
95 }
96
97 #[test]
98 fn trait_object_is_send_and_sync() {
99 fn assert_send_sync<T: Send + Sync + ?Sized>() {}
100 assert_send_sync::<dyn ServerOutbound>();
101 }
102
103 #[tokio::test]
104 async fn outbound_request_stub_dispatches_and_returns_value() {
105 struct StubOutbound;
106 #[async_trait::async_trait]
107 impl ServerOutbound for StubOutbound {
108 async fn outbound_request(
109 &self,
110 _method: &str,
111 _params: serde_json::Value,
112 _timeout: Duration,
113 ) -> Result<serde_json::Value, ServerOutboundError> {
114 Ok(serde_json::json!({"ok": true}))
115 }
116 }
117 let stub = StubOutbound;
118 let result = stub
119 .outbound_request(
120 "test/method",
121 serde_json::Value::Null,
122 Duration::from_secs(5),
123 )
124 .await
125 .unwrap();
126 assert_eq!(result["ok"], true);
127 }
128}