Skip to content

ENSDb Writer Worker for ENSIndexer#1702

Merged
tk-o merged 25 commits intomainfrom
feat/ensdb-writer-worker-for-ensindexer
Mar 3, 2026
Merged

ENSDb Writer Worker for ENSIndexer#1702
tk-o merged 25 commits intomainfrom
feat/ensdb-writer-worker-for-ensindexer

Conversation

@tk-o
Copy link
Contributor

@tk-o tk-o commented Mar 1, 2026

Lite PR

Tip: Review docs on the ENSNode PR process

Summary

  • Implemented EnsDbClient class for ENSIndexer (includes queries and mutations).
  • Implemented EnsDbWriterWorker to handle tasks of writing ENSNode metadata into ENSDb
    • Task 1: write ENSDb client version
    • Task 2: write ENSIndexer Public Config
    • Task 3 (recurring): write Indexing Status snapshot
  • startEnsDbWriterWorker function creates a singleton instance for EnsDbWriterWorker and sets up error handling.

Why

  • We need to decouple ENSIndexer and ENSApi, so that we need an integration point. This integration point is going to be ENSDb, and it needs all required data up-to-date.

Testing

  • Ran static code checks (lint, typechecks), and testing suite.
  • Ran local instance of ENSIndexer and confirmed it writes ENSNode Metadata correctly into ENSDb.
ENSIndexer logs demo
14:41:34.474 INFO  Created HTTP server port=42069 (4ms)
14:41:34.474 INFO  Started returning 200 responses endpoint=/health
[EnsDbWriterWorker]: Upserting ENSDb version into ENSDb...
[EnsDbWriterWorker]: ENSDb version upserted successfully: 1.5.1
[EnsDbWriterWorker]: Upserting ENSIndexer Public Config into ENSDb...
[EnsDbWriterWorker]: ENSIndexer Public Config upserted successfully
[EnsDbWriterWorker]: Error retrieving or validating Indexing Status Snapshot: Error: Invalid serialized Ponder Indexing Metrics: ✖ At least one 'ponder_sync_block' metric must include a 'chain' label.
✖ At least one 'ponder_sync_block_timestamp' metric must include a 'chain' label.
✖ At least one 'ponder_historical_total_blocks' metric must include a 'chain' label.
    at Module.deserializePonderIndexingMetrics (/Users/tko/dev/github/namehash/ensnode/packages/ponder-sdk/src/deserialize/indexing-metrics.ts:296:11)
    at LocalPonderClient.metrics (/Users/tko/dev/github/namehash/ensnode/packages/ponder-sdk/src/client.ts:48:12)
    at processTicksAndRejections (node:internal/process/task_queues:103:5)
    at LocalPonderClient.metrics (/Users/tko/dev/github/namehash/ensnode/packages/ponder-sdk/src/local-ponder-client.ts:154:21)
    at async Promise.all (index 0)
    at IndexingStatusBuilder.getOmnichainIndexingStatusSnapshot (/Users/tko/dev/github/namehash/ensnode/apps/ensindexer/src/lib/indexing-status-builder/indexing-status-builder.ts:49:61)
    at EnsDbWriterWorker.getIndexingStatusSnapshotStream (/Users/tko/dev/github/namehash/ensnode/apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.ts:233:11)
    at EnsDbWriterWorker.run (/Users/tko/dev/github/namehash/ensnode/apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.ts:96:22)
    at EnsDbWriterWorker.runWithRetries (/Users/tko/dev/github/namehash/ensnode/apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.ts:119:9)
