Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(server): JSON-RPC specific middleware #1215

Merged
merged 33 commits into from
Nov 3, 2023
Merged

Conversation

niklasad1
Copy link
Member

@niklasad1 niklasad1 commented Oct 12, 2023

This PR replaces the RpcLogger with a composable middleware similar to the tower::Service trait which runs on every RPC call and batch requests may call this middleware several times.

In that way jsonrpsee can utilize the tower::ServiceBuilder and use the nice layer APIs but jsonrpsee has trait called RpcServiceT which is very similar to the tower::Service trait but simplifies things with concrete types and doesn't require &mut self.

The downside with having a different service trait than tower is that the built-in layers won't work on jsonrpsee.

Example of custom middleware implementation.

#[derive(Default, Clone)]
struct Counter {
	/// (Number of started requests, number of finished requests)
	requests: (u32, u32),
	/// Mapping method names to (number of calls, ids of successfully completed calls)
	calls: HashMap<String, (u32, Vec<Id<'static>>)>,
}

#[derive(Clone)]
pub struct CounterMiddleware<S> {
	service: S,
	counter: Arc<Mutex<Counter>>,
}

#[async_trait]
impl<'a, S> RpcServiceT<'a> for Timings<S>
where
	S: Send + Sync + RpcServiceT<'a>,
{
        // Meta has bunch of data regarding the connection such as URL, HTTP Headers, connection ID and similar.
	async fn call(&self, req: Request<'a>, t: TransportProtocol) -> MethodResponse {
		{
			let mut n = self.counter.lock().unwrap();
			n.requests.0 += 1;
			let entry = n.calls.entry(request.method.to_string()).or_insert((0, Vec::new()));
			entry.0 += 1;
		}

		let rp = self.service.call(request.clone(), t).await;

		{
			let mut n = self.counter.lock().unwrap();
			n.requests.1 += 1;
			if rp.is_success() {
				n.calls.get_mut(request.method.as_ref()).unwrap().1.push(request.id.into_owned());
			}
		}

		rp
	}
}

async fn run_server() -> anyhow::Result<SocketAddr> {
        // Based on the layer_fn it's possible to decide whether create a new state per connection or share it for all connections.
        //
        // The general use-case it to wrap the state in `Arc<Mutex>` thus the guidelines are
        // clone()  -> shared state` 
        // new() -> each connection has its own state
        //
        // Here we create "a separate state" per connection
	let rpc_middleware = tower::ServiceBuilder::new().layer_fn(|service| Counter { service, counter: Default::default() });
	let server = Server::builder().set_rpc_middleware(rpc_middleware).build("127.0.0.1:0").await?;
}

Resolves #1157, resolves #1128, resolves #989, resolves #1190

Benches

➜  benches git:(master) ✗ critcmp
group                                              master                                   middleware                               new
-----                                              ------                                   ----------                               ---
async/http_batch_requests/fast_call/10             1.64    92.6±13.15µs 105.4 KElem/sec     1.00     56.4±6.93µs 173.0 KElem/sec     1.64    92.6±13.15µs 105.4 KElem/sec
async/http_batch_requests/fast_call/100            1.29   302.3±51.01µs 323.0 KElem/sec     1.00   234.0±36.47µs 417.4 KElem/sec     1.29   302.3±51.01µs 323.0 KElem/sec
async/http_batch_requests/fast_call/2              1.39    81.0±14.37µs 24.1 KElem/sec      1.00     58.2±9.28µs 33.6 KElem/sec      1.39    81.0±14.37µs 24.1 KElem/sec
async/http_batch_requests/fast_call/5              1.29     72.7±9.25µs 67.1 KElem/sec      1.00    56.3±10.87µs 86.8 KElem/sec      1.29     72.7±9.25µs 67.1 KElem/sec
async/http_batch_requests/fast_call/50             1.23   177.2±26.95µs 275.5 KElem/sec     1.00   144.1±31.56µs 338.7 KElem/sec     1.23   177.2±26.95µs 275.5 KElem/sec
async/http_concurrent_conn_calls/fast_call/1024    1.00    46.3±16.01ms        ? ?/sec      1.00    46.3±16.34ms        ? ?/sec      1.00    46.3±16.01ms        ? ?/sec
async/http_concurrent_conn_calls/fast_call/128     1.01      5.8±2.40ms        ? ?/sec      1.00      5.7±2.55ms        ? ?/sec      1.01      5.8±2.40ms        ? ?/sec
async/http_concurrent_conn_calls/fast_call/16      1.00  850.6±893.93µs        ? ?/sec      1.01  859.3±911.11µs        ? ?/sec      1.00  850.6±893.93µs        ? ?/sec
async/http_concurrent_conn_calls/fast_call/2       1.03   139.1±33.81µs        ? ?/sec      1.00   135.4±55.63µs        ? ?/sec      1.03   139.1±33.81µs        ? ?/sec
async/http_concurrent_conn_calls/fast_call/256     1.00     11.3±4.26ms        ? ?/sec      1.06     12.0±4.65ms        ? ?/sec      1.00     11.3±4.26ms        ? ?/sec
async/http_concurrent_conn_calls/fast_call/32      1.04  1457.2±1258.20µs        ? ?/sec    1.00  1404.4±1199.09µs        ? ?/sec    1.04  1457.2±1258.20µs        ? ?/sec
async/http_concurrent_conn_calls/fast_call/4       1.09  256.1±357.90µs        ? ?/sec      1.00  235.1±331.56µs        ? ?/sec      1.09  256.1±357.90µs        ? ?/sec
async/http_concurrent_conn_calls/fast_call/512     1.00     22.8±7.84ms        ? ?/sec      1.06     24.2±9.72ms        ? ?/sec      1.00     22.8±7.84ms        ? ?/sec
async/http_concurrent_conn_calls/fast_call/64      1.00      2.8±2.35ms        ? ?/sec      1.15      3.2±2.55ms        ? ?/sec      1.00      2.8±2.35ms        ? ?/sec
async/http_concurrent_conn_calls/fast_call/8       1.00  422.1±555.57µs        ? ?/sec      1.08  454.2±597.93µs        ? ?/sec      1.00  422.1±555.57µs        ? ?/sec
async/http_custom_headers_round_trip/0kb           1.00     50.5±5.51µs        ? ?/sec      1.06     53.5±7.37µs        ? ?/sec      1.00     50.5±5.51µs        ? ?/sec
async/http_custom_headers_round_trip/100kb         1.14   148.0±27.74µs        ? ?/sec      1.00   129.3±25.61µs        ? ?/sec      1.14   148.0±27.74µs        ? ?/sec
async/http_custom_headers_round_trip/1kb           1.00     58.0±8.65µs        ? ?/sec      1.06    61.2±13.12µs        ? ?/sec      1.00     58.0±8.65µs        ? ?/sec
async/http_custom_headers_round_trip/25kb          1.00    74.7±12.29µs        ? ?/sec      1.04    77.6±18.65µs        ? ?/sec      1.00    74.7±12.29µs        ? ?/sec
async/http_custom_headers_round_trip/5kb           1.00     56.4±8.51µs        ? ?/sec      1.00     56.1±7.92µs        ? ?/sec      1.00     56.4±8.51µs        ? ?/sec
async/http_round_trip/243                          1.15    143.6±3.19ms        ? ?/sec      1.00    124.9±1.82ms        ? ?/sec      1.15    143.6±3.19ms        ? ?/sec
async/http_round_trip/27                           1.00     13.9±3.03ms        ? ?/sec      1.31     18.2±4.95ms        ? ?/sec      1.00     13.9±3.03ms        ? ?/sec
async/http_round_trip/3                            1.00  1604.1±61.01µs        ? ?/sec      1.06  1694.1±120.96µs        ? ?/sec     1.00  1604.1±61.01µs        ? ?/sec
async/http_round_trip/729                          1.06   414.0±13.08ms        ? ?/sec      1.00    391.1±9.99ms        ? ?/sec      1.06   414.0±13.08ms        ? ?/sec
async/http_round_trip/81                           1.11     41.0±0.59ms        ? ?/sec      1.00     36.9±0.57ms        ? ?/sec      1.11     41.0±0.59ms        ? ?/sec
async/http_round_trip/9                            1.01      4.2±0.10ms        ? ?/sec      1.00      4.1±1.40ms        ? ?/sec      1.01      4.2±0.10ms        ? ?/sec
async/ws_batch_requests/fast_call/10               1.00     51.3±2.41µs 190.5 KElem/sec     1.00    51.1±12.36µs 191.2 KElem/sec     1.00     51.3±2.41µs 190.5 KElem/sec
async/ws_batch_requests/fast_call/100              1.36   223.2±76.71µs 437.5 KElem/sec     1.00    164.7±3.55µs 593.1 KElem/sec     1.36   223.2±76.71µs 437.5 KElem/sec
async/ws_batch_requests/fast_call/2                1.18     42.2±8.08µs 46.3 KElem/sec      1.00     35.6±3.24µs 54.8 KElem/sec      1.18     42.2±8.08µs 46.3 KElem/sec
async/ws_batch_requests/fast_call/5                1.02     43.2±2.92µs 113.0 KElem/sec     1.00     42.2±3.55µs 115.7 KElem/sec     1.02     43.2±2.92µs 113.0 KElem/sec
async/ws_batch_requests/fast_call/50               1.00    110.7±3.09µs 441.2 KElem/sec     1.81   200.3±15.45µs 243.7 KElem/sec     1.00    110.7±3.09µs 441.2 KElem/sec
async/ws_concurrent_conn_calls/fast_call/1024      1.00     21.2±0.19ms        ? ?/sec      1.00     21.2±0.21ms        ? ?/sec      1.00     21.2±0.19ms        ? ?/sec
async/ws_concurrent_conn_calls/fast_call/128       1.01      2.4±0.03ms        ? ?/sec      1.00      2.4±0.02ms        ? ?/sec      1.01      2.4±0.03ms        ? ?/sec
async/ws_concurrent_conn_calls/fast_call/16        1.00  772.3±163.43µs        ? ?/sec      1.34  1034.6±242.30µs        ? ?/sec     1.00  772.3±163.43µs        ? ?/sec
async/ws_concurrent_conn_calls/fast_call/2         1.03  1127.2±146.13µs        ? ?/sec     1.00  1091.0±93.34µs        ? ?/sec      1.03  1127.2±146.13µs        ? ?/sec
async/ws_concurrent_conn_calls/fast_call/256       1.02      4.5±0.07ms        ? ?/sec      1.00      4.5±0.04ms        ? ?/sec      1.02      4.5±0.07ms        ? ?/sec
async/ws_concurrent_conn_calls/fast_call/32        1.04  1132.9±127.93µs        ? ?/sec     1.00  1093.7±134.14µs        ? ?/sec     1.04  1132.9±127.93µs        ? ?/sec
async/ws_concurrent_conn_calls/fast_call/4         1.04  1255.7±202.37µs        ? ?/sec     1.00  1213.2±180.59µs        ? ?/sec     1.04  1255.7±202.37µs        ? ?/sec
async/ws_concurrent_conn_calls/fast_call/512       1.02      9.6±0.19ms        ? ?/sec      1.00      9.4±0.09ms        ? ?/sec      1.02      9.6±0.19ms        ? ?/sec
async/ws_concurrent_conn_calls/fast_call/64        1.01  1327.4±19.60µs        ? ?/sec      1.00  1317.9±19.06µs        ? ?/sec      1.01  1327.4±19.60µs        ? ?/sec
async/ws_concurrent_conn_calls/fast_call/8         1.02  1128.8±119.18µs        ? ?/sec     1.00  1108.0±188.48µs        ? ?/sec     1.02  1128.8±119.18µs        ? ?/sec
async/ws_concurrent_conn_subs/1024                 1.02     34.7±0.56ms        ? ?/sec      1.00     33.9±0.49ms        ? ?/sec      1.02     34.7±0.56ms        ? ?/sec
async/ws_concurrent_conn_subs/128                  1.01      3.9±0.04ms        ? ?/sec      1.00      3.9±0.05ms        ? ?/sec      1.01      3.9±0.04ms        ? ?/sec
async/ws_concurrent_conn_subs/16                   1.12  1096.5±87.16µs        ? ?/sec      1.00  979.1±129.13µs        ? ?/sec      1.12  1096.5±87.16µs        ? ?/sec
async/ws_concurrent_conn_subs/256                  1.03      7.8±0.11ms        ? ?/sec      1.00      7.6±0.08ms        ? ?/sec      1.03      7.8±0.11ms        ? ?/sec
async/ws_concurrent_conn_subs/32                   1.02  1230.1±16.43µs        ? ?/sec      1.00  1207.3±16.62µs        ? ?/sec      1.02  1230.1±16.43µs        ? ?/sec
async/ws_concurrent_conn_subs/512                  1.01     16.8±0.24ms        ? ?/sec      1.00     16.6±0.24ms        ? ?/sec      1.01     16.8±0.24ms        ? ?/sec
async/ws_concurrent_conn_subs/64                   1.02      2.2±0.03ms        ? ?/sec      1.00      2.1±0.03ms        ? ?/sec      1.02      2.2±0.03ms        ? ?/sec
async/ws_custom_headers_handshake/0kb              1.10     96.4±6.80µs        ? ?/sec      1.00     87.2±1.22µs        ? ?/sec      1.10     96.4±6.80µs        ? ?/sec
async/ws_custom_headers_handshake/1kb              1.00     94.7±4.38µs        ? ?/sec      1.02     97.1±9.47µs        ? ?/sec      1.00     94.7±4.38µs        ? ?/sec
async/ws_custom_headers_handshake/2kb              1.04     95.1±4.18µs        ? ?/sec      1.00     91.2±0.73µs        ? ?/sec      1.04     95.1±4.18µs        ? ?/sec
async/ws_custom_headers_handshake/4kb              1.00    100.2±2.77µs        ? ?/sec      1.01    101.0±3.76µs        ? ?/sec      1.00    100.2±2.77µs        ? ?/sec
async/ws_round_trip/243                            1.00   104.2±11.69ms        ? ?/sec      1.01   105.2±10.75ms        ? ?/sec      1.00   104.2±11.69ms        ? ?/sec
async/ws_round_trip/27                             1.00     15.3±1.83ms        ? ?/sec      1.06     16.3±2.08ms        ? ?/sec      1.00     15.3±1.83ms        ? ?/sec
async/ws_round_trip/3                              1.10  1991.2±244.20µs        ? ?/sec     1.00  1807.7±215.18µs        ? ?/sec     1.10  1991.2±244.20µs        ? ?/sec
async/ws_round_trip/729                            1.01   303.5±18.57ms        ? ?/sec      1.00   299.2±16.33ms        ? ?/sec      1.01   303.5±18.57ms        ? ?/sec
async/ws_round_trip/81                             1.00     47.0±5.02ms        ? ?/sec      1.04     48.8±5.68ms        ? ?/sec      1.00     47.0±5.02ms        ? ?/sec
async/ws_round_trip/9                              1.00      4.2±0.45ms        ? ?/sec      1.06      4.4±0.65ms        ? ?/sec      1.00      4.2±0.45ms        ? ?/sec
jsonrpsee_types_array_params                       1.00    162.5±0.98ns        ? ?/sec      1.03    167.5±2.04ns        ? ?/sec      1.00    162.5±0.98ns        ? ?/sec
jsonrpsee_types_array_params_baseline              1.08    100.1±0.60ns        ? ?/sec      1.00     93.0±2.55ns        ? ?/sec      1.08    100.1±0.60ns        ? ?/sec
jsonrpsee_types_object_params                      1.00    167.9±1.37ns        ? ?/sec      1.02    171.1±1.44ns        ? ?/sec      1.00    167.9±1.37ns        ? ?/sec
jsonrpsee_types_object_params_baseline             1.00     97.6±1.33ns        ? ?/sec      1.28    125.0±0.77ns        ? ?/sec      1.00     97.6±1.33ns        ? ?/sec
subscriptions/subscribe                            1.00    78.2±13.58µs        ? ?/sec      1.04    81.4±20.46µs        ? ?/sec      1.00    78.2±13.58µs        ? ?/sec
subscriptions/subscribe_response                   1.18      4.3±1.15µs        ? ?/sec      1.00      3.6±1.01µs        ? ?/sec      1.18      4.3±1.15µs        ? ?/sec
subscriptions/unsub                                1.00      2.1±0.37µs        ? ?/sec      1.02      2.1±0.40µs        ? ?/sec      1.00      2.1±0.37µs        ? ?/sec
sync/http_batch_requests/fast_call/10              1.00     59.3±8.69µs 164.6 KElem/sec     1.04    61.8±11.82µs 157.9 KElem/sec     1.00     59.3±8.69µs 164.6 KElem/sec
sync/http_batch_requests/fast_call/100             1.04   302.4±41.95µs 322.9 KElem/sec     1.00   289.8±36.92µs 337.0 KElem/sec     1.04   302.4±41.95µs 322.9 KElem/sec
sync/http_batch_requests/fast_call/2               1.07    66.3±13.86µs 29.5 KElem/sec      1.00    61.7±11.34µs 31.7 KElem/sec      1.07    66.3±13.86µs 29.5 KElem/sec
sync/http_batch_requests/fast_call/5               1.10    61.7±16.43µs 79.1 KElem/sec      1.00    56.3±10.88µs 86.8 KElem/sec      1.10    61.7±16.43µs 79.1 KElem/sec
sync/http_batch_requests/fast_call/50              1.00   157.3±42.44µs 310.4 KElem/sec     1.08   169.9±42.40µs 287.4 KElem/sec     1.00   157.3±42.44µs 310.4 KElem/sec
sync/http_concurrent_conn_calls/fast_call/1024     1.00    46.1±16.32ms        ? ?/sec      1.00    46.1±16.17ms        ? ?/sec      1.00    46.1±16.32ms        ? ?/sec
sync/http_concurrent_conn_calls/fast_call/128      1.04      5.9±2.52ms        ? ?/sec      1.00      5.7±2.17ms        ? ?/sec      1.04      5.9±2.52ms        ? ?/sec
sync/http_concurrent_conn_calls/fast_call/16       1.02  950.3±1011.16µs        ? ?/sec     1.00  931.3±950.89µs        ? ?/sec      1.02  950.3±1011.16µs        ? ?/sec
sync/http_concurrent_conn_calls/fast_call/2        1.04   141.5±52.77µs        ? ?/sec      1.00   136.3±48.84µs        ? ?/sec      1.04   141.5±52.77µs        ? ?/sec
sync/http_concurrent_conn_calls/fast_call/256      1.00     11.2±4.41ms        ? ?/sec      1.06     11.9±4.55ms        ? ?/sec      1.00     11.2±4.41ms        ? ?/sec
sync/http_concurrent_conn_calls/fast_call/32       1.03  1597.2±1300.04µs        ? ?/sec    1.00  1550.4±1270.27µs        ? ?/sec    1.03  1597.2±1300.04µs        ? ?/sec
sync/http_concurrent_conn_calls/fast_call/4        1.23  285.1±391.70µs        ? ?/sec      1.00  232.1±299.10µs        ? ?/sec      1.23  285.1±391.70µs        ? ?/sec
sync/http_concurrent_conn_calls/fast_call/512      1.00     23.4±8.39ms        ? ?/sec      1.00     23.5±9.06ms        ? ?/sec      1.00     23.4±8.39ms        ? ?/sec
sync/http_concurrent_conn_calls/fast_call/64       1.02      2.8±2.38ms        ? ?/sec      1.00      2.8±2.41ms        ? ?/sec      1.02      2.8±2.38ms        ? ?/sec
sync/http_concurrent_conn_calls/fast_call/8        1.00  440.4±574.25µs        ? ?/sec      1.00  438.2±569.93µs        ? ?/sec      1.00  440.4±574.25µs        ? ?/sec
sync/http_custom_headers_round_trip/0kb            1.27    66.4±15.42µs        ? ?/sec      1.00     52.1±7.43µs        ? ?/sec      1.27    66.4±15.42µs        ? ?/sec
sync/http_custom_headers_round_trip/100kb          1.03   128.3±25.88µs        ? ?/sec      1.00   124.7±26.70µs        ? ?/sec      1.03   128.3±25.88µs        ? ?/sec
sync/http_custom_headers_round_trip/1kb            1.49     76.6±8.70µs        ? ?/sec      1.00    51.3±11.23µs        ? ?/sec      1.49     76.6±8.70µs        ? ?/sec
sync/http_custom_headers_round_trip/25kb           1.17    77.7±14.65µs        ? ?/sec      1.00    66.1±14.01µs        ? ?/sec      1.17    77.7±14.65µs        ? ?/sec
sync/http_custom_headers_round_trip/5kb            1.01     53.4±5.41µs        ? ?/sec      1.00     52.7±8.59µs        ? ?/sec      1.01     53.4±5.41µs        ? ?/sec
sync/http_round_trip/243                           1.10    138.8±4.17ms        ? ?/sec      1.00    125.8±6.94ms        ? ?/sec      1.10    138.8±4.17ms        ? ?/sec
sync/http_round_trip/27                            1.04     15.6±0.44ms        ? ?/sec      1.00     15.0±0.53ms        ? ?/sec      1.04     15.6±0.44ms        ? ?/sec
sync/http_round_trip/3                             1.01  1529.7±27.74µs        ? ?/sec      1.00  1517.4±100.90µs        ? ?/sec     1.01  1529.7±27.74µs        ? ?/sec
sync/http_round_trip/729                           1.17   422.5±14.18ms        ? ?/sec      1.00   360.9±11.96ms        ? ?/sec      1.17   422.5±14.18ms        ? ?/sec
sync/http_round_trip/81                            1.14     51.6±1.98ms        ? ?/sec      1.00     45.1±1.45ms        ? ?/sec      1.14     51.6±1.98ms        ? ?/sec
sync/http_round_trip/9                             1.40      6.2±0.36ms        ? ?/sec      1.00      4.4±0.18ms        ? ?/sec      1.40      6.2±0.36ms        ? ?/sec
sync/ws_batch_requests/fast_call/10                1.00     49.6±3.72µs 196.7 KElem/sec     1.00     49.6±3.24µs 196.9 KElem/sec     1.00     49.6±3.72µs 196.7 KElem/sec
sync/ws_batch_requests/fast_call/100               1.08    173.2±1.53µs 563.8 KElem/sec     1.00    159.8±1.27µs 611.1 KElem/sec     1.08    173.2±1.53µs 563.8 KElem/sec
sync/ws_batch_requests/fast_call/2                 1.03     37.7±2.64µs 51.8 KElem/sec      1.00     36.6±1.13µs 53.4 KElem/sec      1.03     37.7±2.64µs 51.8 KElem/sec
sync/ws_batch_requests/fast_call/5                 1.08     43.1±5.17µs 113.4 KElem/sec     1.00     40.1±1.09µs 121.9 KElem/sec     1.08     43.1±5.17µs 113.4 KElem/sec
sync/ws_batch_requests/fast_call/50                1.08    106.6±0.40µs 458.0 KElem/sec     1.00     98.3±0.52µs 496.5 KElem/sec     1.08    106.6±0.40µs 458.0 KElem/sec
sync/ws_concurrent_conn_calls/fast_call/1024       1.03     21.8±0.30ms        ? ?/sec      1.00     21.2±0.20ms        ? ?/sec      1.03     21.8±0.30ms        ? ?/sec
sync/ws_concurrent_conn_calls/fast_call/128        1.04      2.4±0.04ms        ? ?/sec      1.00      2.4±0.03ms        ? ?/sec      1.04      2.4±0.04ms        ? ?/sec
sync/ws_concurrent_conn_calls/fast_call/16         1.00  986.6±208.64µs        ? ?/sec      1.03  1020.4±254.87µs        ? ?/sec     1.00  986.6±208.64µs        ? ?/sec
sync/ws_concurrent_conn_calls/fast_call/2          1.00  1097.4±130.50µs        ? ?/sec     1.01  1104.8±88.05µs        ? ?/sec      1.00  1097.4±130.50µs        ? ?/sec
sync/ws_concurrent_conn_calls/fast_call/256        1.04      4.6±0.11ms        ? ?/sec      1.00      4.5±0.03ms        ? ?/sec      1.04      4.6±0.11ms        ? ?/sec
sync/ws_concurrent_conn_calls/fast_call/32         1.03  1110.1±154.49µs        ? ?/sec     1.00  1082.3±100.18µs        ? ?/sec     1.03  1110.1±154.49µs        ? ?/sec
sync/ws_concurrent_conn_calls/fast_call/4          1.00  1169.7±125.53µs        ? ?/sec     1.06  1239.8±168.88µs        ? ?/sec     1.00  1169.7±125.53µs        ? ?/sec
sync/ws_concurrent_conn_calls/fast_call/512        1.02      9.6±0.16ms        ? ?/sec      1.00      9.4±0.10ms        ? ?/sec      1.02      9.6±0.16ms        ? ?/sec
sync/ws_concurrent_conn_calls/fast_call/64         1.00  1303.0±17.28µs        ? ?/sec      1.00  1305.3±20.36µs        ? ?/sec      1.00  1303.0±17.28µs        ? ?/sec
sync/ws_concurrent_conn_calls/fast_call/8          1.05  1124.9±152.58µs        ? ?/sec     1.00  1067.5±241.29µs        ? ?/sec     1.05  1124.9±152.58µs        ? ?/sec
sync/ws_concurrent_conn_subs/1024                  1.01     34.5±0.46ms        ? ?/sec      1.00     34.1±0.50ms        ? ?/sec      1.01     34.5±0.46ms        ? ?/sec
sync/ws_concurrent_conn_subs/128                   1.03      4.0±0.05ms        ? ?/sec      1.00      3.9±0.05ms        ? ?/sec      1.03      4.0±0.05ms        ? ?/sec
sync/ws_concurrent_conn_subs/16                    1.01   989.5±92.25µs        ? ?/sec      1.00   981.9±96.16µs        ? ?/sec      1.01   989.5±92.25µs        ? ?/sec
sync/ws_concurrent_conn_subs/256                   1.04      7.9±0.12ms        ? ?/sec      1.00      7.6±0.07ms        ? ?/sec      1.04      7.9±0.12ms        ? ?/sec
sync/ws_concurrent_conn_subs/32                    1.00  1200.8±16.12µs        ? ?/sec      1.00  1197.1±17.78µs        ? ?/sec      1.00  1200.8±16.12µs        ? ?/sec
sync/ws_concurrent_conn_subs/512                   1.03     17.1±0.40ms        ? ?/sec      1.00     16.6±0.25ms        ? ?/sec      1.03     17.1±0.40ms        ? ?/sec
sync/ws_concurrent_conn_subs/64                    1.00      2.1±0.03ms        ? ?/sec      1.00      2.1±0.03ms        ? ?/sec      1.00      2.1±0.03ms        ? ?/sec
sync/ws_custom_headers_handshake/0kb               1.07     97.9±3.01µs        ? ?/sec      1.00     91.5±5.93µs        ? ?/sec      1.07     97.9±3.01µs        ? ?/sec
sync/ws_custom_headers_handshake/1kb               1.09     99.8±4.41µs        ? ?/sec      1.00     91.7±4.62µs        ? ?/sec      1.09     99.8±4.41µs        ? ?/sec
sync/ws_custom_headers_handshake/2kb               1.13    102.4±7.15µs        ? ?/sec      1.00     90.9±1.53µs        ? ?/sec      1.13    102.4±7.15µs        ? ?/sec
sync/ws_custom_headers_handshake/4kb               1.12    103.9±5.41µs        ? ?/sec      1.00     92.4±5.79µs        ? ?/sec      1.12    103.9±5.41µs        ? ?/sec
sync/ws_round_trip/243                             1.00   105.6±10.47ms        ? ?/sec      1.04    109.5±9.44ms        ? ?/sec      1.00   105.6±10.47ms        ? ?/sec
sync/ws_round_trip/27                              1.00     16.3±2.20ms        ? ?/sec      1.01     16.4±2.12ms        ? ?/sec      1.00     16.3±2.20ms        ? ?/sec
sync/ws_round_trip/3                               1.00  1864.7±221.14µs        ? ?/sec     1.09      2.0±0.27ms        ? ?/sec      1.00  1864.7±221.14µs        ? ?/sec
sync/ws_round_trip/729                             1.00   303.2±18.75ms        ? ?/sec      1.00   303.6±19.93ms        ? ?/sec      1.00   303.2±18.75ms        ? ?/sec
sync/ws_round_trip/81                              1.00     49.3±5.78ms        ? ?/sec      1.01     49.6±6.11ms        ? ?/sec      1.00     49.3±5.78ms        ? ?/sec
sync/ws_round_trip/9                               1.02      4.2±0.41ms        ? ?/sec      1.00      4.1±0.44ms        ? ?/sec      1.02      4.2±0.41ms        ? ?/sec

@niklasad1 niklasad1 changed the title WIP: new jsonrpc specific middleware feat(server): add JSON-RPC specific middleware Oct 17, 2023
@niklasad1 niklasad1 added the breaking change Breaking change in the public APIs label Oct 17, 2023
@niklasad1 niklasad1 changed the title feat(server): add JSON-RPC specific middleware feat(server): JSON-RPC specific middleware Oct 17, 2023
/// Similar to `tower::Service` but specific for jsonrpsee and
/// doesn't requires `&mut self` for performance reasons.
#[async_trait::async_trait]
pub trait RpcServiceT<'a> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also an alternative to do which doesn't requrire boxing the future as the async trait does:

pub trait Service {
    /// The future response value.
    type Future<'cx>: Future<Output = MethodResponse>>
    where
        Self: 'cx,
        Request: 'cx;

