Wrap inner providers with RetryingProvider when using QuorumProvider, not the QuorumProvider itself (#1099)

* Retry inner providers when using QuorumProvider, not the QuorumProvider itself

* small log change for serde issues, test quorumprovider

* Add provider_host to retrying provider span

* Deploy
pull/1101/head
Trevor Porter 2 years ago committed by GitHub
parent 1bb06324bc
commit c2a948fcc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      rust/chains/abacus-ethereum/src/retrying.rs
  2. 14
      rust/chains/abacus-ethereum/src/trait_builder.rs
  3. 6
      typescript/infra/config/environments/testnet2/agent.ts

@ -160,7 +160,7 @@ where
impl JsonRpcClient for RetryingProvider<Http> { impl JsonRpcClient for RetryingProvider<Http> {
type Error = RetryingProviderError<Http>; type Error = RetryingProviderError<Http>;
#[instrument(level = "error", skip_all, fields(method = %method))] #[instrument(level = "error", skip_all, fields(method = %method, provider_host = %self.inner.url().host_str().unwrap_or("unknown")))]
async fn request<T, R>(&self, method: &str, params: T) -> Result<R, Self::Error> async fn request<T, R>(&self, method: &str, params: T) -> Result<R, Self::Error>
where where
T: Debug + Serialize + Send + Sync, T: Debug + Serialize + Send + Sync,
@ -190,7 +190,7 @@ impl JsonRpcClient for RetryingProvider<Http> {
} }
} }
Err(HttpClientError::SerdeJson { err, text }) => { Err(HttpClientError::SerdeJson { err, text }) => {
info!(attempt, next_backoff_ms, error = %err, "SerdeJson error in http provider"); info!(attempt, next_backoff_ms, error = %err, text = text, "SerdeJson error in http provider");
HandleMethod::Retry(HttpClientError::SerdeJson { err, text }) HandleMethod::Retry(HttpClientError::SerdeJson { err, text })
} }
}) })

@ -47,8 +47,17 @@ pub trait MakeableWithProvider {
let mut builder = QuorumProvider::builder().quorum(Quorum::Majority); let mut builder = QuorumProvider::builder().quorum(Quorum::Majority);
for url in urls.split(',') { for url in urls.split(',') {
let http_provider: Http = url.parse()?; let http_provider: Http = url.parse()?;
// Wrap the inner providers as RetryingProviders rather than the QuorumProvider.
// We've observed issues where the QuorumProvider will first get the latest block
// number and then submit an RPC at that block height, sometimes resulting in the
// second RPC getting serviced by a node that isn't aware of the requested block
// height yet. Retrying at the QuorumProvider level will result in both those RPCs
// being retried, while retrying at the inner provider level will result in only the
// second RPC being retried (the one with the error), which is the desired behavior.
let retrying_provider =
RetryingProvider::new(http_provider, Some(3), Some(1000));
let metrics_provider = self.wrap_rpc_with_metrics( let metrics_provider = self.wrap_rpc_with_metrics(
http_provider, retrying_provider,
Url::parse(url)?, Url::parse(url)?,
&rpc_metrics, &rpc_metrics,
&middleware_metrics, &middleware_metrics,
@ -57,8 +66,7 @@ pub trait MakeableWithProvider {
builder = builder.add_provider(weighted_provider); builder = builder.add_provider(weighted_provider);
} }
let quorum_provider = builder.build(); let quorum_provider = builder.build();
let retrying = RetryingProvider::new(quorum_provider, Some(3), Some(1000)); self.wrap_with_metrics(quorum_provider, locator, signer, middleware_metrics)
self.wrap_with_metrics(retrying, locator, signer, middleware_metrics)
.await? .await?
} }
Connection::Http { url } => { Connection::Http { url } => {

@ -26,7 +26,7 @@ export const abacus: AgentConfig<TestnetChains> = {
context: Contexts.Abacus, context: Contexts.Abacus,
docker: { docker: {
repo: 'gcr.io/abacus-labs-dev/abacus-agent', repo: 'gcr.io/abacus-labs-dev/abacus-agent',
tag: 'sha-0d76398', tag: 'sha-ebfd1c1',
}, },
aws: { aws: {
region: 'us-east-1', region: 'us-east-1',
@ -37,7 +37,7 @@ export const abacus: AgentConfig<TestnetChains> = {
gelato: { gelato: {
enabledChains: ['alfajores', 'mumbai', 'goerli'], enabledChains: ['alfajores', 'mumbai', 'goerli'],
}, },
connectionType: ConnectionType.Http, connectionType: ConnectionType.HttpQuorum,
validator: { validator: {
default: { default: {
interval: 5, interval: 5,
@ -124,7 +124,7 @@ export const releaseCandidate: AgentConfig<TestnetChains> = {
context: Contexts.ReleaseCandidate, context: Contexts.ReleaseCandidate,
docker: { docker: {
repo: 'gcr.io/abacus-labs-dev/abacus-agent', repo: 'gcr.io/abacus-labs-dev/abacus-agent',
tag: 'sha-0d76398', tag: 'sha-ebfd1c1',
}, },
aws: { aws: {
region: 'us-east-1', region: 'us-east-1',

Loading…
Cancel
Save