14:41:34.719 INFO  Started backfill indexing chain=84532 block_range=[13012458,38345272]
14:41:34.720 INFO  Started backfill indexing chain=11155111 block_range=[3702721,10368807]
14:41:34.720 INFO  Started backfill indexing chain=59141 block_range=[2395094,25953939]
14:41:34.721 INFO  Started fetching backfill JSON-RPC data chain=84532 cached_block=38345249 cache_rate=100%
14:41:34.721 INFO  Started fetching backfill JSON-RPC data chain=11155111 cached_block=10368804 cache_rate=100%
14:41:34.721 INFO  Started fetching backfill JSON-RPC data chain=59141 cached_block=25953913 cache_rate=100%
14:41:35.214 INFO  Finished fetching backfill JSON-RPC data chain=84532 (494ms)
14:41:35.327 INFO  Finished fetching backfill JSON-RPC data chain=59141 (606ms)
14:41:35.826 INFO  Indexed block range chain=11155111 event_count=2995 block_range=[3702721,4177830] (846ms)
14:41:36.052 INFO  Finished fetching backfill JSON-RPC data chain=11155111 (1s)
14:41:36.564 INFO  Indexed block range chain=11155111 event_count=2995 block_range=[4177831,4325397] (736ms)
14:41:37.005 INFO  Indexed block range chain=11155111 event_count=3005 block_range=[4325398,4447290] (439ms)
14:41:37.408 INFO  Indexed block range chain=11155111 event_count=2997 block_range=[4447291,4603398] (402ms)
14:41:38.077 INFO  Indexed block range chain=11155111 event_count=3005 block_range=[4603399,4646580] (668ms)
14:41:38.557 INFO  Indexed block range chain=11155111 event_count=3002 block_range=[4646581,4805136] (478ms)
14:41:39.293 INFO  Indexed block range chain=11155111 event_count=3001 block_range=[4805137,4831114] (735ms)
14:41:39.719 INFO  Updated backfill indexing progress progress=17.5%
[EnsDbWriterWorker]: Upserting Indexing Status Snapshot into ENSDb...
[EnsDbWriterWorker]: Indexing Status Snapshot upserted successfully
14:41:40.104 INFO  Indexed block range chain=11155111 event_count=3003 block_range=[4831115,4836708] (809ms)
14:41:40.919 INFO  Indexed block range chain=11155111 event_count=2997 block_range=[4836709,4845690] (813ms)

Notes for Reviewer (Optional)

  • Review commit-by-commit is highly encouraged.
  • There's a plan for implementing a read-only client (see EnsDbClientQuery interface) from ENSDb that will be available via a new package so our customers could use it in their backend workloads. That update is out of scope for this PR, but when it's live, the apps/ensindexer/src/lib/ensdb-client/ensdb-client.ts implementation could simply extend the "read-only" client and only add the mutation methods (see EnsDbClientMutation interface).

Pre-Review Checklist (Blocking)

  • This PR does not introduce significant changes and is low-risk to review quickly.
    • PR updates have been carefully sliced into separate commits to make the PR review process more straightforward.
  • Relevant changesets are included (or are not required)

Resolves #1252

Copilot AI review requested due to automatic review settings March 1, 2026 17:59
@changeset-bot
Copy link

changeset-bot bot commented Mar 1, 2026

🦋 Changeset detected

Latest commit: f608c31

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 18 packages
Name Type
ensindexer Major
ensadmin Major
ensrainbow Major
ensapi Major
fallback-ensapi Major
@ensnode/datasources Major
@ensnode/ensrainbow-sdk Major
@ensnode/ensnode-schema Major
@ensnode/ensnode-react Major
@ensnode/ensnode-sdk Major
@ensnode/ponder-sdk Major
@ensnode/ponder-subgraph Major
@ensnode/shared-configs Major
@docs/ensnode Major
@docs/ensrainbow Major
@docs/mintlify Major
@namehash/ens-referrals Major
@namehash/namehash-ui Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Contributor

vercel bot commented Mar 1, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

3 Skipped Deployments
Project Deployment Actions Updated (UTC)
admin.ensnode.io Skipped Skipped Mar 3, 2026 4:31pm
ensnode.io Skipped Skipped Mar 3, 2026 4:31pm
ensrainbow.io Skipped Skipped Mar 3, 2026 4:31pm

@tk-o
Copy link
Contributor Author

tk-o commented Mar 1, 2026

@greptile review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 1, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds ENSDb persistence and a background writer: Drizzle factory, ENSDb client and singleton, writer worker + starter singleton, indexer/indexing-status singletons, tests/mocks, package dependency additions, and updates the API handler to use singletons and start the writer.

Changes

