Skip to content

Commit

Permalink
Retry on wrong hypersync instance response
Browse files Browse the repository at this point in the history
  • Loading branch information
DZakh committed Dec 17, 2024
1 parent 4133be6 commit 1b78955
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 11 deletions.
4 changes: 2 additions & 2 deletions codegenerator/cli/templates/static/codegen/src/Time.res
Original file line number Diff line number Diff line change
@@ -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<Pino.t>=None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -109,7 +109,7 @@ module LogsQuery = {
Amount,
ToAddress,
AssetId,
To
To,
],
block: [Id, Height, Time],
},
Expand Down Expand Up @@ -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 HyperSync. Should work after a retry.",
)
}
res
}

let res = await executeQuery->Time.retryAsyncWithExponentialBackOff(~logger=Some(logger))

Expand Down Expand Up @@ -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})
let delayMilliseconds = 100
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.`,
`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)
} else {
res->convertResponse
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down Expand Up @@ -305,10 +314,11 @@ module BlockData = {
switch maybeSuccessfulRes {
| None => {
let logger = Logging.createChild(~params={"url": serverUrl})
let delayMilliseconds = 100
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.`,
`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))
Expand Down

0 comments on commit 1b78955

Please sign in to comment.