refactor: Transport trait and worker transport, and streamable http client with those new features. (#167)
* refactor: a transport trait and streamable http client * test: test with js streamable http server * refactor: separate sse stream connection * fix(test): streamable http client test with js * fix(test): wait longer time for js server startup
This commit is contained in:
parent
01eedb7770
commit
9a771fb157
2 changed files with 2761 additions and 1315 deletions
|
|
@ -1,4 +1,3 @@
|
|||
use futures::{SinkExt, Stream, StreamExt};
|
||||
use thiserror::Error;
|
||||
|
||||
use super::*;
|
||||
|
|
@ -38,29 +37,29 @@ pub enum ClientError {
|
|||
}
|
||||
|
||||
/// Helper function to get the next message from the stream
|
||||
async fn expect_next_message<S>(
|
||||
stream: &mut S,
|
||||
async fn expect_next_message<T>(
|
||||
transport: &mut T,
|
||||
context: &str,
|
||||
) -> Result<ServerJsonRpcMessage, ClientError>
|
||||
where
|
||||
S: Stream<Item = ServerJsonRpcMessage> + Unpin,
|
||||
T: Transport<RoleClient>,
|
||||
{
|
||||
stream
|
||||
.next()
|
||||
transport
|
||||
.receive()
|
||||
.await
|
||||
.ok_or_else(|| ClientError::ConnectionClosed(context.to_string()))
|
||||
.map_err(|e| ClientError::Io(std::io::Error::new(std::io::ErrorKind::Other, e)))
|
||||
}
|
||||
|
||||
/// Helper function to expect a response from the stream
|
||||
async fn expect_response<S>(
|
||||
stream: &mut S,
|
||||
async fn expect_response<T>(
|
||||
transport: &mut T,
|
||||
context: &str,
|
||||
) -> Result<(ServerResult, RequestId), ClientError>
|
||||
where
|
||||
S: Stream<Item = ServerJsonRpcMessage> + Unpin,
|
||||
T: Transport<RoleClient>,
|
||||
{
|
||||
let msg = expect_next_message(stream, context).await?;
|
||||
let msg = expect_next_message(transport, context).await?;
|
||||
|
||||
match msg {
|
||||
ServerJsonRpcMessage::Response(JsonRpcResponse { id, result, .. }) => Ok((result, id)),
|
||||
|
|
@ -123,9 +122,7 @@ where
|
|||
T: IntoTransport<RoleClient, E, A>,
|
||||
E: std::error::Error + From<std::io::Error> + Send + Sync + 'static,
|
||||
{
|
||||
let (sink, stream) = transport.into_transport();
|
||||
let mut sink = Box::pin(sink);
|
||||
let mut stream = Box::pin(stream);
|
||||
let mut transport = transport.into_transport();
|
||||
let id_provider = <Arc<AtomicU32RequestIdProvider>>::default();
|
||||
|
||||
// Convert ClientError to std::io::Error, then to E
|
||||
|
|
@ -143,13 +140,14 @@ where
|
|||
params: service.get_info(),
|
||||
extensions: Default::default(),
|
||||
};
|
||||
sink.send(ClientJsonRpcMessage::request(
|
||||
ClientRequest::InitializeRequest(init_request),
|
||||
id.clone(),
|
||||
))
|
||||
.await?;
|
||||
transport
|
||||
.send(ClientJsonRpcMessage::request(
|
||||
ClientRequest::InitializeRequest(init_request),
|
||||
id.clone(),
|
||||
))
|
||||
.await?;
|
||||
|
||||
let (response, response_id) = expect_response(&mut stream, "initialize response")
|
||||
let (response, response_id) = expect_response(&mut transport, "initialize response")
|
||||
.await
|
||||
.map_err(handle_client_error)?;
|
||||
|
||||
|
|
@ -173,9 +171,9 @@ where
|
|||
extensions: Default::default(),
|
||||
}),
|
||||
);
|
||||
sink.send(notification).await?;
|
||||
transport.send(notification).await?;
|
||||
let (peer, peer_rx) = Peer::new(id_provider, initialize_result);
|
||||
serve_inner(service, (sink, stream), peer, peer_rx, ct).await
|
||||
serve_inner(service, transport, peer, peer_rx, ct).await
|
||||
}
|
||||
|
||||
macro_rules! method {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use futures::{SinkExt, StreamExt};
|
||||
use thiserror::Error;
|
||||
|
||||
use super::*;
|
||||
|
|
@ -81,42 +80,42 @@ where
|
|||
}
|
||||
|
||||
/// Helper function to get the next message from the stream
|
||||
async fn expect_next_message<S>(
|
||||
stream: &mut S,
|
||||
async fn expect_next_message<T>(
|
||||
transport: &mut T,
|
||||
context: &str,
|
||||
) -> Result<ClientJsonRpcMessage, ServerError>
|
||||
where
|
||||
S: StreamExt<Item = ClientJsonRpcMessage> + Unpin,
|
||||
T: Transport<RoleServer>,
|
||||
{
|
||||
stream
|
||||
.next()
|
||||
transport
|
||||
.receive()
|
||||
.await
|
||||
.ok_or_else(|| ServerError::ConnectionClosed(context.to_string()))
|
||||
}
|
||||
|
||||
/// Helper function to expect a request from the stream
|
||||
async fn expect_request<S>(
|
||||
stream: &mut S,
|
||||
async fn expect_request<T>(
|
||||
transport: &mut T,
|
||||
context: &str,
|
||||
) -> Result<(ClientRequest, RequestId), ServerError>
|
||||
where
|
||||
S: StreamExt<Item = ClientJsonRpcMessage> + Unpin,
|
||||
T: Transport<RoleServer>,
|
||||
{
|
||||
let msg = expect_next_message(stream, context).await?;
|
||||
let msg = expect_next_message(transport, context).await?;
|
||||
let msg_clone = msg.clone();
|
||||
msg.into_request()
|
||||
.ok_or(ServerError::ExpectedInitRequest(Some(msg_clone)))
|
||||
}
|
||||
|
||||
/// Helper function to expect a notification from the stream
|
||||
async fn expect_notification<S>(
|
||||
stream: &mut S,
|
||||
async fn expect_notification<T>(
|
||||
transport: &mut T,
|
||||
context: &str,
|
||||
) -> Result<ClientNotification, ServerError>
|
||||
where
|
||||
S: StreamExt<Item = ClientJsonRpcMessage> + Unpin,
|
||||
T: Transport<RoleServer>,
|
||||
{
|
||||
let msg = expect_next_message(stream, context).await?;
|
||||
let msg = expect_next_message(transport, context).await?;
|
||||
let msg_clone = msg.clone();
|
||||
msg.into_notification()
|
||||
.ok_or(ServerError::ExpectedInitNotification(Some(msg_clone)))
|
||||
|
|
@ -132,9 +131,7 @@ where
|
|||
T: IntoTransport<RoleServer, E, A>,
|
||||
E: std::error::Error + From<std::io::Error> + Send + Sync + 'static,
|
||||
{
|
||||
let (sink, stream) = transport.into_transport();
|
||||
let mut sink = Box::pin(sink);
|
||||
let mut stream = Box::pin(stream);
|
||||
let mut transport = transport.into_transport();
|
||||
let id_provider = <Arc<AtomicU32RequestIdProvider>>::default();
|
||||
|
||||
// Convert ServerError to std::io::Error, then to E
|
||||
|
|
@ -146,7 +143,7 @@ where
|
|||
};
|
||||
|
||||
// Get initialize request
|
||||
let (request, id) = expect_request(&mut stream, "initialized request")
|
||||
let (request, id) = expect_request(&mut transport, "initialized request")
|
||||
.await
|
||||
.map_err(handle_server_error)?;
|
||||
|
||||
|
|
@ -173,7 +170,8 @@ where
|
|||
));
|
||||
}
|
||||
Err(e) => {
|
||||
sink.send(ServerJsonRpcMessage::error(e.clone(), id))
|
||||
transport
|
||||
.send(ServerJsonRpcMessage::error(e.clone(), id))
|
||||
.await?;
|
||||
return Err(handle_server_error(ServerError::InitializeFailed(e)));
|
||||
}
|
||||
|
|
@ -190,14 +188,15 @@ where
|
|||
_ => init_response.protocol_version,
|
||||
};
|
||||
init_response.protocol_version = protocol_version;
|
||||
sink.send(ServerJsonRpcMessage::response(
|
||||
ServerResult::InitializeResult(init_response),
|
||||
id,
|
||||
))
|
||||
.await?;
|
||||
transport
|
||||
.send(ServerJsonRpcMessage::response(
|
||||
ServerResult::InitializeResult(init_response),
|
||||
id,
|
||||
))
|
||||
.await?;
|
||||
|
||||
// Wait for initialize notification
|
||||
let notification = expect_notification(&mut stream, "initialize notification")
|
||||
let notification = expect_notification(&mut transport, "initialize notification")
|
||||
.await
|
||||
.map_err(handle_server_error)?;
|
||||
let ClientNotification::InitializedNotification(_) = notification else {
|
||||
|
|
@ -207,7 +206,7 @@ where
|
|||
};
|
||||
let _ = service.handle_notification(notification).await;
|
||||
// Continue processing service
|
||||
serve_inner(service, (sink, stream), peer, peer_rx, ct).await
|
||||
serve_inner(service, transport, peer, peer_rx, ct).await
|
||||
}
|
||||
|
||||
macro_rules! method {
|
||||
|
|
|
|||
Loading…
Reference in a new issue