From 4faa0274aa25fba2b5ed0beb988ca48b2c24e86e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Wo=C5=9B?= Date: Wed, 13 Sep 2023 15:01:23 +0200 Subject: [PATCH] handle missing blocks as a speacial case of database error --- packages/fuel-indexer-lib/src/lib.rs | 5 +++++ packages/fuel-indexer/src/executor.rs | 10 ++++++++++ packages/fuel-indexer/src/ffi.rs | 24 ++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/fuel-indexer-lib/src/lib.rs b/packages/fuel-indexer-lib/src/lib.rs index 1a26e983a..2d3d98727 100644 --- a/packages/fuel-indexer-lib/src/lib.rs +++ b/packages/fuel-indexer-lib/src/lib.rs @@ -46,6 +46,7 @@ pub enum WasmIndexerError { UnableToFetchLogString, KillSwitch, DatabaseError, + MissingBlocksError, GeneralError, } @@ -60,6 +61,7 @@ impl From for WasmIndexerError { 5 => Self::UnableToFetchLogString, 6 => Self::KillSwitch, 7 => Self::DatabaseError, + 8 => Self::MissingBlocksError, _ => Self::GeneralError, } } @@ -92,6 +94,9 @@ impl std::fmt::Display for WasmIndexerError { Self::DatabaseError => { write!(f, "Failed performing a database operation") } + Self::MissingBlocksError => { + write!(f, "Some blocks are missing") + } Self::GeneralError => write!(f, "Some unspecified WASM error occurred."), } } diff --git a/packages/fuel-indexer/src/executor.rs b/packages/fuel-indexer/src/executor.rs index 24d3d9c88..2290b0320 100644 --- a/packages/fuel-indexer/src/executor.rs +++ b/packages/fuel-indexer/src/executor.rs @@ -190,6 +190,16 @@ pub fn run_executor( } if let Err(e) = result { + if let IndexerError::RuntimeError(ref e) = e { + if let Some(&WasmIndexerError::MissingBlocksError) = + e.downcast_ref::() + { + error!( + "Indexer({indexer_uid}) terminating due to missing blocks." + ); + break; + } + } // Run time metering is deterministic. There is no point in retrying. if let IndexerError::RunTimeLimitExceededError = e { error!("Indexer({indexer_uid}) executor run time limit exceeded. Giving up. <('.')>. Consider increasing metering points"); diff --git a/packages/fuel-indexer/src/ffi.rs b/packages/fuel-indexer/src/ffi.rs index be4b763c7..7480c15b0 100644 --- a/packages/fuel-indexer/src/ffi.rs +++ b/packages/fuel-indexer/src/ffi.rs @@ -227,7 +227,7 @@ fn put_object( if let Err(e) = result { error!("Failed to put_object: {e}"); - return Err(WasmIndexerError::DatabaseError); + return Err(database_operation_failure(e)); }; Ok(()) @@ -285,12 +285,32 @@ fn put_many_to_many_record( if let Err(e) = result { error!("Failed to put_many_to_many_record: {e:?}"); - return Err(WasmIndexerError::DatabaseError); + return Err(database_operation_failure(e)); } Ok(()) } +// Takes care of the exception raised by a trigger to ensure no blocks are +// missed by the indexers. +fn database_operation_failure(e: crate::IndexerError) -> WasmIndexerError { + match e { + crate::IndexerError::SqlxError(e) => { + if let Some(e) = e.as_database_error() { + if let Some(e) = e.try_downcast_ref::() { + if let Some(source) = e.r#where() { + if source.contains("PL/pgSQL function ensure_block_height_consecutive() line 8 at RAISE") { + return WasmIndexerError::MissingBlocksError + } + } + } + } + WasmIndexerError::DatabaseError + } + _ => WasmIndexerError::DatabaseError, + } +} + /// When called from WASM it will terminate the execution and return the error /// code. pub fn early_exit(err_code: u32) -> Result<(), WasmIndexerError> {