Skip to content

Commit 375aaf0

Browse files
authored
chore: stop run when an RPC fails to get latest block number (#263)
1 parent 7f24fe7 commit 375aaf0

File tree

2 files changed

+92
-63
lines changed

2 files changed

+92
-63
lines changed

crates/oracle/src/metrics.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ pub struct Metrics {
1818
registry: Registry,
1919
jrpc_request_duration_seconds: HistogramVec,
2020
jrpc_failure: IntCounterVec,
21+
jrpc_protocol_chain_failure: IntCounterVec,
22+
jrpc_indexed_chain_failure: IntCounterVec,
2123
current_epoch: IntGaugeVec,
2224
last_sent_message: Gauge,
2325
latest_block_number: IntGaugeVec,
@@ -45,6 +47,20 @@ impl Metrics {
4547
registry
4648
)?;
4749

50+
let jrpc_protocol_chain_failure = register_int_counter_vec_with_registry!(
51+
"epoch_block_oracle_jrpc_protocol_chain_failure_total",
52+
"JSON RPC Protocol Chain Request Failure",
53+
&["network"],
54+
registry
55+
)?;
56+
57+
let jrpc_indexed_chain_failure = register_int_counter_vec_with_registry!(
58+
"epoch_block_oracle_jrpc_indexed_chain_failure_total",
59+
"JSON RPC Indexed Chain Request Failure",
60+
&["network"],
61+
registry
62+
)?;
63+
4864
let current_epoch = register_int_gauge_vec_with_registry!(
4965
"epoch_block_oracle_current_epoch",
5066
"Current Epoch",
@@ -93,6 +109,8 @@ impl Metrics {
93109
registry,
94110
jrpc_request_duration_seconds,
95111
jrpc_failure,
112+
jrpc_protocol_chain_failure,
113+
jrpc_indexed_chain_failure,
96114
current_epoch,
97115
last_sent_message,
98116
latest_block_number,
@@ -162,6 +180,20 @@ impl Metrics {
162180
.unwrap()
163181
.inc();
164182
}
183+
184+
pub fn track_jrpc_protocol_chain_failure(&self, network: &str) {
185+
self.jrpc_protocol_chain_failure
186+
.get_metric_with_label_values(&[network])
187+
.unwrap()
188+
.inc();
189+
}
190+
191+
pub fn track_jrpc_indexed_chain_failure(&self, network: &str) {
192+
self.jrpc_indexed_chain_failure
193+
.get_metric_with_label_values(&[network])
194+
.unwrap()
195+
.inc();
196+
}
165197
}
166198

167199
pub async fn metrics_server(metrics: &'static Metrics, port: u16) {

crates/oracle/src/runner/oracle.rs

Lines changed: 60 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,15 @@ impl Oracle {
8787
Err(other) => return Err(other),
8888
};
8989

90-
let protocol_chain_current_block = get_latest_block(self.protocol_chain.web3.clone())
90+
let protocol_chain_current_block = match get_latest_block(self.protocol_chain.web3.clone())
9191
.await
92-
.map_err(Error::BadJrpcProtocolChain)?;
92+
{
93+
Ok(block) => block,
94+
Err(e) => {
95+
METRICS.track_jrpc_protocol_chain_failure(self.config.protocol_chain.id.as_str());
96+
return Err(Error::BadJrpcProtocolChain(e));
97+
}
98+
};
9399
debug!(
94100
number = protocol_chain_current_block.number,
95101
hash = hex::encode(protocol_chain_current_block.hash).as_str(),
@@ -155,72 +161,63 @@ impl Oracle {
155161
info!("Collecting latest block information from all indexed chains.");
156162

157163
let latest_jrpc_blocks_res = get_latest_blocks(&self.indexed_chains).await;
158-
let latest_jrpc_blocks: BTreeMap<Caip2ChainId, BlockPtr> = latest_jrpc_blocks_res
159-
.iter()
160-
.filter_map(|(chain_id, res)| -> Option<(Caip2ChainId, BlockPtr)> {
161-
match res {
162-
Ok(block) => {
163-
METRICS.set_latest_block_number(
164-
chain_id.as_str(),
165-
"jrpc",
166-
block.number as i64,
167-
);
168-
Some((chain_id.clone(), *block))
169-
}
170-
Err(e) => {
171-
warn!(
172-
chain_id = chain_id.as_str(),
173-
error = e.to_string().as_str(),
174-
"Failed to get latest block from chain. Skipping."
175-
);
176-
None
177-
}
164+
let mut latest_jrpc_blocks = BTreeMap::new();
165+
latest_jrpc_blocks_res
166+
.into_iter()
167+
.try_for_each(|(chain_id, res)| match res {
168+
Ok(block) => {
169+
METRICS.set_latest_block_number(chain_id.as_str(), "jrpc", block.number as i64);
170+
latest_jrpc_blocks.insert(chain_id.clone(), block);
171+
Ok(())
178172
}
179-
})
180-
.collect();
173+
Err(e) => {
174+
METRICS.track_jrpc_indexed_chain_failure(chain_id.as_str());
175+
Err(Error::BadJrpcIndexedChain {
176+
chain_id: chain_id.clone(),
177+
error: web3::Error::InvalidResponse(e.to_string()),
178+
})
179+
}
180+
})?;
181181

182182
let latest_blockmeta_blocks_res =
183183
get_latest_blockmeta_blocks(&self.blockmeta_indexed_chains).await;
184-
let latest_blockmeta_blocks: BTreeMap<Caip2ChainId, BlockPtr> = latest_blockmeta_blocks_res
185-
.iter()
186-
.filter_map(|(chain_id, res)| -> Option<(Caip2ChainId, BlockPtr)> {
187-
match res {
188-
Ok(block) => {
189-
METRICS.set_latest_block_number(
190-
chain_id.as_str(),
191-
"blockmeta",
192-
block.num as i64,
193-
);
194-
195-
match block.id.clone().parse::<BlockHash>() {
196-
Ok(hash) => {
197-
let block_ptr = BlockPtr {
198-
number: block.num,
199-
hash: hash.0,
200-
};
201-
Some((chain_id.clone(), block_ptr))
202-
}
203-
Err(e) => {
204-
warn!(
205-
chain_id = chain_id.as_str(),
206-
error = e.to_string().as_str(),
207-
"Failed to parse block hash. Skipping."
208-
);
209-
None
210-
}
184+
let mut latest_blockmeta_blocks = BTreeMap::new();
185+
latest_blockmeta_blocks_res
186+
.into_iter()
187+
.try_for_each(|(chain_id, res)| match res {
188+
Ok(block) => {
189+
METRICS.set_latest_block_number(
190+
chain_id.as_str(),
191+
"blockmeta",
192+
block.num as i64,
193+
);
194+
195+
match block.id.clone().parse::<BlockHash>() {
196+
Ok(hash) => {
197+
let block_ptr = BlockPtr {
198+
number: block.num,
199+
hash: hash.0,
200+
};
201+
latest_blockmeta_blocks.insert(chain_id.clone(), block_ptr);
202+
Ok(())
203+
}
204+
Err(e) => {
205+
METRICS.track_jrpc_indexed_chain_failure(chain_id.as_str());
206+
Err(Error::BadJrpcIndexedChain {
207+
chain_id: chain_id.clone(),
208+
error: web3::Error::InvalidResponse(e.to_string()),
209+
})
211210
}
212-
}
213-
Err(e) => {
214-
warn!(
215-
chain_id = chain_id.as_str(),
216-
error = e.to_string().as_str(),
217-
"Failed to get latest block from chain. Skipping."
218-
);
219-
None
220211
}
221212
}
222-
})
223-
.collect();
213+
Err(e) => {
214+
METRICS.track_jrpc_indexed_chain_failure(chain_id.as_str());
215+
Err(Error::BadJrpcIndexedChain {
216+
chain_id: chain_id.clone(),
217+
error: web3::Error::InvalidResponse(e.to_string()),
218+
})
219+
}
220+
})?;
224221

225222
let latest_blocks: BTreeMap<Caip2ChainId, BlockPtr> = latest_jrpc_blocks
226223
.into_iter()
@@ -395,13 +392,13 @@ mod freshness {
395392
/// targeting the DataEdge contract.
396393
///
397394
/// To assert that, the Block Oracle will need to get the latest block from a JSON RPC provider
398-
/// and compare its number with the subgraphs current block.
395+
/// and compare its number with the subgraph's current block.
399396
///
400397
/// If they are way too different, then the subgraph is not fresh, and we should gracefully
401398
/// handle that error.
402399
///
403400
/// Otherwise, if block numbers are under a certain threshold apart, we could scan the blocks
404-
/// in between and ensure theyre not relevant to the DataEdge contract.
401+
/// in between and ensure they're not relevant to the DataEdge contract.
405402
pub async fn subgraph_is_fresh<T>(
406403
subgraph_latest_block: U64,
407404
current_block: U64,

0 commit comments

Comments
 (0)