improve responses when blocks are not available
This commit is contained in:
parent
694e552b5d
commit
cffc60e7f6
2
TODO.md
2
TODO.md
|
@ -347,7 +347,7 @@ These are not yet ordered. There might be duplicates. We might not actually need
|
||||||
- [ ] `stat delay` script
|
- [ ] `stat delay` script
|
||||||
- query database for newest stat
|
- query database for newest stat
|
||||||
- [ ] period_datetime should always be :00. right now it depends on start time
|
- [ ] period_datetime should always be :00. right now it depends on start time
|
||||||
- [ ] two servers running will confuse rpc_accounting!
|
- [ ] we have our hard rate limiter set up with a period of 60. but most providers have period of 1- [ ] two servers running will confuse rpc_accounting!
|
||||||
- it won't happen with users often because they should be sticky to one proxy, but unauthenticated users will definitely hit this
|
- it won't happen with users often because they should be sticky to one proxy, but unauthenticated users will definitely hit this
|
||||||
- one option: we need the insert to be an upsert, but how do we merge historgrams?
|
- one option: we need the insert to be an upsert, but how do we merge historgrams?
|
||||||
- [ ] don't use systemtime. use chrono
|
- [ ] don't use systemtime. use chrono
|
||||||
|
|
|
@ -1326,8 +1326,8 @@ impl Web3ProxyApp {
|
||||||
}
|
}
|
||||||
"eth_subscribe" => {
|
"eth_subscribe" => {
|
||||||
return Ok((
|
return Ok((
|
||||||
JsonRpcForwardedResponse::from_string(
|
JsonRpcForwardedResponse::from_str(
|
||||||
format!("notifications not supported. eth_subscribe is only available over a websocket"),
|
"notifications not supported. eth_subscribe is only available over a websocket",
|
||||||
Some(-32601),
|
Some(-32601),
|
||||||
Some(request_id),
|
Some(request_id),
|
||||||
),
|
),
|
||||||
|
@ -1336,8 +1336,8 @@ impl Web3ProxyApp {
|
||||||
}
|
}
|
||||||
"eth_unsubscribe" => {
|
"eth_unsubscribe" => {
|
||||||
return Ok((
|
return Ok((
|
||||||
JsonRpcForwardedResponse::from_string(
|
JsonRpcForwardedResponse::from_str(
|
||||||
format!("notifications not supported. eth_unsubscribe is only available over a websocket"),
|
"notifications not supported. eth_unsubscribe is only available over a websocket",
|
||||||
Some(-32601),
|
Some(-32601),
|
||||||
Some(request_id),
|
Some(request_id),
|
||||||
),
|
),
|
||||||
|
|
|
@ -123,6 +123,7 @@ fn main() -> anyhow::Result<()> {
|
||||||
"web3_proxy=trace",
|
"web3_proxy=trace",
|
||||||
"web3_proxy_cli=trace",
|
"web3_proxy_cli=trace",
|
||||||
"web3_proxy::rpcs::blockchain=info",
|
"web3_proxy::rpcs::blockchain=info",
|
||||||
|
"web3_proxy::rpcs::request=debug",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -149,7 +149,7 @@ impl Web3Connections {
|
||||||
// TODO: if error, retry?
|
// TODO: if error, retry?
|
||||||
let block: ArcBlock = match rpc {
|
let block: ArcBlock = match rpc {
|
||||||
Some(rpc) => rpc
|
Some(rpc) => rpc
|
||||||
.wait_for_request_handle(authorization, Duration::from_secs(30), false)
|
.wait_for_request_handle(authorization, Some(Duration::from_secs(30)), false)
|
||||||
.await?
|
.await?
|
||||||
.request::<_, Option<_>>(
|
.request::<_, Option<_>>(
|
||||||
"eth_getBlockByHash",
|
"eth_getBlockByHash",
|
||||||
|
@ -253,11 +253,16 @@ impl Web3Connections {
|
||||||
|
|
||||||
// TODO: if error, retry?
|
// TODO: if error, retry?
|
||||||
// TODO: request_metadata or authorization?
|
// TODO: request_metadata or authorization?
|
||||||
|
// we don't actually set min_block_needed here because all nodes have all blocks
|
||||||
let response = self
|
let response = self
|
||||||
.try_send_best_consensus_head_connection(authorization, request, None, Some(num))
|
.try_send_best_consensus_head_connection(authorization, request, None, None)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let raw_block = response.result.context("no block result")?;
|
if let Some(err) = response.error {
|
||||||
|
debug!("could not find canonical block {}: {:?}", num, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
let raw_block = response.result.context("no cannonical block result")?;
|
||||||
|
|
||||||
let block: ArcBlock = serde_json::from_str(raw_block.get())?;
|
let block: ArcBlock = serde_json::from_str(raw_block.get())?;
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ impl Web3Connection {
|
||||||
// TODO: start at 0 or 1?
|
// TODO: start at 0 or 1?
|
||||||
for block_data_limit in [0, 32, 64, 128, 256, 512, 1024, 90_000, u64::MAX] {
|
for block_data_limit in [0, 32, 64, 128, 256, 512, 1024, 90_000, u64::MAX] {
|
||||||
let handle = self
|
let handle = self
|
||||||
.wait_for_request_handle(authorization, Duration::from_secs(30), true)
|
.wait_for_request_handle(authorization, None, true)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let head_block_num_future = handle.request::<Option<()>, U256>(
|
let head_block_num_future = handle.request::<Option<()>, U256>(
|
||||||
|
@ -239,7 +239,7 @@ impl Web3Connection {
|
||||||
// TODO: wait for the handle BEFORE we check the current block number. it might be delayed too!
|
// TODO: wait for the handle BEFORE we check the current block number. it might be delayed too!
|
||||||
// TODO: what should the request be?
|
// TODO: what should the request be?
|
||||||
let handle = self
|
let handle = self
|
||||||
.wait_for_request_handle(authorization, Duration::from_secs(30), true)
|
.wait_for_request_handle(authorization, None, true)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let archive_result: Result<Bytes, _> = handle
|
let archive_result: Result<Bytes, _> = handle
|
||||||
|
@ -436,7 +436,7 @@ impl Web3Connection {
|
||||||
// TODO: what should the timeout be? should there be a request timeout?
|
// TODO: what should the timeout be? should there be a request timeout?
|
||||||
// trace!("waiting on chain id for {}", self);
|
// trace!("waiting on chain id for {}", self);
|
||||||
let found_chain_id: Result<U64, _> = self
|
let found_chain_id: Result<U64, _> = self
|
||||||
.wait_for_request_handle(&authorization, Duration::from_secs(30), true)
|
.wait_for_request_handle(&authorization, None, true)
|
||||||
.await?
|
.await?
|
||||||
.request(
|
.request(
|
||||||
"eth_chainId",
|
"eth_chainId",
|
||||||
|
@ -720,7 +720,7 @@ impl Web3Connection {
|
||||||
loop {
|
loop {
|
||||||
// TODO: what should the max_wait be?
|
// TODO: what should the max_wait be?
|
||||||
match self
|
match self
|
||||||
.wait_for_request_handle(&authorization, Duration::from_secs(30), false)
|
.wait_for_request_handle(&authorization, None, false)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(active_request_handle) => {
|
Ok(active_request_handle) => {
|
||||||
|
@ -806,7 +806,7 @@ impl Web3Connection {
|
||||||
Web3Provider::Ws(provider) => {
|
Web3Provider::Ws(provider) => {
|
||||||
// todo: move subscribe_blocks onto the request handle?
|
// todo: move subscribe_blocks onto the request handle?
|
||||||
let active_request_handle = self
|
let active_request_handle = self
|
||||||
.wait_for_request_handle(&authorization, Duration::from_secs(30), false)
|
.wait_for_request_handle(&authorization, None, false)
|
||||||
.await;
|
.await;
|
||||||
let mut stream = provider.subscribe_blocks().await?;
|
let mut stream = provider.subscribe_blocks().await?;
|
||||||
drop(active_request_handle);
|
drop(active_request_handle);
|
||||||
|
@ -816,7 +816,7 @@ impl Web3Connection {
|
||||||
// all it does is print "new block" for the same block as current block
|
// all it does is print "new block" for the same block as current block
|
||||||
// TODO: how does this get wrapped in an arc? does ethers handle that?
|
// TODO: how does this get wrapped in an arc? does ethers handle that?
|
||||||
let block: Result<Option<ArcBlock>, _> = self
|
let block: Result<Option<ArcBlock>, _> = self
|
||||||
.wait_for_request_handle(&authorization, Duration::from_secs(30), false)
|
.wait_for_request_handle(&authorization, None, false)
|
||||||
.await?
|
.await?
|
||||||
.request(
|
.request(
|
||||||
"eth_getBlockByNumber",
|
"eth_getBlockByNumber",
|
||||||
|
@ -917,8 +917,8 @@ impl Web3Connection {
|
||||||
Web3Provider::Ws(provider) => {
|
Web3Provider::Ws(provider) => {
|
||||||
// TODO: maybe the subscribe_pending_txs function should be on the active_request_handle
|
// TODO: maybe the subscribe_pending_txs function should be on the active_request_handle
|
||||||
let active_request_handle = self
|
let active_request_handle = self
|
||||||
.wait_for_request_handle(&authorization, Duration::from_secs(30), false)
|
.wait_for_request_handle(&authorization, None, false)
|
||||||
.await;
|
.await?;
|
||||||
|
|
||||||
let mut stream = provider.subscribe_pending_txs().await?;
|
let mut stream = provider.subscribe_pending_txs().await?;
|
||||||
|
|
||||||
|
@ -955,10 +955,10 @@ impl Web3Connection {
|
||||||
pub async fn wait_for_request_handle(
|
pub async fn wait_for_request_handle(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
authorization: &Arc<Authorization>,
|
authorization: &Arc<Authorization>,
|
||||||
max_wait: Duration,
|
max_wait: Option<Duration>,
|
||||||
allow_not_ready: bool,
|
allow_not_ready: bool,
|
||||||
) -> anyhow::Result<OpenRequestHandle> {
|
) -> anyhow::Result<OpenRequestHandle> {
|
||||||
let max_wait = Instant::now() + max_wait;
|
let max_wait = max_wait.map(|x| Instant::now() + x);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match self
|
match self
|
||||||
|
@ -968,25 +968,35 @@ impl Web3Connection {
|
||||||
Ok(OpenRequestResult::Handle(handle)) => return Ok(handle),
|
Ok(OpenRequestResult::Handle(handle)) => return Ok(handle),
|
||||||
Ok(OpenRequestResult::RetryAt(retry_at)) => {
|
Ok(OpenRequestResult::RetryAt(retry_at)) => {
|
||||||
// TODO: emit a stat?
|
// TODO: emit a stat?
|
||||||
trace!("{} waiting for request handle until {:?}", self, retry_at);
|
let wait = retry_at.duration_since(Instant::now());
|
||||||
|
|
||||||
|
trace!(
|
||||||
|
"waiting {} millis for request handle on {}",
|
||||||
|
wait.as_millis(),
|
||||||
|
self
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(max_wait) = max_wait {
|
||||||
if retry_at > max_wait {
|
if retry_at > max_wait {
|
||||||
// break now since we will wait past our maximum wait time
|
// break now since we will wait past our maximum wait time
|
||||||
// TODO: don't use anyhow. use specific error type
|
// TODO: don't use anyhow. use specific error type
|
||||||
return Err(anyhow::anyhow!("timeout waiting for request handle"));
|
return Err(anyhow::anyhow!("timeout waiting for request handle"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sleep_until(retry_at).await;
|
sleep_until(retry_at).await;
|
||||||
}
|
}
|
||||||
Ok(OpenRequestResult::NotReady) => {
|
Ok(OpenRequestResult::NotReady(_)) => {
|
||||||
// TODO: when can this happen? log? emit a stat?
|
// TODO: when can this happen? log? emit a stat?
|
||||||
trace!("{} has no handle ready", self);
|
trace!("{} has no handle ready", self);
|
||||||
|
|
||||||
|
if let Some(max_wait) = max_wait {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
|
|
||||||
if now > max_wait {
|
if now > max_wait {
|
||||||
return Err(anyhow::anyhow!("unable to retry for request handle"));
|
return Err(anyhow::anyhow!("unable to retry for request handle"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: sleep how long? maybe just error?
|
// TODO: sleep how long? maybe just error?
|
||||||
// TODO: instead of an arbitrary sleep, subscribe to the head block on this
|
// TODO: instead of an arbitrary sleep, subscribe to the head block on this
|
||||||
|
@ -1013,7 +1023,8 @@ impl Web3Connection {
|
||||||
.await
|
.await
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
return Ok(OpenRequestResult::NotReady);
|
trace!("{} is not ready", self);
|
||||||
|
return Ok(OpenRequestResult::NotReady(self.backup));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(hard_limit_until) = self.hard_limit_until.as_ref() {
|
if let Some(hard_limit_until) = self.hard_limit_until.as_ref() {
|
||||||
|
@ -1029,25 +1040,33 @@ impl Web3Connection {
|
||||||
// check rate limits
|
// check rate limits
|
||||||
if let Some(ratelimiter) = self.hard_limit.as_ref() {
|
if let Some(ratelimiter) = self.hard_limit.as_ref() {
|
||||||
// TODO: how should we know if we should set expire or not?
|
// TODO: how should we know if we should set expire or not?
|
||||||
match ratelimiter.throttle().await? {
|
match ratelimiter
|
||||||
|
.throttle()
|
||||||
|
.await
|
||||||
|
.context(format!("attempting to throttle {}", self))?
|
||||||
|
{
|
||||||
RedisRateLimitResult::Allowed(_) => {
|
RedisRateLimitResult::Allowed(_) => {
|
||||||
// trace!("rate limit succeeded")
|
// trace!("rate limit succeeded")
|
||||||
}
|
}
|
||||||
RedisRateLimitResult::RetryAt(retry_at, _) => {
|
RedisRateLimitResult::RetryAt(retry_at, _) => {
|
||||||
// rate limit failed
|
// rate limit gave us a wait time
|
||||||
// save the smallest retry_after. if nothing succeeds, return an Err with retry_after in it
|
if !self.backup {
|
||||||
// TODO: use tracing better
|
let when = retry_at.duration_since(Instant::now());
|
||||||
// TODO: i'm seeing "Exhausted rate limit on moralis: 0ns". How is it getting 0?
|
warn!(
|
||||||
warn!("Exhausted rate limit on {}. Retry at {:?}", self, retry_at);
|
"Exhausted rate limit on {}. Retry in {}ms",
|
||||||
|
self,
|
||||||
|
when.as_millis()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(hard_limit_until) = self.hard_limit_until.as_ref() {
|
if let Some(hard_limit_until) = self.hard_limit_until.as_ref() {
|
||||||
hard_limit_until.send(retry_at.clone())?;
|
hard_limit_until.send_replace(retry_at.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(OpenRequestResult::RetryAt(retry_at));
|
return Ok(OpenRequestResult::RetryAt(retry_at));
|
||||||
}
|
}
|
||||||
RedisRateLimitResult::RetryNever => {
|
RedisRateLimitResult::RetryNever => {
|
||||||
return Ok(OpenRequestResult::NotReady);
|
return Ok(OpenRequestResult::NotReady(self.backup));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -428,8 +428,11 @@ impl Web3Connections {
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
// TODO: this might use backups too eagerly. but even when we allow backups, we still prioritize our own
|
||||||
|
if matches!(without_backups, OpenRequestResult::Handle(_)) {
|
||||||
return Ok(without_backups);
|
return Ok(without_backups);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self._best_consensus_head_connection(
|
self._best_consensus_head_connection(
|
||||||
true,
|
true,
|
||||||
|
@ -460,7 +463,7 @@ impl Web3Connections {
|
||||||
head_block.number()
|
head_block.number()
|
||||||
} else {
|
} else {
|
||||||
// TODO: optionally wait for a head block >= min_block_needed
|
// TODO: optionally wait for a head block >= min_block_needed
|
||||||
return Ok(OpenRequestResult::NotReady);
|
return Ok(OpenRequestResult::NotReady(allow_backups));
|
||||||
};
|
};
|
||||||
|
|
||||||
let min_block_needed = min_block_needed.unwrap_or(&head_block_num);
|
let min_block_needed = min_block_needed.unwrap_or(&head_block_num);
|
||||||
|
@ -504,7 +507,7 @@ impl Web3Connections {
|
||||||
}
|
}
|
||||||
cmp::Ordering::Greater => {
|
cmp::Ordering::Greater => {
|
||||||
// TODO? if the blocks is close and wait_for_sync and allow_backups, wait for change on a watch_consensus_connections_receiver().subscribe()
|
// TODO? if the blocks is close and wait_for_sync and allow_backups, wait for change on a watch_consensus_connections_receiver().subscribe()
|
||||||
return Ok(OpenRequestResult::NotReady);
|
return Ok(OpenRequestResult::NotReady(allow_backups));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,7 +598,7 @@ impl Web3Connections {
|
||||||
Ok(OpenRequestResult::RetryAt(retry_at)) => {
|
Ok(OpenRequestResult::RetryAt(retry_at)) => {
|
||||||
earliest_retry_at = earliest_retry_at.min(Some(retry_at));
|
earliest_retry_at = earliest_retry_at.min(Some(retry_at));
|
||||||
}
|
}
|
||||||
Ok(OpenRequestResult::NotReady) => {
|
Ok(OpenRequestResult::NotReady(_)) => {
|
||||||
// TODO: log a warning? emit a stat?
|
// TODO: log a warning? emit a stat?
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -625,7 +628,7 @@ impl Web3Connections {
|
||||||
|
|
||||||
// TODO: should we log here?
|
// TODO: should we log here?
|
||||||
|
|
||||||
Ok(OpenRequestResult::NotReady)
|
Ok(OpenRequestResult::NotReady(allow_backups))
|
||||||
}
|
}
|
||||||
Some(earliest_retry_at) => {
|
Some(earliest_retry_at) => {
|
||||||
warn!("no servers on {:?}! {:?}", self, earliest_retry_at);
|
warn!("no servers on {:?}! {:?}", self, earliest_retry_at);
|
||||||
|
@ -719,7 +722,7 @@ impl Web3Connections {
|
||||||
max_count -= 1;
|
max_count -= 1;
|
||||||
selected_rpcs.push(handle)
|
selected_rpcs.push(handle)
|
||||||
}
|
}
|
||||||
Ok(OpenRequestResult::NotReady) => {
|
Ok(OpenRequestResult::NotReady(_)) => {
|
||||||
warn!("no request handle for {}", connection)
|
warn!("no request handle for {}", connection)
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -911,17 +914,51 @@ impl Web3Connections {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OpenRequestResult::NotReady => {
|
OpenRequestResult::NotReady(backups_included) => {
|
||||||
if let Some(request_metadata) = request_metadata {
|
if let Some(request_metadata) = request_metadata {
|
||||||
request_metadata.no_servers.fetch_add(1, Ordering::Release);
|
request_metadata.no_servers.fetch_add(1, Ordering::Release);
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("No servers ready. Waiting up to 1 second for change in synced servers");
|
// todo!(
|
||||||
|
// "check if we are requesting an old block and no archive servers are synced"
|
||||||
|
// );
|
||||||
|
|
||||||
|
if let Some(min_block_needed) = min_block_needed {
|
||||||
|
let mut theres_a_chance = false;
|
||||||
|
|
||||||
|
for potential_conn in self.conns.values() {
|
||||||
|
if skip_rpcs.contains(potential_conn) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: should we instead check if has_block_data but with the current head block?
|
||||||
|
if potential_conn.has_block_data(min_block_needed) {
|
||||||
|
trace!("chance for {} on {}", min_block_needed, potential_conn);
|
||||||
|
theres_a_chance = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_rpcs.push(potential_conn.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !theres_a_chance {
|
||||||
|
debug!("no chance of finding data in block #{}", min_block_needed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if backups_included {
|
||||||
|
// if NotReady and we tried backups, there's no chance
|
||||||
|
warn!("No servers ready even after checking backups");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("No servers ready. Waiting up to 1 second for change in synced servers");
|
||||||
|
|
||||||
// TODO: exponential backoff?
|
// TODO: exponential backoff?
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = sleep(Duration::from_secs(1)) => {
|
_ = sleep(Duration::from_secs(1)) => {
|
||||||
skip_rpcs.pop();
|
// do NOT pop the last rpc off skip here
|
||||||
}
|
}
|
||||||
_ = watch_consensus_connections.changed() => {
|
_ = watch_consensus_connections.changed() => {
|
||||||
watch_consensus_connections.borrow_and_update();
|
watch_consensus_connections.borrow_and_update();
|
||||||
|
@ -944,17 +981,30 @@ impl Web3Connections {
|
||||||
}
|
}
|
||||||
|
|
||||||
let num_conns = self.conns.len();
|
let num_conns = self.conns.len();
|
||||||
|
let num_skipped = skip_rpcs.len();
|
||||||
|
|
||||||
if skip_rpcs.is_empty() {
|
if num_skipped == 0 {
|
||||||
error!("No servers synced ({} known)", num_conns);
|
error!("No servers synced ({} known)", num_conns);
|
||||||
|
|
||||||
Err(anyhow::anyhow!("No servers synced ({} known)", num_conns))
|
return Ok(JsonRpcForwardedResponse::from_str(
|
||||||
|
"No servers synced",
|
||||||
|
Some(-32000),
|
||||||
|
Some(request.id),
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
Err(anyhow::anyhow!(
|
// TODO: warn? debug? trace?
|
||||||
"{}/{} servers erred",
|
warn!(
|
||||||
skip_rpcs.len(),
|
"Requested data was not available on {}/{} servers",
|
||||||
num_conns
|
num_skipped, num_conns
|
||||||
))
|
);
|
||||||
|
|
||||||
|
// TODO: what error code?
|
||||||
|
// cloudflare gives {"jsonrpc":"2.0","error":{"code":-32043,"message":"Requested data cannot be older than 128 blocks."},"id":1}
|
||||||
|
return Ok(JsonRpcForwardedResponse::from_str(
|
||||||
|
"Requested data is not available",
|
||||||
|
Some(-32043),
|
||||||
|
Some(request.id),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1287,7 +1337,7 @@ mod tests {
|
||||||
|
|
||||||
dbg!(&x);
|
dbg!(&x);
|
||||||
|
|
||||||
assert!(matches!(x, OpenRequestResult::NotReady));
|
assert!(matches!(x, OpenRequestResult::NotReady(true)));
|
||||||
|
|
||||||
// add lagged blocks to the conns. both servers should be allowed
|
// add lagged blocks to the conns. both servers should be allowed
|
||||||
lagged_block.block = conns.save_block(lagged_block.block, true).await.unwrap();
|
lagged_block.block = conns.save_block(lagged_block.block, true).await.unwrap();
|
||||||
|
@ -1360,7 +1410,7 @@ mod tests {
|
||||||
conns
|
conns
|
||||||
.best_consensus_head_connection(&authorization, None, &[], Some(&2.into()))
|
.best_consensus_head_connection(&authorization, None, &[], Some(&2.into()))
|
||||||
.await,
|
.await,
|
||||||
Ok(OpenRequestResult::NotReady)
|
Ok(OpenRequestResult::NotReady(true))
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,8 @@ pub enum OpenRequestResult {
|
||||||
/// Unable to start a request. Retry at the given time.
|
/// Unable to start a request. Retry at the given time.
|
||||||
RetryAt(Instant),
|
RetryAt(Instant),
|
||||||
/// Unable to start a request because the server is not synced
|
/// Unable to start a request because the server is not synced
|
||||||
NotReady,
|
/// contains "true" if backup servers were attempted
|
||||||
|
NotReady(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make RPC requests through this handle and drop it when you are done.
|
/// Make RPC requests through this handle and drop it when you are done.
|
||||||
|
|
Loading…
Reference in New Issue