-
Notifications
You must be signed in to change notification settings - Fork 14
feat: Create endpoint manager for websockets #251
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
Open
shahnami
wants to merge
3
commits into
plat-6492-add-network-and-models
Choose a base branch
from
plat-6659-refactor-rpc-calls-to-use-substrate-client-with-websocket
base: plat-6492-add-network-and-models
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...blockchain/transports/endpoint_manager.rs → ...chain/transports/http/endpoint_manager.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
//! Midnight transport implementation for blockchain interactions. | ||
//! | ||
//! This module provides a client implementation for interacting with Midnight-compatible nodes | ||
//! by wrapping the WsTransportClient. This allows for consistent behavior with other | ||
//! transport implementations while providing specific Midnight-focused functionality. | ||
|
||
use reqwest_middleware::ClientWithMiddleware; | ||
use reqwest_retry::policies::ExponentialBackoff; | ||
use serde::Serialize; | ||
use serde_json::Value; | ||
|
||
use crate::{ | ||
models::Network, | ||
services::blockchain::{ | ||
transports::{ | ||
BlockchainTransport, RotatingTransport, TransientErrorRetryStrategy, WsTransportClient, | ||
}, | ||
WsConfig, | ||
}, | ||
}; | ||
|
||
/// A client for interacting with Midnight-compatible blockchain nodes via WebSocket | ||
/// | ||
/// This implementation wraps the WsTransportClient to provide consistent | ||
/// behavior with other transport implementations while offering Midnight-specific | ||
/// functionality. It handles WebSocket connection management, message handling, | ||
/// and endpoint rotation for Midnight-based networks. | ||
#[derive(Clone, Debug)] | ||
pub struct MidnightTransportClient { | ||
/// The underlying WebSocket transport client that handles actual RPC communications | ||
ws_client: WsTransportClient, | ||
} | ||
|
||
impl MidnightTransportClient { | ||
/// Creates a new Midnight transport client by initializing a WebSocket transport client | ||
/// | ||
/// # Arguments | ||
/// * `network` - Network configuration containing RPC URLs and other network details | ||
/// | ||
/// # Returns | ||
/// * `Result<Self, anyhow::Error>` - A new client instance or connection error | ||
pub async fn new(network: &Network, config: Option<WsConfig>) -> Result<Self, anyhow::Error> { | ||
let ws_client = WsTransportClient::new(network, config).await?; | ||
Ok(Self { ws_client }) | ||
} | ||
} | ||
|
||
#[async_trait::async_trait] | ||
impl BlockchainTransport for MidnightTransportClient { | ||
/// Gets the current active RPC URL | ||
/// | ||
/// # Returns | ||
/// * `String` - The currently active RPC endpoint URL | ||
async fn get_current_url(&self) -> String { | ||
self.ws_client.get_current_url().await | ||
} | ||
|
||
/// Sends a raw JSON-RPC request to the Midnight node via WebSocket | ||
/// | ||
/// # Arguments | ||
/// * `method` - The JSON-RPC method to call | ||
/// * `params` - Optional parameters to pass with the request | ||
/// | ||
/// # Returns | ||
/// * `Result<Value, anyhow::Error>` - The JSON response or error | ||
async fn send_raw_request<P>( | ||
&self, | ||
method: &str, | ||
params: Option<P>, | ||
) -> Result<Value, anyhow::Error> | ||
where | ||
P: Into<Value> + Send + Clone + Serialize, | ||
{ | ||
self.ws_client.send_raw_request(method, params).await | ||
} | ||
|
||
/// Sets a new retry policy for the transport | ||
/// | ||
/// Note: Not applicable for WebSocket transport | ||
fn set_retry_policy( | ||
&mut self, | ||
_retry_policy: ExponentialBackoff, | ||
_retry_strategy: Option<TransientErrorRetryStrategy>, | ||
) -> Result<(), anyhow::Error> { | ||
Err(anyhow::anyhow!( | ||
"`set_retry_policy` not implemented for WebSocket transport" | ||
)) | ||
} | ||
|
||
/// Update endpoint manager with a new client | ||
/// | ||
/// Note: Not applicable for WebSocket transport | ||
fn update_endpoint_manager_client( | ||
&mut self, | ||
_client: ClientWithMiddleware, | ||
) -> Result<(), anyhow::Error> { | ||
Err(anyhow::anyhow!( | ||
"`update_endpoint_manager_client` not implemented for WebSocket transport" | ||
)) | ||
} | ||
} | ||
|
||
#[async_trait::async_trait] | ||
impl RotatingTransport for MidnightTransportClient { | ||
/// Tests connection to a specific WebSocket URL | ||
/// | ||
/// # Arguments | ||
/// * `url` - The WebSocket URL to test connection with | ||
/// | ||
/// # Returns | ||
/// * `Result<(), anyhow::Error>` - Success or error status | ||
async fn try_connect(&self, url: &str) -> Result<(), anyhow::Error> { | ||
self.ws_client.try_connect(url).await | ||
} | ||
|
||
/// Updates the client to use a new WebSocket URL | ||
/// | ||
/// # Arguments | ||
/// * `url` - The new WebSocket URL to use for subsequent requests | ||
/// | ||
/// # Returns | ||
/// * `Result<(), anyhow::Error>` - Success or error status | ||
async fn update_client(&self, url: &str) -> Result<(), anyhow::Error> { | ||
self.ws_client.update_client(url).await | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this to maintain consistency with other transport implementations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right, it implements BlockchainTransport where we only need get_current_url and send_raw_request.
We don't need retry policy logic and update_endpoint_manager because our websocket implementwtion doesn't have a middleware client, as opposed to http implementation, which has the reqwest middleware client. Mainly because of how connections are handled in http vs websockets.
As you can see, we don't actually have a client associated in the endpoint manager for ws to update. It simply manages rotation based on weights. Whereas for http it's a bit more complex, where we can configure different retry strategies based on error codes etc.. I hope that makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense! thanks for the explanation Nami!