1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
# karyon jsonrpc
A fast and lightweight async implementation of [JSON-RPC
2.0](https://www.jsonrpc.org/specification).
features:
- Supports TCP, TLS, WebSocket, and Unix protocols.
- Uses `smol`(async-std) as the async runtime, but also supports `tokio` via the
`tokio` feature.
- Allows registration of multiple services (structs) of different types on a
single server.
- Supports pub/sub
- Allows passing an `async_executors::Executor` or tokio's `Runtime` when building
the server.
## Example
```rust
use std::{sync::Arc, time::Duration};
use serde_json::Value;
use smol::stream::StreamExt;
use karyon_jsonrpc::{
Error, Server, Client, rpc_impl, rpc_pubsub_impl, SubscriptionID, ArcChannel
};
struct HelloWorld {}
#[rpc_impl]
impl HelloWorld {
async fn say_hello(&self, params: Value) -> Result<Value, Error> {
let msg: String = serde_json::from_value(params)?;
Ok(serde_json::json!(format!("Hello {msg}!")))
}
async fn foo(&self, params: Value) -> Result<Value, Error> {
Ok(serde_json::json!("foo!"))
}
async fn bar(&self, params: Value) -> Result<Value, Error> {
Ok(serde_json::json!("bar!"))
}
}
#[rpc_pubsub_impl]
impl HelloWorld {
async fn log_subscribe(&self, chan: ArcChannel, method: String, _params: Value) -> Result<Value, Error> {
let sub = chan.new_subscription(&method).await;
let sub_id = sub.id.clone();
smol::spawn(async move {
loop {
smol::Timer::after(std::time::Duration::from_secs(1)).await;
if let Err(err) = sub.notify(serde_json::json!("Hello")).await {
println!("Error send notification {err}");
break;
}
}
})
.detach();
Ok(serde_json::json!(sub_id))
}
async fn log_unsubscribe(&self, chan: ArcChannel, method: String, params: Value) -> Result<Value, Error> {
let sub_id: SubscriptionID = serde_json::from_value(params)?;
chan.remove_subscription(&sub_id).await;
Ok(serde_json::json!(true))
}
}
// Server
async {
let service = Arc::new(HelloWorld {});
// Creates a new server
let server = Server::builder("tcp://127.0.0.1:60000")
.expect("create new server builder")
.service(service.clone())
.pubsub_service(service)
.build()
.await
.expect("build the server");
// Starts the server
server.start().await;
smol::Timer::after(Duration::MAX).await;
};
// Client
async {
// Creates a new client
let client = Client::builder("tcp://127.0.0.1:60000")
.expect("create new client builder")
.build()
.await
.expect("build the client");
let result: String = client.call("HelloWorld.say_hello", "world".to_string())
.await
.expect("send a request");
let (sub_id, sub) = client
.subscribe("HelloWorld.log_subscribe", ())
.await
.expect("Subscribe to log_subscribe method");
smol::spawn(async move {
sub.for_each(|m| {
println!("Receive new notification: {m}");
})
.await
})
.detach();
smol::Timer::after(std::time::Duration::from_secs(5)).await;
client
.unsubscribe("HelloWorld.log_unsubscribe", sub_id)
.await
.expect("Unsubscribe from log_unsubscirbe method");
};
```
|