add(grpc): `get_results` (#8255)
* add `get_results` grpc call * nitpick
This commit is contained in:
parent
6b8cbf9904
commit
d59c7305b0
|
@ -1,6 +1,8 @@
|
||||||
//! Compile proto files
|
//! Compile proto files
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
tonic_build::compile_protos("proto/scanner.proto")?;
|
tonic_build::configure()
|
||||||
|
.btree_map(["."])
|
||||||
|
.compile(&["proto/scanner.proto"], &[""])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@ service Scanner {
|
||||||
// Deletes a set of keys and their results from the scanner.
|
// Deletes a set of keys and their results from the scanner.
|
||||||
// This request stop the scanner from scanning blocks for the these keys.
|
// This request stop the scanner from scanning blocks for the these keys.
|
||||||
rpc DeleteKeys(DeleteKeysRequest) returns (Empty);
|
rpc DeleteKeys(DeleteKeysRequest) returns (Empty);
|
||||||
|
|
||||||
|
// Get all data we have stored for the given keys.
|
||||||
|
rpc GetResults(GetResultsRequest) returns (GetResultsResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A response to a GetInfo call.
|
// A response to a GetInfo call.
|
||||||
|
@ -34,4 +37,28 @@ message ClearResultsRequest {
|
||||||
message DeleteKeysRequest {
|
message DeleteKeysRequest {
|
||||||
// Keys to delete from scanner.
|
// Keys to delete from scanner.
|
||||||
repeated string keys = 1;
|
repeated string keys = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A request for getting results for a set of keys.
|
||||||
|
message GetResultsRequest {
|
||||||
|
// Keys for which to get results.
|
||||||
|
repeated string keys = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A set of responses for each provided key of a GetResults call.
|
||||||
|
message GetResultsResponse {
|
||||||
|
// Results for each key.
|
||||||
|
map<string, Results> results = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A result for a single key.
|
||||||
|
message Results {
|
||||||
|
// A height, transaction id map
|
||||||
|
map<uint32, TransactionHash> transactions = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A vector of transaction hashes
|
||||||
|
message TransactionHash {
|
||||||
|
// A transaction id hash
|
||||||
|
repeated string hash = 1;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! The gRPC server implementation
|
//! The gRPC server implementation
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
use std::{collections::BTreeMap, net::SocketAddr};
|
||||||
|
|
||||||
use futures_util::future::TryFutureExt;
|
use futures_util::future::TryFutureExt;
|
||||||
use tonic::{transport::Server, Response, Status};
|
use tonic::{transport::Server, Response, Status};
|
||||||
|
@ -12,7 +12,8 @@ use zebra_node_services::scan_service::{
|
||||||
|
|
||||||
use crate::scanner::{
|
use crate::scanner::{
|
||||||
scanner_server::{Scanner, ScannerServer},
|
scanner_server::{Scanner, ScannerServer},
|
||||||
ClearResultsRequest, DeleteKeysRequest, Empty, InfoReply,
|
ClearResultsRequest, DeleteKeysRequest, Empty, GetResultsRequest, GetResultsResponse,
|
||||||
|
InfoReply, Results, TransactionHash,
|
||||||
};
|
};
|
||||||
|
|
||||||
type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
|
type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
|
||||||
|
@ -120,6 +121,57 @@ where
|
||||||
|
|
||||||
Ok(Response::new(Empty {}))
|
Ok(Response::new(Empty {}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_results(
|
||||||
|
&self,
|
||||||
|
request: tonic::Request<GetResultsRequest>,
|
||||||
|
) -> Result<Response<GetResultsResponse>, Status> {
|
||||||
|
let keys = request.into_inner().keys;
|
||||||
|
|
||||||
|
if keys.is_empty() {
|
||||||
|
let msg = "must provide at least 1 key to get results";
|
||||||
|
return Err(Status::invalid_argument(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
let ScanServiceResponse::Results(response) = self
|
||||||
|
.scan_service
|
||||||
|
.clone()
|
||||||
|
.ready()
|
||||||
|
.and_then(|service| service.call(ScanServiceRequest::Results(keys.clone())))
|
||||||
|
.await
|
||||||
|
.map_err(|err| Status::unknown(format!("scan service returned error: {err}")))?
|
||||||
|
else {
|
||||||
|
return Err(Status::unknown(
|
||||||
|
"scan service returned an unexpected response",
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
// If there are no results for a key, we still want to return it with empty results.
|
||||||
|
let empty_map = BTreeMap::new();
|
||||||
|
|
||||||
|
let results = keys
|
||||||
|
.into_iter()
|
||||||
|
.map(|key| {
|
||||||
|
let values = response.get(&key).unwrap_or(&empty_map);
|
||||||
|
|
||||||
|
// Skip heights with no transactions, they are scanner markers and should not be returned.
|
||||||
|
let transactions = Results {
|
||||||
|
transactions: values
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, transactions)| !transactions.is_empty())
|
||||||
|
.map(|(height, transactions)| {
|
||||||
|
let txs = transactions.iter().map(ToString::to_string).collect();
|
||||||
|
(height.0, TransactionHash { hash: txs })
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
};
|
||||||
|
|
||||||
|
(key, transactions)
|
||||||
|
})
|
||||||
|
.collect::<BTreeMap<_, _>>();
|
||||||
|
|
||||||
|
Ok(Response::new(GetResultsResponse { results }))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initializes the zebra-scan gRPC server
|
/// Initializes the zebra-scan gRPC server
|
||||||
|
|
Loading…
Reference in New Issue