diff --git a/packages/node-core/src/api.service.ts b/packages/node-core/src/api.service.ts index 208acbbd5d..5d938ccce6 100644 --- a/packages/node-core/src/api.service.ts +++ b/packages/node-core/src/api.service.ts @@ -43,18 +43,30 @@ export abstract class ApiService = any[] private timeouts: Record = {}; async fetchBlocks(heights: number[], numAttempts = MAX_RECONNECT_ATTEMPTS): Promise { + return this.retryFetch(async () => { + // Get the latest fetch function from the provider + const apiInstance = this.connectionPoolService.api; + return apiInstance.fetchBlocks(heights); + }, numAttempts); + } + + protected async retryFetch(fn: () => Promise, numAttempts = MAX_RECONNECT_ATTEMPTS): Promise { let reconnectAttempts = 0; + let lastError: Error | null = null; while (reconnectAttempts < numAttempts) { try { - // Get the latest fetch function from the provider - const apiInstance = this.connectionPoolService.api; - return await apiInstance.fetchBlocks(heights); + return await fn(); } catch (e: any) { - logger.error(e, `Failed to fetch blocks ${heights[0]}...${heights[heights.length - 1]}`); - + lastError = e; reconnectAttempts++; } } + if (lastError !== null) { + logger.error( + `Maximum number of retries (${numAttempts}) reached. See the following error for the underlying reason.` + ); + throw lastError; + } throw new Error(`Maximum number of retries (${numAttempts}) reached.`); } diff --git a/packages/node-core/src/indexer/blockDispatcher/block-dispatcher.ts b/packages/node-core/src/indexer/blockDispatcher/block-dispatcher.ts index a2d870d43c..8ebe3dc331 100644 --- a/packages/node-core/src/indexer/blockDispatcher/block-dispatcher.ts +++ b/packages/node-core/src/indexer/blockDispatcher/block-dispatcher.ts @@ -206,7 +206,7 @@ export abstract class BlockDispatcher // Do nothing, fetching the block was flushed, this could be caused by forked blocks or dynamic datasources return; } - logger.warn(e, 'Failed to enqueue fetched block to process'); + logger.error(e, 'Failed to enqueue fetched block to process'); process.exit(1); }); diff --git a/packages/node/src/indexer/api.service.ts b/packages/node/src/indexer/api.service.ts index 524e38e0d8..16b647a59d 100644 --- a/packages/node/src/indexer/api.service.ts +++ b/packages/node/src/indexer/api.service.ts @@ -263,27 +263,16 @@ export class ApiService return `api.rpc.${ext?.section ?? '*'}.${ext?.method ?? '*'}`; } + // Overrides the super function because of the specVer async fetchBlocks( heights: number[], overallSpecVer?: number, numAttempts = MAX_RECONNECT_ATTEMPTS, ): Promise { - let reconnectAttempts = 0; - while (reconnectAttempts < numAttempts) { - try { - const apiInstance = this.connectionPoolService.api; - return await apiInstance.fetchBlocks(heights, overallSpecVer); - } catch (e: any) { - logger.error( - e, - `Failed to fetch blocks ${heights[0]}...${ - heights[heights.length - 1] - }`, - ); - - reconnectAttempts++; - } - } - throw new Error(`Maximum number of retries (${numAttempts}) reached.`); + return this.retryFetch(async () => { + // Get the latest fetch function from the provider + const apiInstance = this.connectionPoolService.api; + return apiInstance.fetchBlocks(heights, overallSpecVer); + }, numAttempts); } }