-
Notifications
You must be signed in to change notification settings - Fork 205
feat(request): make request ID generation on client configurable #1535
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
base: master
Are you sure you want to change the base?
Changes from 7 commits
51ad234
0ee2516
8f7b381
150f07d
3d714a0
b57905d
556ee8a
e4005ac
a8c2689
ebae283
607226a
4f6b8e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,8 @@ | |
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
// DEALINGS IN THE SOFTWARE. | ||
|
||
use std::collections::BTreeMap; | ||
|
||
use crate::client::async_client::manager::{RequestManager, RequestStatus}; | ||
use crate::client::async_client::{Notification, LOG_TARGET}; | ||
use crate::client::{subscription_channel, Error, RequestMessage, TransportSenderT, TrySubscriptionSendError}; | ||
|
@@ -39,11 +41,10 @@ use jsonrpsee_types::{ | |
ErrorObject, Id, InvalidRequestId, RequestSer, Response, ResponseSuccess, SubscriptionId, SubscriptionResponse, | ||
}; | ||
use serde_json::Value as JsonValue; | ||
use std::ops::Range; | ||
|
||
#[derive(Debug, Clone)] | ||
pub(crate) struct InnerBatchResponse { | ||
pub(crate) id: u64, | ||
pub(crate) id: Id<'static>, | ||
pub(crate) result: Result<JsonValue, ErrorObject<'static>>, | ||
} | ||
|
||
|
@@ -53,36 +54,29 @@ pub(crate) struct InnerBatchResponse { | |
pub(crate) fn process_batch_response( | ||
manager: &mut RequestManager, | ||
rps: Vec<InnerBatchResponse>, | ||
range: Range<u64>, | ||
ids: Vec<Id<'static>>, | ||
) -> Result<(), InvalidRequestId> { | ||
let mut responses = Vec::with_capacity(rps.len()); | ||
|
||
let start_idx = range.start; | ||
|
||
let batch_state = match manager.complete_pending_batch(range.clone()) { | ||
let batch_state = match manager.complete_pending_batch(ids.clone()) { | ||
Some(state) => state, | ||
None => { | ||
tracing::debug!(target: LOG_TARGET, "Received unknown batch response"); | ||
return Err(InvalidRequestId::NotPendingRequest(format!("{:?}", range))); | ||
return Err(InvalidRequestId::NotPendingRequest(format!("{:?}", ids))); | ||
} | ||
}; | ||
|
||
for _ in range { | ||
let err_obj = ErrorObject::borrowed(0, "", None); | ||
responses.push(Err(err_obj)); | ||
} | ||
let mut responses_map: BTreeMap<Id<'static>, Result<_, ErrorObject>> = | ||
|
||
ids.iter().map(|id| (id.clone(), Err(ErrorObject::borrowed(0, "", None)))).collect(); | ||
|
||
for rp in rps { | ||
let maybe_elem = | ||
rp.id.checked_sub(start_idx).and_then(|p| p.try_into().ok()).and_then(|p: usize| responses.get_mut(p)); | ||
|
||
if let Some(elem) = maybe_elem { | ||
*elem = rp.result; | ||
if let Some(entry) = responses_map.get_mut(&rp.id) { | ||
*entry = rp.result; | ||
} else { | ||
return Err(InvalidRequestId::NotPendingRequest(rp.id.to_string())); | ||
} | ||
} | ||
|
||
let responses: Vec<_> = responses_map.into_values().collect(); | ||
|
||
let _ = batch_state.send_back.send(Ok(responses)); | ||
Ok(()) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,10 +32,7 @@ | |
//! > **Note**: The spec allow number, string or null but this crate only supports numbers. | ||
//! - SubscriptionId: unique ID generated by server | ||
|
||
use std::{ | ||
collections::{hash_map::Entry, HashMap}, | ||
ops::Range, | ||
}; | ||
use std::collections::{HashMap, hash_map::Entry}; | ||
|
||
use crate::{ | ||
client::{BatchEntry, Error, SubscriptionReceiver, SubscriptionSender}, | ||
|
@@ -91,7 +88,7 @@ pub(crate) struct RequestManager { | |
/// requests. | ||
subscriptions: HashMap<SubscriptionId<'static>, RequestId>, | ||
/// Pending batch requests. | ||
batches: FxHashMap<Range<u64>, BatchState>, | ||
batches: FxHashMap<Vec<Id<'static>>, BatchState>, | ||
/// Registered Methods for incoming notifications. | ||
notification_handlers: HashMap<String, SubscriptionSink>, | ||
} | ||
|
@@ -124,7 +121,7 @@ impl RequestManager { | |
/// Returns `Ok` if the pending request was successfully inserted otherwise `Err`. | ||
pub(crate) fn insert_pending_batch( | ||
&mut self, | ||
batch: Range<u64>, | ||
batch: Vec<Id<'static>>, | ||
send_back: PendingBatchOneshot, | ||
) -> Result<(), PendingBatchOneshot> { | ||
if let Entry::Vacant(v) = self.batches.entry(batch) { | ||
|
@@ -223,14 +220,23 @@ impl RequestManager { | |
/// Tries to complete a pending batch request. | ||
/// | ||
/// Returns `Some` if the subscription was completed otherwise `None`. | ||
pub(crate) fn complete_pending_batch(&mut self, batch: Range<u64>) -> Option<BatchState> { | ||
match self.batches.entry(batch) { | ||
Entry::Occupied(request) => { | ||
let (_digest, state) = request.remove_entry(); | ||
Some(state) | ||
pub(crate) fn complete_pending_batch(&mut self, batch: Vec<Id<'static>>) -> Option<BatchState> { | ||
let mut matched_key = None; | ||
|
||
for (key, _) in self.batches.iter() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, this is inefficient/annoying compared to the old code 🤔 |
||
if key.len() == batch.len() && batch.iter().all(|id| key.contains(id)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you could just use Vec partialeq/eq impl here. |
||
matched_key = Some(key.clone()); | ||
break; | ||
} | ||
_ => None, | ||
} | ||
|
||
if let Some(key) = matched_key { | ||
if let Some((_key, state)) = self.batches.remove_entry(&key) { | ||
|
||
return Some(state); | ||
} | ||
} | ||
|
||
None | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Most likely this could improved if a different data structure is used to store batches on |
||
} | ||
|
||
/// Tries to complete a pending call. | ||
|
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.
can you please change this to use a custom id i.e., you need to set it by
Client::id_format
? 🙏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.
Done!