Rpc: Add custom error for BigTable data not found (#14762)

* Expose not-found bigtable error

* Add custom rpc error for bigtable data not found

* Return custom rpc error when bigtable block is not found

* Generalize long-term storage
This commit is contained in:
Tyera Eulberg 2021-01-21 21:40:47 -07:00 committed by GitHub
parent 12410541a4
commit 71e9958e06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 7 deletions

View File

@ -12,6 +12,7 @@ pub const JSON_RPC_SERVER_ERROR_NODE_UNHEALTHLY: i64 = -32005;
pub const JSON_RPC_SERVER_ERROR_TRANSACTION_PRECOMPILE_VERIFICATION_FAILURE: i64 = -32006; pub const JSON_RPC_SERVER_ERROR_TRANSACTION_PRECOMPILE_VERIFICATION_FAILURE: i64 = -32006;
pub const JSON_RPC_SERVER_ERROR_SLOT_SKIPPED: i64 = -32007; pub const JSON_RPC_SERVER_ERROR_SLOT_SKIPPED: i64 = -32007;
pub const JSON_RPC_SERVER_ERROR_NO_SNAPSHOT: i64 = -32008; pub const JSON_RPC_SERVER_ERROR_NO_SNAPSHOT: i64 = -32008;
pub const JSON_RPC_SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED: i64 = -32009;
pub enum RpcCustomError { pub enum RpcCustomError {
BlockCleanedUp { BlockCleanedUp {
@ -34,6 +35,9 @@ pub enum RpcCustomError {
slot: Slot, slot: Slot,
}, },
NoSnapshot, NoSnapshot,
LongTermStorageSlotSkipped {
slot: Slot,
},
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
@ -106,6 +110,11 @@ impl From<RpcCustomError> for Error {
message: "No snapshot".to_string(), message: "No snapshot".to_string(),
data: None, data: None,
}, },
RpcCustomError::LongTermStorageSlotSkipped { slot } => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED),
message: format!("Slot {} was skipped, or missing in long-term storage", slot),
data: None,
},
} }
} }
} }

View File

@ -670,6 +670,22 @@ impl JsonRpcRequestProcessor {
Ok(()) Ok(())
} }
fn check_bigtable_result<T>(
&self,
result: &std::result::Result<T, solana_storage_bigtable::Error>,
) -> Result<()>
where
T: std::fmt::Debug,
{
if result.is_err() {
let err = result.as_ref().unwrap_err();
if let solana_storage_bigtable::Error::BlockNotFound(slot) = err {
return Err(RpcCustomError::LongTermStorageSlotSkipped { slot: *slot }.into());
}
}
Ok(())
}
pub fn get_confirmed_block( pub fn get_confirmed_block(
&self, &self,
slot: Slot, slot: Slot,
@ -688,9 +704,11 @@ impl JsonRpcRequestProcessor {
self.check_blockstore_root(&result, slot)?; self.check_blockstore_root(&result, slot)?;
if result.is_err() { if result.is_err() {
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage { if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
return Ok(self let bigtable_result = self
.runtime_handle .runtime_handle
.block_on(bigtable_ledger_storage.get_confirmed_block(slot)) .block_on(bigtable_ledger_storage.get_confirmed_block(slot));
self.check_bigtable_result(&bigtable_result)?;
return Ok(bigtable_result
.ok() .ok()
.map(|confirmed_block| confirmed_block.encode(encoding))); .map(|confirmed_block| confirmed_block.encode(encoding)));
} }
@ -803,9 +821,11 @@ impl JsonRpcRequestProcessor {
self.check_blockstore_root(&result, slot)?; self.check_blockstore_root(&result, slot)?;
if result.is_err() || matches!(result, Ok(None)) { if result.is_err() || matches!(result, Ok(None)) {
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage { if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
return Ok(self let bigtable_result = self
.runtime_handle .runtime_handle
.block_on(bigtable_ledger_storage.get_confirmed_block(slot)) .block_on(bigtable_ledger_storage.get_confirmed_block(slot));
self.check_bigtable_result(&bigtable_result)?;
return Ok(bigtable_result
.ok() .ok()
.and_then(|confirmed_block| confirmed_block.block_time)); .and_then(|confirmed_block| confirmed_block.block_time));
} }

View File

@ -334,7 +334,11 @@ impl LedgerStorage {
"blocks", "blocks",
slot_to_key(slot), slot_to_key(slot),
) )
.await?; .await
.map_err(|err| match err {
bigtable::Error::RowNotFound => Error::BlockNotFound(slot),
_ => err.into(),
})?;
Ok(match block_cell_data { Ok(match block_cell_data {
bigtable::CellData::Bincode(block) => block.into(), bigtable::CellData::Bincode(block) => block.into(),
bigtable::CellData::Protobuf(block) => block.try_into().map_err(|_err| { bigtable::CellData::Protobuf(block) => block.try_into().map_err(|_err| {
@ -347,7 +351,11 @@ impl LedgerStorage {
let mut bigtable = self.connection.client(); let mut bigtable = self.connection.client();
let transaction_info = bigtable let transaction_info = bigtable
.get_bincode_cell::<TransactionInfo>("tx", signature.to_string()) .get_bincode_cell::<TransactionInfo>("tx", signature.to_string())
.await?; .await
.map_err(|err| match err {
bigtable::Error::RowNotFound => Error::SignatureNotFound,
_ => err.into(),
})?;
Ok(transaction_info.into()) Ok(transaction_info.into())
} }
@ -361,7 +369,11 @@ impl LedgerStorage {
// Figure out which block the transaction is located in // Figure out which block the transaction is located in
let TransactionInfo { slot, index, .. } = bigtable let TransactionInfo { slot, index, .. } = bigtable
.get_bincode_cell("tx", signature.to_string()) .get_bincode_cell("tx", signature.to_string())
.await?; .await
.map_err(|err| match err {
bigtable::Error::RowNotFound => Error::SignatureNotFound,
_ => err.into(),
})?;
// Load the block and return the transaction // Load the block and return the transaction
let block = self.get_confirmed_block(slot).await?; let block = self.get_confirmed_block(slot).await?;