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(sdk): fetch many and return metadata and proof to client #2331

Merged
merged 4 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/rs-dapi-client/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl<E: CanRetry> CanRetry for ExecutionError<E> {
}

/// Request execution response.
#[derive(Debug, Clone, Eq, PartialEq)]
#[derive(Debug, Clone, PartialEq)]
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved
pub struct ExecutionResponse<R> {
/// The response from the request
pub inner: R,
Expand Down
115 changes: 94 additions & 21 deletions packages/rs-sdk/src/platform/fetch_many.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ use dapi_grpc::platform::v0::{
GetDataContractsRequest, GetEpochsInfoRequest, GetEvonodesProposedEpochBlocksByIdsRequest,
GetEvonodesProposedEpochBlocksByRangeRequest, GetIdentitiesBalancesRequest,
GetIdentityKeysRequest, GetPathElementsRequest, GetProtocolVersionUpgradeStateRequest,
GetProtocolVersionUpgradeVoteStatusRequest, GetVotePollsByEndDateRequest,
GetProtocolVersionUpgradeVoteStatusRequest, GetVotePollsByEndDateRequest, Proof,
ResponseMetadata,
};
use dashcore_rpc::dashcore::ProTxHash;
use dpp::data_contract::DataContract;
Expand Down Expand Up @@ -145,8 +146,71 @@ where
sdk: &Sdk,
query: Q,
) -> Result<O, Error> {
Self::fetch_many_with_metadata_and_proof(sdk, query, None)
.await
.map(|(objects, _, _)| objects)
}

/// Fetch multiple objects from Platform with metadata.
///
/// Fetch objects from Platform that satisfy the provided [Query].
/// This method allows you to retrieve the metadata associated with the response.
///
/// ## Parameters
///
/// - `sdk`: An instance of [Sdk].
/// - `query`: A query parameter implementing [`crate::platform::query::Query`] to specify the data to be fetched.
/// - `settings`: An optional `RequestSettings` to give greater flexibility on the request.
///
/// ## Returns
///
/// Returns a `Result` containing either:
///
/// * A tuple `(O, ResponseMetadata)` where `O` is the collection of fetched objects, and `ResponseMetadata` contains metadata about the response.
/// * [`Error`](crate::error::Error) when an error occurs.
///
/// ## Error Handling
///
/// Any errors encountered during the execution are returned as [Error] instances.
async fn fetch_many_with_metadata<Q: Query<<Self as FetchMany<K, O>>::Request>>(
sdk: &Sdk,
query: Q,
settings: Option<RequestSettings>,
) -> Result<(O, ResponseMetadata), Error> {
Self::fetch_many_with_metadata_and_proof(sdk, query, settings)
.await
.map(|(objects, metadata, _)| (objects, metadata))
}

/// Fetch multiple objects from Platform with metadata and underlying proof.
///
/// Fetch objects from Platform that satisfy the provided [Query].
/// This method allows you to retrieve the metadata and the underlying proof associated with the response.
///
/// ## Parameters
///
/// - `sdk`: An instance of [Sdk].
/// - `query`: A query parameter implementing [`crate::platform::query::Query`] to specify the data to be fetched.
/// - `settings`: An optional `RequestSettings` to give greater flexibility on the request.
///
/// ## Returns
///
/// Returns a `Result` containing either:
///
/// * A tuple `(O, ResponseMetadata, Proof)` where `O` is the collection of fetched objects, `ResponseMetadata` contains metadata about the response, and `Proof` is the underlying proof.
/// * [`Error`](crate::error::Error) when an error occurs.
///
/// ## Error Handling
///
/// Any errors encountered during the execution are returned as [Error] instances.
async fn fetch_many_with_metadata_and_proof<Q: Query<<Self as FetchMany<K, O>>::Request>>(
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved
sdk: &Sdk,
query: Q,
settings: Option<RequestSettings>,
) -> Result<(O, ResponseMetadata, Proof), Error> {
let request = &query.query(sdk.prove())?;
let closure = |settings: RequestSettings| async move {

let fut = |settings: RequestSettings| async move {
let ExecutionResponse {
address,
retries,
Expand All @@ -158,28 +222,37 @@ where
.map_err(|e| e.inner_into())?;

let object_type = std::any::type_name::<Self>().to_string();
tracing::trace!(request = ?request, response = ?response, ?address, retries, object_type, "fetched object from platform");
tracing::trace!(
request = ?request,
response = ?response,
?address,
retries,
object_type,
"fetched objects from platform"
);

sdk.parse_proof::<<Self as FetchMany<K, O>>::Request, O>(request.clone(), response)
.await
.map(|o| ExecutionResponse {
inner: o,
retries,
address: address.clone(),
})
.map_err(|e| ExecutionError {
inner: e,
retries,
address: Some(address),
})
sdk.parse_proof_with_metadata_and_proof::<<Self as FetchMany<K, O>>::Request, O>(
request.clone(),
response,
)
.await
.map_err(|e| ExecutionError {
inner: e,
address: Some(address.clone()),
retries,
})
.map(|(o, metadata, proof)| ExecutionResponse {
inner: (o.unwrap_or_default(), metadata, proof),
Copy link
Contributor

@coderabbitai coderabbitai bot Nov 15, 2024

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Handle potential None value without using unwrap_or_default()

On line 245, o.unwrap_or_default() is used when constructing the ExecutionResponse. This could mask situations where no data is returned (o is None), possibly leading to confusion for the caller. Consider handling the None case explicitly, perhaps by returning an error or conveying that no data was found.

Copy link
Member Author

Choose a reason for hiding this comment

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

it's okay

Copy link
Contributor

Choose a reason for hiding this comment

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

@QuantumExplorer, understood.

retries,
address: address.clone(),
})
};

let settings = sdk.dapi_client_settings;
let settings = sdk
.dapi_client_settings
.override_by(settings.unwrap_or_default());

retry(settings, closure)
.await
.into_inner()
.map(|o| o.unwrap_or_default())
retry(settings, fut).await.into_inner()
}

/// Fetch multiple objects from Platform by their identifiers.
Expand Down Expand Up @@ -260,7 +333,7 @@ impl FetchMany<Identifier, Documents> for Document {
let ExecutionResponse {
address,
retries,
inner: response,
inner: response
} = request.execute(sdk, settings).await.map_err(|e| e.inner_into())?;

tracing::trace!(request=?document_query, response=?response, ?address, retries, "fetch multiple documents");
Expand Down
Loading