    /// Process the request and return the response asynchronously.
    fn call(&self, req: Request<'_>) -> Self::Future<'_>;
}

Copy link
Collaborator

@jsdw jsdw Oct 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would allow more a little better control/performance especially if there are a bunch of middlewares, and our logging one could also then be as light weight as possible, so IMO it's probably worth doing this even if it makes the trait more annoying (people can just set the type to Box<dyn Future<Output = Foo> + Send + Sync + 'static> if they want to keep it simple anyway I think).

Copy link
Member Author

@niklasad1 niklasad1 Oct 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our stuff requires still requires Send + 'static and not sure if it's worth all the complexity with such Service trait

@niklasad1 niklasad1 marked this pull request as ready for review October 18, 2023 08:49
@niklasad1 niklasad1 requested a review from a team as a code owner October 18, 2023 08:49
server/src/server.rs Outdated Show resolved Hide resolved
server/src/server.rs Outdated Show resolved Hide resolved
///
/// This logs each request and response for every call.
///
pub fn rpc_logger(self, max_log_len: u32) -> RpcServiceBuilder<Stack<RpcLoggerLayer, L>> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dq: Is this a wrapper over RpcService.layer(RpcLogger::new(..)) for convenience since that's a very common use-case?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I removed our default logging/tracing in the server and this can be used for "backward-compatible logger" or folks to adapt their own layer for customized logging/tracing.

rate: Rate,
}

