From 2c21ffab0339675e4577017f06ee01dd3852a4fc Mon Sep 17 00:00:00 2001 From: kyscott18 <43524469+kyscott18@users.noreply.github.com> Date: Fri, 16 Aug 2024 17:53:35 -0400 Subject: [PATCH] fix cached from block (#1042) * fix cached from block * cleanup * chore: changeset * Update silver-lamps-tan.md --------- Co-authored-by: typedarray <90073088+0xOlias@users.noreply.github.com> --- .changeset/silver-lamps-tan.md | 5 +++++ packages/core/src/sync-historical/index.ts | 18 ++++++++++++++---- packages/core/src/utils/interval.test.ts | 21 +++++++++++++++++++++ packages/core/src/utils/interval.ts | 4 ++++ 4 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 .changeset/silver-lamps-tan.md diff --git a/.changeset/silver-lamps-tan.md b/.changeset/silver-lamps-tan.md new file mode 100644 index 000000000..5f845c0bd --- /dev/null +++ b/.changeset/silver-lamps-tan.md @@ -0,0 +1,5 @@ +--- +"@ponder/core": patch +--- + +Fixed a regression introduced in `0.5.9` that sometimes caused events to be skipped during indexing if any `startBlock` was set earlier than in a previous indexing run. This issue did not affect the database integrity, but affected apps should restart to ensure all events are indexed. diff --git a/packages/core/src/sync-historical/index.ts b/packages/core/src/sync-historical/index.ts index 05f5e1b56..556df5d76 100644 --- a/packages/core/src/sync-historical/index.ts +++ b/packages/core/src/sync-historical/index.ts @@ -20,6 +20,7 @@ import { intervalDifference, intervalIntersection, intervalSum, + sortIntervals, } from "@/utils/interval.js"; import { never } from "@/utils/never.js"; import type { RequestQueue } from "@/utils/requestQueue.js"; @@ -89,12 +90,21 @@ export const createHistoricalSync = async ( * some progress. */ const _latestCompletedBlocks = args.sources.map(({ filter }) => { - const completedIntervals = intervalIntersection( - [[filter.fromBlock, filter.toBlock ?? Number.POSITIVE_INFINITY]], - intervalsCache.get(filter)!, + const requiredInterval = [ + filter.fromBlock, + filter.toBlock ?? Number.POSITIVE_INFINITY, + ] satisfies Interval; + const cachedIntervals = intervalsCache.get(filter)!; + + const completedIntervals = sortIntervals( + intervalIntersection([requiredInterval], cachedIntervals), ); + if (completedIntervals.length === 0) return undefined; - return completedIntervals[0]![1]; + + const earliestCompletedInterval = completedIntervals[0]!; + if (earliestCompletedInterval[0] !== filter.fromBlock) return undefined; + return earliestCompletedInterval[1]; }); if (_latestCompletedBlocks.every((block) => block !== undefined)) { diff --git a/packages/core/src/utils/interval.test.ts b/packages/core/src/utils/interval.test.ts index 1f737228c..3d7497efe 100644 --- a/packages/core/src/utils/interval.test.ts +++ b/packages/core/src/utils/interval.test.ts @@ -4,6 +4,7 @@ import { intervalIntersection, intervalSum, intervalUnion, + sortIntervals, } from "./interval.js"; test("intervalSum handles empty input", () => { @@ -194,3 +195,23 @@ test("intervalDifference does not mutate inputs", () => { expect(initial).toStrictEqual([6, 17]); }); + +test("sortIntervals", () => { + let result = sortIntervals([ + [1, 5], + [4, 7], + ]); + expect(result).toStrictEqual([ + [1, 5], + [4, 7], + ]); + + result = sortIntervals([ + [4, 7], + [1, 5], + ]); + expect(result).toStrictEqual([ + [1, 5], + [4, 7], + ]); +}); diff --git a/packages/core/src/utils/interval.ts b/packages/core/src/utils/interval.ts index 46c727864..6c409007f 100644 --- a/packages/core/src/utils/interval.ts +++ b/packages/core/src/utils/interval.ts @@ -164,6 +164,10 @@ export function intervalDifference( return result; } +export function sortIntervals(intervals: Interval[]) { + return intervals.sort((a, b) => (a[0] < b[0] ? -1 : 1)); +} + export function getChunks({ interval, maxChunkSize,