Cohort / File(s) Summary
Dependencies
apps/ensindexer/package.json
Added @ponder/client, drizzle-orm to dependencies and @types/pg to devDependencies.
Drizzle factory
apps/ensindexer/src/lib/ensdb-client/drizzle.ts
New makeDrizzle factory: configures Drizzle ORM with provided schema, DB URL, DB schema name, and snake_case casing.
ENSDb client implementation
apps/ensindexer/src/lib/ensdb-client/ensdb-client.ts, apps/ensindexer/src/lib/ensdb-client/singleton.ts
Added exported EnsDbClient class (read/upsert, serialize/deserialize, single-record enforcement) and singleton ensDbClient.
ENSDb tests & mocks
apps/ensindexer/src/lib/ensdb-client/ensdb-client.mock.ts, apps/ensindexer/src/lib/ensdb-client/ensdb-client.test.ts
New strongly-typed mock data and comprehensive unit tests covering get/upsert behaviors and edge cases.
ENSDb writer worker & tests
apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.ts, .../ensdb-writer-worker.test.ts, .../singleton.ts
New EnsDbWriterWorker (run, runWithRetries, stop, streaming/upsert, validation) plus startEnsDbWriterWorker() singleton that manages lifecycle and signal handlers; tests for normal, retry, and failure scenarios.
Indexer & builder singletons
apps/ensindexer/src/lib/ensindexer-client/singleton.ts, apps/ensindexer/src/lib/indexing-status-builder/singleton.ts
New singletons: ensIndexerClient and indexingStatusBuilder (wired to local Ponder client).
API handler change
apps/ensindexer/ponder/src/api/handlers/ensnode-api.ts
Replaced local IndexingStatusBuilder/local Ponder client instantiation with indexingStatusBuilder singleton import and invokes startEnsDbWriterWorker() at module initialization.

Sequence Diagram

sequenceDiagram
    participant API as "ensnode-api"
    participant Worker as "EnsDbWriterWorker (singleton)"
    participant Indexer as "IndexingStatusBuilder / EnsIndexerClient"
    participant Client as "EnsDbClient"
    participant DB as "PostgreSQL"

    API->>Worker: startEnsDbWriterWorker()

    rect rgba(100,150,255,0.5)
    Note over Worker,Indexer: initial validation & config fetch
    Worker->>Indexer: getValidatedEnsIndexerPublicConfig()
    Indexer->>Client: request stored config
    Client->>DB: SELECT metadata by key
    DB-->>Client: stored config or none
    Client-->>Worker: config (or undefined)
    end

    rect rgba(100,150,255,0.5)
    Note over Worker: initial upserts
    Worker->>Client: upsertEnsDbVersion()
    Client->>DB: upsert version metadata
    Worker->>Client: upsertEnsIndexerPublicConfig()
    Client->>DB: upsert config metadata
    end

    rect rgba(150,200,100,0.5)
    Note over Worker: streaming snapshots
    loop every interval
      Worker->>Indexer: buildIndexingStatusSnapshot()
      Indexer-->>Worker: snapshot
      Worker->>Client: upsertIndexingStatusSnapshot()
      Client->>DB: upsert serialized snapshot
      DB-->>Client: OK
    end
    end

    alt Worker stops normally
      Worker-->>API: stopped
    else Unrecoverable error / retries exhausted
      Worker-->>API: error -> process abort
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I stitched a schema by moonlit code,

Snapshots hop in on a steady road.
Singletons hum, a worker keeps pace,
Retries and tests tidy every place—
A rabbit saves bytes with a proud little bounce.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR implements key ENSIndexer-side objectives from issue #1252: EnsDbClient with queries/mutations, EnsDbWriterWorker for writing metadata (version, config, snapshots), and periodic snapshot upserting with error handling and retry logic.
Out of Scope Changes check ✅ Passed All changes align with issue #1252 ENSIndexer objectives: EnsDbClient, EnsDbWriterWorker, dependency management (drizzle-orm, @ponder/client), singleton modules, and handler integration are all required for ENSIndexer to push metadata to ENSDb.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The pull request title 'ENSDb Writer Worker for ENSIndexer' clearly and specifically summarizes the main change in the changeset.
Description check ✅ Passed The PR description is well-structured, follows the template, and provides clear summary, rationale, testing details, and reviewer notes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/ensdb-writer-worker-for-ensindexer

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces an ENSDb “writer worker” in ENSIndexer to persist ENSIndexer metadata into ENSDb, and updates the ensnode-sdk ENSDb client interface naming to be explicitly ENSIndexer-scoped.

