From ab843eff906d3901e3503cb4d6836c692c1f65be Mon Sep 17 00:00:00 2001 From: Dmitry Zakharov Date: Wed, 18 Dec 2024 13:01:23 +0400 Subject: [PATCH] Retry on wrong hypersync instance response (#388) * Retry on wrong hypersync instance response * Log info instead of warn --- .../cli/templates/static/codegen/src/Time.res | 4 ++-- .../src/eventFetching/hyperfuel/HyperFuel.res | 24 +++++++++++++------ .../src/eventFetching/hypersync/HyperSync.res | 18 ++++++++++---- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/codegenerator/cli/templates/static/codegen/src/Time.res b/codegenerator/cli/templates/static/codegen/src/Time.res index 3464bd476..08052a3ba 100644 --- a/codegenerator/cli/templates/static/codegen/src/Time.res +++ b/codegenerator/cli/templates/static/codegen/src/Time.res @@ -1,8 +1,8 @@ let resolvePromiseAfterDelay = (~delayMilliseconds) => Utils.delay(delayMilliseconds) let rec retryAsyncWithExponentialBackOff = async ( - ~backOffMillis=1000, - ~multiplicative=2, + ~backOffMillis=100, + ~multiplicative=4, ~retryCount=0, ~maxRetries=5, ~logger: option=None, diff --git a/codegenerator/cli/templates/static/codegen/src/eventFetching/hyperfuel/HyperFuel.res b/codegenerator/cli/templates/static/codegen/src/eventFetching/hyperfuel/HyperFuel.res index c84bc5561..e719a62e3 100644 --- a/codegenerator/cli/templates/static/codegen/src/eventFetching/hyperfuel/HyperFuel.res +++ b/codegenerator/cli/templates/static/codegen/src/eventFetching/hyperfuel/HyperFuel.res @@ -90,8 +90,8 @@ module LogsQuery = { { fromBlock, toBlockExclusive: ?switch toBlockInclusive { - | Some(toBlockInclusive) => Some(toBlockInclusive + 1) - | None => None + | Some(toBlockInclusive) => Some(toBlockInclusive + 1) + | None => None }, receipts: recieptsSelection, fieldSelection: { @@ -109,7 +109,7 @@ module LogsQuery = { Amount, ToAddress, AssetId, - To + To, ], block: [Id, Height, Time], }, @@ -201,7 +201,16 @@ module LogsQuery = { ~params={"type": "hypersync query", "fromBlock": fromBlock, "serverUrl": serverUrl}, ) - let executeQuery = () => hyperFuelClient->HyperFuelClient.getSelectedData(query) + let executeQuery = async () => { + let res = await hyperFuelClient->HyperFuelClient.getSelectedData(query) + if res.nextBlock <= fromBlock { + // Might happen when /height response was from another instance of HyperSync + Js.Exn.raiseError( + "Received page response from another instance of HyperFuel. Should work after a retry.", + ) + } + res + } let res = await executeQuery->Time.retryAsyncWithExponentialBackOff(~logger=Some(logger)) @@ -261,10 +270,11 @@ module BlockData = { // If the block is not found, retry the query. This can occur since replicas of hypersync might not hack caught up yet if res.nextBlock <= blockNumber { let logger = Logging.createChild(~params={"url": serverUrl}) - logger->Logging.childWarn( - `Block #${blockNumber->Int.toString} not found in hypersync. HyperSync runs multiple instances of hypersync and it is possible that they drift independently slightly from the head. Retrying query in 100ms.`, + let delayMilliseconds = 100 + logger->Logging.childInfo( + `Block #${blockNumber->Int.toString} not found in HyperFuel. HyperFuel has multiple instances and it's possible that they drift independently slightly from the head. Indexing should continue correctly after retrying the query in ${delayMilliseconds->Int.toString}ms.`, ) - await Time.resolvePromiseAfterDelay(~delayMilliseconds=100) + await Time.resolvePromiseAfterDelay(~delayMilliseconds) await queryBlockData(~serverUrl, ~blockNumber, ~logger) } else { res->convertResponse diff --git a/codegenerator/cli/templates/static/codegen/src/eventFetching/hypersync/HyperSync.res b/codegenerator/cli/templates/static/codegen/src/eventFetching/hypersync/HyperSync.res index 0986c62f1..d88ce82a9 100644 --- a/codegenerator/cli/templates/static/codegen/src/eventFetching/hypersync/HyperSync.res +++ b/codegenerator/cli/templates/static/codegen/src/eventFetching/hypersync/HyperSync.res @@ -181,7 +181,16 @@ module LogsQuery = { ~fieldSelection, ) - let executeQuery = () => client.getEvents(~query) + let executeQuery = async () => { + let res = await client.getEvents(~query) + if res.nextBlock <= fromBlock { + // Might happen when /height response was from another instance of HyperSync + Js.Exn.raiseError( + "Received page response from another instance of HyperSync. Should work after a retry.", + ) + } + res + } let res = await executeQuery->Time.retryAsyncWithExponentialBackOff(~logger=Some(logger)) @@ -305,10 +314,11 @@ module BlockData = { switch maybeSuccessfulRes { | None => { let logger = Logging.createChild(~params={"url": serverUrl}) - logger->Logging.childWarn( - `Block #${blockNumber->Int.toString} not found in hypersync. HyperSync runs multiple instances of hypersync and it is possible that they drift independently slightly from the head. Retrying query in 100ms.`, + let delayMilliseconds = 100 + logger->Logging.childInfo( + `Block #${blockNumber->Int.toString} not found in HyperSync. HyperSync has multiple instances and it's possible that they drift independently slightly from the head. Indexing should continue correctly after retrying the query in ${delayMilliseconds->Int.toString}ms.`, ) - await Time.resolvePromiseAfterDelay(~delayMilliseconds=100) + await Time.resolvePromiseAfterDelay(~delayMilliseconds) await queryBlockData(~serverUrl, ~blockNumber, ~logger) } | Some(res) => res->convertResponse->Result.map(res => res->Array.get(0))