diff --git a/.changeset/pink-fans-nail.md b/.changeset/pink-fans-nail.md new file mode 100644 index 0000000000..4c84c50347 --- /dev/null +++ b/.changeset/pink-fans-nail.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/store-sync": patch +--- + +add retry attempts and more logging to `waitForTransaction` diff --git a/packages/store-sync/package.json b/packages/store-sync/package.json index c03eb0e7d5..4c987235c2 100644 --- a/packages/store-sync/package.json +++ b/packages/store-sync/package.json @@ -54,6 +54,7 @@ "debug": "^4.3.4", "drizzle-orm": "^0.27.0", "kysely": "^0.26.1", + "p-retry": "^5.1.2", "rxjs": "7.5.5", "sql.js": "^1.8.0", "superjson": "^1.12.4", diff --git a/packages/store-sync/src/createStoreSync.ts b/packages/store-sync/src/createStoreSync.ts index d0bdcfb301..97480a68d0 100644 --- a/packages/store-sync/src/createStoreSync.ts +++ b/packages/store-sync/src/createStoreSync.ts @@ -3,6 +3,7 @@ import { Hex, TransactionReceipt } from "viem"; import { SetRecordOperation, SyncOptions, SyncResult } from "./common"; import { createBlockStream, blockRangeToLogs, groupLogsByBlockNumber } from "@latticexyz/block-logs-stream"; import { filter, map, tap, mergeMap, from, concatMap, share, firstValueFrom } from "rxjs"; +import pRetry from "p-retry"; import { blockLogsToStorage } from "./blockLogsToStorage"; import { debug as parentDebug } from "./debug"; import { createIndexerClient } from "./trpc-indexer"; @@ -148,17 +149,28 @@ export async function createStoreSync async function waitForTransaction(tx: Hex): Promise<{ receipt: TransactionReceipt; }> { - // Wait for tx to be mined - const receipt = await publicClient.waitForTransactionReceipt({ hash: tx }); + // viem doesn't retry timeouts, so we'll wrap in a retry + const receipt = await pRetry( + (attempt) => { + // Wait for tx to be mined + debug("waiting for tx receipt", tx, "attempt", attempt); + return publicClient.waitForTransactionReceipt({ + hash: tx, + timeout: publicClient.pollingInterval * 2 * attempt, + }); + }, + { retries: 3 } + ); + debug("got tx receipt", tx, receipt); // If we haven't processed a block yet or we haven't processed the block for the tx, wait for it if (lastBlockNumberProcessed == null || lastBlockNumberProcessed < receipt.blockNumber) { + debug("waiting for tx block to be processed", tx, receipt.blockNumber); await firstValueFrom( - blockStorageOperations$.pipe( - filter(({ blockNumber }) => blockNumber != null && blockNumber >= receipt.blockNumber) - ) + blockStorageOperations$.pipe(filter(({ blockNumber }) => blockNumber >= receipt.blockNumber)) ); } + debug("tx block was processed", tx, receipt.blockNumber); return { receipt }; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e637d4ddd5..79b04639c8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1075,6 +1075,9 @@ importers: kysely: specifier: ^0.26.1 version: 0.26.1 + p-retry: + specifier: ^5.1.2 + version: 5.1.2 rxjs: specifier: 7.5.5 version: 7.5.5