Changes:

  • Add EnsDbClient (Drizzle-based) for reading/writing ENSNode metadata records in ENSDb, plus unit tests/mocks.
  • Add EnsDbWriterWorker that upserts ENSDb version + ENSIndexer public config once, then periodically upserts indexing status snapshots (with retries), plus unit tests.
  • Wire the worker + new singletons into ENSIndexer’s Hono API handler; add required deps (drizzle-orm, @ponder/client, @types/pg).

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
pnpm-lock.yaml Adds/threads @types/pg through relevant dependency snapshots.
packages/ensnode-sdk/src/ensdb/client.ts Renames ENSDb client query/mutation methods to ENSIndexer-specific names.
apps/ensindexer/src/lib/indexing-status-builder/singleton.ts Introduces singleton instance for IndexingStatusBuilder.
apps/ensindexer/src/lib/ensindexer-client/singleton.ts Introduces singleton EnsIndexerClient configured via app config.
apps/ensindexer/src/lib/ensdb-writer-worker/singleton.ts Creates a singleton EnsDbWriterWorker wired with required dependencies.
apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.ts Implements the worker loop, validation, and retry behavior.
apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.test.ts Adds unit tests for worker behavior (currently has signature mismatches).
apps/ensindexer/src/lib/ensdb-client/singleton.ts Adds singleton EnsDbClient for ENSIndexer.
apps/ensindexer/src/lib/ensdb-client/ensdb-client.ts Implements ENSDb client queries/mutations for ENSNode metadata.
apps/ensindexer/src/lib/ensdb-client/ensdb-client.test.ts Adds unit tests for ENSDb client behavior.
apps/ensindexer/src/lib/ensdb-client/ensdb-client.mock.ts Adds fixtures for ENSDb client tests (public config, serialized snapshot).
apps/ensindexer/src/lib/ensdb-client/drizzle.ts Adds makeDrizzle helper (adapted from ENSApi).
apps/ensindexer/ponder/src/api/handlers/ensnode-api.ts Starts the writer worker on module load and swaps in singleton builder usage.
apps/ensindexer/package.json Adds needed runtime/dev deps for Drizzle and pg typings.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/ensindexer/package.json`:
- Line 49: Update the dependency entry for "@types/pg" in package.json to use
the workspace catalog reference (matching how "@types/node" is declared) instead
of the hardcoded "8.16.0"; if "@types/pg" is not yet listed in the pnpm
workspace catalog, add it there with the desired version and then change the
package.json entry to "catalog:`@types/pg`" (or the exact catalog key used in your
monorepo) so the monorepo versioning pattern remains consistent.

In `@apps/ensindexer/ponder/src/api/handlers/ensnode-api.ts`:
- Around line 24-32: Replace the current un-awaited promise handling for
ensDbWriterWorker.runWithRetries so it doesn't create an unhandled rejection:
either move the call into a ponder.on("setup", ...) handler and await
ensDbWriterWorker.runWithRetries({ maxRetries: 3 }) so failures can be thrown to
fail setup, or keep it fire-and-forget but mark failure deterministically by
using void ensDbWriterWorker.runWithRetries(...).catch(...) and inside the catch
call ensDbWriterWorker.stop(), log the error and set process.exitCode = 1;
update the code around ensDbWriterWorker.runWithRetries and related stop/logging
accordingly.

In `@apps/ensindexer/src/lib/ensdb-client/ensdb-client.ts`:
- Around line 131-136: Remove the redundant `@returns` JSDoc tag from the JSDoc
block that begins "Get ENSNode metadata record" in ensdb-client.ts (the doc for
the ENS node metadata retrieval method); keep the summary and other tags such as
`@throws` but delete the `@returns` line so the comment no longer restates the
method summary.

In `@apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.test.ts`:
- Line 242: The call to worker.runWithRetries currently passes a numeric
argument but the method signature expects an options object; change the
invocation of runWithRetries on the worker instance to pass an object like {
maxRetries: 2 } (mirror the same fix you applied at the earlier call near line
210) so the call matches the runWithRetries({ maxRetries: number }) signature.
- Line 210: The test calls worker.runWithRetries(2) but runWithRetries expects
an object parameter; change the call to pass an object like
worker.runWithRetries({ maxRetries: 2 }) (update the runPromise assignment and
any other test invocations of runWithRetries accordingly) so the signature for
runWithRetries and the worker variable usage match the expected { maxRetries:
number } shape.

In `@apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.ts`:
- Around line 158-160: Remove the redundant JSDoc `@returns` lines from the method
docblocks that describe returning the in-memory config object (the block that
currently says "In-memory config object, if the validation is successful or if
there is no stored config.") as well as the similar docblock around lines
204-207; keep the summary and `@throws` entries but delete the repetitive `@returns`
tags so the method documentation follows repo style.
- Around line 113-136: The retry loop in runWithRetries is unbounded because it
loops while (!this.isStopped) and only checks maxRetries after sleeping, which
can cause runaway timers; change the loop to explicitly bound retries (e.g.,
while (attempt < maxRetries && !this.isStopped)) or otherwise include an attempt
check in the loop condition so the delay on Line 130 cannot execute beyond
maxRetries; keep the existing behavior of throwing an Error with cause when
attempts are exhausted (the throw that references attempt and error should
remain inside the failure branch) and continue using
INDEXING_STATUS_RECORD_UPDATE_INTERVAL for the sleep duration.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a13e206 and c6ce77f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (13)
  • apps/ensindexer/package.json
  • apps/ensindexer/ponder/src/api/handlers/ensnode-api.ts
  • apps/ensindexer/src/lib/ensdb-client/drizzle.ts
  • apps/ensindexer/src/lib/ensdb-client/ensdb-client.mock.ts
  • apps/ensindexer/src/lib/ensdb-client/ensdb-client.test.ts
  • apps/ensindexer/src/lib/ensdb-client/ensdb-client.ts
  • apps/ensindexer/src/lib/ensdb-client/singleton.ts
  • apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.test.ts
  • apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.ts
  • apps/ensindexer/src/lib/ensdb-writer-worker/singleton.ts
  • apps/ensindexer/src/lib/ensindexer-client/singleton.ts
  • apps/ensindexer/src/lib/indexing-status-builder/singleton.ts
  • packages/ensnode-sdk/src/ensdb/client.ts

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 1, 2026

Greptile Summary

This PR introduces EnsDbClient and EnsDbWriterWorker to decouple ENSIndexer from ENSApi by writing ENSNode metadata (ENSDb version, ENSIndexer public config, and recurring indexing status snapshots) into a shared Postgres database (ENSDb) that both services can read.

Key changes:

  • EnsDbClient — thin Drizzle ORM wrapper over the ensnode_metadata table; supports upsert and get for ENSDb version, ENSIndexer public config, and indexing status snapshots.
  • EnsDbWriterWorker — orchestrates three tasks on startup (upsert version + config) and a 1-second setInterval for recurring snapshot writes; errors in the recurring task are caught and logged so the interval keeps running.
  • singleton.ts (worker) — provides startEnsDbWriterWorker() with a guard against double-initialization and a .catch() handler that sets process.exitCode = 1 and re-throws on fatal startup failures. The guard error message could be more accurate about the worker state.
  • Entrypointensdb-writer-worker-entrypoint.ts is imported as a side effect from ponder/src/api/index.ts, keeping it outside Ponder's indexer dependency graph as required.
  • Tests provide solid coverage for happy-path, config incompatibility, snapshot recovery, and interval management.

Two style observations remain: the guard error message in singleton.ts doesn't accurately reflect all possible states, and @types/pg uses a different dependency specification pattern than other @types packages in the project.

Confidence Score: 4/5

  • This PR is safe to merge with minor style clarifications applied.
  • The implementation is well-structured, follows existing patterns in the codebase, and is backed by a thorough test suite. The two remaining observations are both style-level: an inaccurate guard error message and a dependency specification inconsistency. No logic errors or security issues were found.
  • apps/ensindexer/src/lib/ensdb-writer-worker/singleton.ts and apps/ensindexer/package.json have style comments that should be addressed for clarity and consistency.

Last reviewed commit: 09d2b8e

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

18 files reviewed, 18 comments

Edit Code Review Agent Settings | Greptile

@tk-o tk-o force-pushed the feat/ensdb-writer-worker-for-ensindexer branch from c6ce77f to 328e5c1 Compare March 1, 2026 19:51
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io March 1, 2026 19:51 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io March 1, 2026 19:51 Inactive
@vercel vercel bot temporarily deployed to Preview – ensnode.io March 1, 2026 19:51 Inactive
@tk-o tk-o force-pushed the feat/ensdb-writer-worker-for-ensindexer branch from 328e5c1 to c39e3ea Compare March 1, 2026 19:52
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io March 1, 2026 19:53 Inactive
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io March 1, 2026 19:53 Inactive
@vercel vercel bot temporarily deployed to Preview – ensnode.io March 1, 2026 19:53 Inactive
@tk-o tk-o force-pushed the feat/ensdb-writer-worker-for-ensindexer branch from c39e3ea to eed564c Compare March 1, 2026 19:55
@vercel vercel bot temporarily deployed to Preview – ensnode.io March 1, 2026 19:55 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io March 1, 2026 19:55 Inactive
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io March 1, 2026 19:55 Inactive
ENSIndexer modules can import the singleton instance from `@/lib/ensdb-client`.
Copilot AI review requested due to automatic review settings March 1, 2026 19:57
@tk-o tk-o force-pushed the feat/ensdb-writer-worker-for-ensindexer branch from eed564c to 8208a39 Compare March 1, 2026 19:57
@tk-o
Copy link
Contributor Author

tk-o commented Mar 3, 2026

@greptile review

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@tk-o
Copy link
Contributor Author

tk-o commented Mar 3, 2026

@greptile review

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 6 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@tk-o
Copy link
Contributor Author

tk-o commented Mar 3, 2026

@greptile review

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 4 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@tk-o
Copy link
Contributor Author

tk-o commented Mar 3, 2026

@greptile review

@tk-o
Copy link
Contributor Author

tk-o commented Mar 3, 2026

@greptile review

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +229 to +268
it("calls pRetry for config fetch with retry logic", async () => {
// arrange - pRetry is mocked to call fn directly
const omnichainSnapshot = {
omnichainStatus: OmnichainIndexingStatusIds.Following,
omnichainIndexingCursor: 100,
chains: {},
} as OmnichainIndexingStatusSnapshot;

const snapshot = {
strategy: CrossChainIndexingStrategyIds.Omnichain,
slowestChainIndexingCursor: 100,
snapshotTime: 200,
omnichainSnapshot,
} as CrossChainIndexingStatusSnapshot;

vi.mocked(buildCrossChainIndexingStatusSnapshotOmnichain).mockReturnValue(snapshot);

const ensDbClient = {
getEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
upsertEnsDbVersion: vi.fn().mockResolvedValue(undefined),
upsertEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
upsertIndexingStatusSnapshot: vi.fn().mockResolvedValue(undefined),
} as unknown as EnsDbClient;

const ensIndexerClient = {
config: vi.fn().mockResolvedValue(publicConfig),
} as unknown as EnsIndexerClient;

const indexingStatusBuilder = {
getOmnichainIndexingStatusSnapshot: vi.fn().mockResolvedValue(omnichainSnapshot),
} as unknown as IndexingStatusBuilder;

const worker = new EnsDbWriterWorker(ensDbClient, ensIndexerClient, indexingStatusBuilder);

// act
await worker.run();

// assert - config should be called once (pRetry is mocked)
expect(ensIndexerClient.config).toHaveBeenCalledTimes(1);
expect(ensDbClient.upsertEnsIndexerPublicConfig).toHaveBeenCalledWith(publicConfig);
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test case "calls pRetry for config fetch with retry logic" doesn’t actually assert that pRetry was invoked or that the retry options were wired in; it only checks that ensIndexerClient.config ran once. To make this test meaningful, import pRetry in the test and assert it was called (and optionally that it received the expected retries/onFailedAttempt options).

Copilot uses AI. Check for mistakes.
Copy link
Member

@lightwalker-eth lightwalker-eth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tk-o Nice updates 😄 Shared a few small comments. Please take the lead to merge when ready 👍

@@ -0,0 +1,9 @@
// This file is the entry point for the ENSDb Writer Worker.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest to move all the ideas here (including this nice comment) into apps/ensindexer/ponder/src/api/index.ts

Goal: Not a fan of the import "./ensdb-writer-worker-entrypoint"; in that index.ts file because it's not so explicit what importing it does.

The call to startEnsDbWriterWorker can be in index.ts too which feels natural.

// wait for the configured delay before the next attempt.
await this.nextTryDelay();
}
console.log(`[EnsDbWriterWorker]: Upserting Indexing Status Snapshot into ENSDb...`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are running this task every second, perhaps best not to log this notices and instead only log error cases?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, will drop these log entires. I wish Ponder allowed using its logger so we could log our application stuff and re-use Ponder's log levels: ponder-sh/ponder#1727


resolve();
}, secondsToMilliseconds(INDEXING_STATUS_RECORD_UPDATE_INTERVAL));
// Invariant: the Omnichain Status must indicate that indexing has started already.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be great to document the why for this idea

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ENSApi: Persist ENSIndexerPublicConfig to the database

3 participants