impl<S> RateLimit<S> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your opinion on supporting this in the server/rpc/layers similar to the RpcLogger? Its a pretty nice implementation :D

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My offhand thought is that rate limiting is quite complicated and everybody may want to have a slightly different approach to how limits are applied and how things are throttled etc, so while we could maintain a "simple" one, maybe it's best left as an exercise for the reader (but I might be wrong!)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, let's start with this an example and let see whether anyone wants it or not in jsonrpsee :)

I would be happy not to maintain it :D

Comment on lines 246 to 248
/// Send a JSON-RPC response to the client. If the serialization of `result` exceeds `max_response_size`,
/// an error will be sent instead.
pub fn response<T>(id: Id, result: ResponsePayload<T>, max_response_size: usize) -> Self
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I wonder whether it's worth renaming this to method_response to try and make it feel like "not the default one to use", and/or maybe just a tweak to docs like "If the response is from a subscription, use subscription_response", orr ditching subscription_response and instead adding another arg to response (ie is_subscription: bool) so that every call has to be explicit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, it makes sense.

I just added subscription_response and never thought about it. I was just happy that it worked :P

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not too fussed, having looked at the rest of the code (maybe just add the doc comment?), so whatever you prefer :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, a subscription response is basically just a method response but in some scenarios in the server it may be useful to know and in middleware doing grafana metrics etc.

