Skip to content

Commit

Permalink
feat(store-sync,store-indexer): add followBlockTag option (#2315)
Browse files Browse the repository at this point in the history
  • Loading branch information
holic committed Feb 27, 2024
1 parent 3be4dee commit 3622e39
Show file tree
Hide file tree
Showing 8 changed files with 20 additions and 2 deletions.
8 changes: 8 additions & 0 deletions .changeset/brave-ghosts-walk.md
@@ -0,0 +1,8 @@
---
"@latticexyz/store-indexer": minor
"@latticexyz/store-sync": minor
---

Added a `followBlockTag` option to configure which block number to follow when running `createStoreSync`. It defaults to `latest` (current behavior), which is recommended for individual clients so that you always have the latest chain state.

Indexers now default to `safe` to avoid issues with reorgs and load-balanced RPCs being out of sync. This means indexers will be slightly behind the latest block number, but clients can quickly catch up. Indexers can override this setting using `FOLLOW_BLOCK_TAG` environment variable.
1 change: 1 addition & 0 deletions e2e/packages/sync-test/setup/startIndexer.ts
Expand Up @@ -37,6 +37,7 @@ export async function startIndexer(opts: StartIndexerOptions) {
RPC_HTTP_URL: opts.rpcHttpUrl,
SQLITE_FILENAME: opts.indexer === "sqlite" ? opts.sqliteFilename : undefined,
DATABASE_URL: opts.indexer === "postgres" ? opts.databaseUrl : undefined,
FOLLOW_BLOCK_TAG: "latest",
};
console.log(chalk.magenta("[indexer]:"), "starting indexer", env);

Expand Down
1 change: 1 addition & 0 deletions packages/store-indexer/bin/parseEnv.ts
Expand Up @@ -8,6 +8,7 @@ export const frontendEnvSchema = z.object({

export const indexerEnvSchema = z.intersection(
z.object({
FOLLOW_BLOCK_TAG: z.enum(["latest", "safe", "finalized"]).default("safe"),
START_BLOCK: z.coerce.bigint().nonnegative().default(0n),
MAX_BLOCK_RANGE: z.coerce.bigint().positive().default(1000n),
POLLING_INTERVAL: z.coerce.number().positive().default(1000),
Expand Down
1 change: 1 addition & 0 deletions packages/store-indexer/bin/postgres-decoded-indexer.ts
Expand Up @@ -69,6 +69,7 @@ try {
const { latestBlockNumber$, storedBlockLogs$ } = await createStoreSync({
storageAdapter,
publicClient,
followBlockTag: env.FOLLOW_BLOCK_TAG,
startBlock,
maxBlockRange: env.MAX_BLOCK_RANGE,
address: env.STORE_ADDRESS,
Expand Down
1 change: 1 addition & 0 deletions packages/store-indexer/bin/postgres-indexer.ts
Expand Up @@ -70,6 +70,7 @@ try {
const { latestBlockNumber$, storedBlockLogs$ } = await createStoreSync({
storageAdapter,
publicClient,
followBlockTag: env.FOLLOW_BLOCK_TAG,
startBlock,
maxBlockRange: env.MAX_BLOCK_RANGE,
address: env.STORE_ADDRESS,
Expand Down
1 change: 1 addition & 0 deletions packages/store-indexer/bin/sqlite-indexer.ts
Expand Up @@ -75,6 +75,7 @@ try {
const { latestBlockNumber$, storedBlockLogs$ } = await syncToSqlite({
database,
publicClient,
followBlockTag: env.FOLLOW_BLOCK_TAG,
startBlock,
maxBlockRange: env.MAX_BLOCK_RANGE,
address: env.STORE_ADDRESS,
Expand Down
4 changes: 4 additions & 0 deletions packages/store-sync/src/common.ts
Expand Up @@ -77,6 +77,10 @@ export type SyncOptions<TConfig extends StoreConfig = StoreConfig> = {
* @deprecated Use `filters` option instead.
* */
tableIds?: Hex[];
/**
* Optional block tag to follow for the latest block number. Defaults to `latest`. It's recommended to use `safe` for indexers.
*/
followBlockTag?: "latest" | "safe" | "finalized";
/**
* Optional block number to start indexing from. Useful for resuming the indexer from a particular point in time or starting after a particular contract deployment.
*/
Expand Down
5 changes: 3 additions & 2 deletions packages/store-sync/src/createStoreSync.ts
Expand Up @@ -55,6 +55,7 @@ export async function createStoreSync<TConfig extends StoreConfig = StoreConfig>
address,
filters: initialFilters = [],
tableIds = [],
followBlockTag = "latest",
startBlock: initialStartBlock = 0n,
maxBlockRange,
initialState,
Expand Down Expand Up @@ -176,11 +177,11 @@ export async function createStoreSync<TConfig extends StoreConfig = StoreConfig>
tap((startBlock) => debug("starting sync from block", startBlock))
);

const latestBlock$ = createBlockStream({ publicClient, blockTag: "latest" }).pipe(shareReplay(1));
const latestBlock$ = createBlockStream({ publicClient, blockTag: followBlockTag }).pipe(shareReplay(1));
const latestBlockNumber$ = latestBlock$.pipe(
map((block) => block.number),
tap((blockNumber) => {
debug("latest block number", blockNumber);
debug("on block number", blockNumber, "for", followBlockTag, "block tag");
}),
shareReplay(1)
);
Expand Down

0 comments on commit 3622e39

Please sign in to comment.