I think I want to keep response but lemme adjust the docs a little bit better.

Comment on lines 249 to 250
pub fn method_kind(&self, method_name: &str) -> MethodKind {
match self.method(method_name) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of MethodKind::Unknown, wouyld it make more sense to return Option<MethodKind> here? (or alternately, rename it to somehting clearer eg MethodKind::NotFound?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, this code is not used so I removed it but I guess your comment still applies.

Lemme fix it NotFound is better

@@ -438,6 +438,9 @@ impl Subscription {
let raw = self.rx.recv().await?;

tracing::debug!("[Subscription::next]: rx {}", raw);

// clippy complains about this but it doesn't compile without the extra res binding.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh weird; what's the error?!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lifetime doesn't live long enough, it may be some issue with my own serde impl I did a long time ago.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange though that nothing changes at all whether the variable is there or not! I wouldn't expect any difference since you haven't given any extra type info on the variable or whatever :)

Comment on lines +130 to +135
let rpc_middleware = RpcServiceBuilder::new()
.layer_fn(|service| Logger(service))
// This state is created per connection.
.layer_fn(|service| CallsPerConn { service, count: AtomicUsize::new(0) })
// This state is shared by all connections.
.layer_fn(move |service| GlobalCalls { service, count: global_cnt.clone() });
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

Copy link
Collaborator

@jsdw jsdw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great stuff! I feel like it makes a bunch of nice improvements to the code along the way, as well as giving more flexibility with the new RPC middleware stuff :)

Copy link
Contributor

@lexnv lexnv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change Breaking change in the public APIs
Projects
None yet
4 participants