Skip to content

Apply specific variant types for ChainIndexingMetrics#1612

Open
tk-o wants to merge 6 commits intomainfrom
refactor/ponder-sdk-indexing-metrics
Open

Apply specific variant types for ChainIndexingMetrics#1612
tk-o wants to merge 6 commits intomainfrom
refactor/ponder-sdk-indexing-metrics

Conversation

@tk-o
Copy link
Contributor

@tk-o tk-o commented Feb 6, 2026

Lite PR

Tip: Review docs on the ENSNode PR process

Summary

  • Ponder SDK improved data model.
    • All possible variants of ChainIndexingMetrics type have been collected as a discriminated union.
      • ChainIndexingMetricsQueued and ChainIndexingMetricBackfill both include backfillTotalBlocks field to support ENSIndexer use case where, at the ENSIndexer app start, all block refs must be fetched from RPC and cached for further use.
      • ChainIndexingMetricsRealtime includes latestKnownBlock field
      • ChainIndexingMetricsCompleted includes targetBlock field
    • PonderIndexingStatus now includes the checkpointBlock field for each indexed chain.

Why

  • More accurate data model allows learning the business logic details more easily.

Testing

  • Testing suite defined for Ponder SDK is happy with the updated data model (minor testing data tweaks were required to account for improved invariants logic).

Notes for Reviewer (Optional)

  • Anything non-obvious or worth a heads-up.

Pre-Review Checklist (Blocking)

  • This PR does not introduce significant changes and is low-risk to review quickly.
  • Relevant changesets are included (or are not required)

Copilot AI review requested due to automatic review settings February 6, 2026 13:59
@vercel
Copy link
Contributor

vercel bot commented Feb 6, 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 Feb 7, 2026 0:29am
ensnode.io Skipped Skipped Feb 7, 2026 0:29am
ensrainbow.io Skipped Skipped Feb 7, 2026 0:29am

@changeset-bot
Copy link

changeset-bot bot commented Feb 6, 2026

⚠️ No Changeset found

Latest commit: 47c2bed

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@coderabbitai
Copy link

coderabbitai bot commented Feb 6, 2026

Warning

Rate limit exceeded

@tk-o has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 17 minutes and 22 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

Convert chain indexing metrics to a discriminated-union model (Queued/Backfill/Realtime/Completed), refactor deserialization to build/validate per-chain variants, update mocks and a client test, add DeepPartial utility, and wrap per-chain checkpointBlock in a new ChainIndexingStatus object.

Changes

Cohort / File(s) Summary
Type Definitions
packages/ponder-sdk/src/indexing-metrics.ts
Replace monolithic ChainIndexingMetrics with discriminated union variants (Queued, Backfill, Realtime, Completed); add ChainIndexingMetricTypes discriminator, BackfillTotalBlocks type, and rename/replace fields (backfillSyncBlocksTotalbackfillTotalBlocks, latestKnownBlock, targetBlock).
Deserialization — indexing metrics
packages/ponder-sdk/src/deserialize/indexing-metrics.ts
Add buildUnvalidatedChainIndexingMetrics and refactor buildUnvalidatedPonderIndexingMetrics to assemble per-chain DeepPartial results; switch to unvalidated→validated flow; require ponder_historical_completed_indexing_seconds; remove prior global invariant preventing conflicting flags.
Mocks
packages/ponder-sdk/src/deserialize/indexing-metrics.mock.ts
Update mock chain entries to the new Realtime shape (type: ChainIndexingMetricTypes.Realtime, latestKnownBlock) with satisfies ChainIndexingMetricsRealtime assertions; add/adjust ponder_historical_completed_indexing_seconds gauge blocks across valid/invalid mocks.
Utilities
packages/ponder-sdk/src/deserialize/utils.ts
Add exported DeepPartial<T> utility type that recursively makes properties optional (handles arrays and nested objects).
Indexing status types
packages/ponder-sdk/src/indexing-status.ts
Add exported ChainIndexingStatus ({ checkpointBlock: BlockRef }) and change PonderIndexingStatus.chains from Map<ChainId, BlockRef> to Map<ChainId, ChainIndexingStatus>.
Deserialization — indexing status
packages/ponder-sdk/src/deserialize/indexing-status.ts
Change local map type and population to use ChainIndexingStatus (chains.set(chainData.id, { checkpointBlock: chainData.block })) and update imports to reflect new type usage.
Tests
packages/ponder-sdk/src/client.test.ts
Update expected error message in metrics() invalid-conflicting-metrics test to reference Prometheus metrics ponder_sync_is_complete and ponder_sync_is_realtime and that they cannot both be 1 for chain 10.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐇 I hopped through types, four states in a row,
Queued, Backfill, Realtime, Completed — watch me go,
I tucked checkpoints in boxes, made mocks sing with glee,
DeepPartial made things gentle, now schemas hop free,
Thump-thump — the rabbit celebrates with a tiny tea!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Apply specific variant types for ChainIndexingMetrics' directly and precisely summarizes the main change: refactoring ChainIndexingMetrics into a discriminated union of specific variant types.
Description check ✅ Passed The PR description follows the template structure with all major sections completed: Summary clearly explains the variant types and their fields, Why section justifies the change, Testing confirms suite passes, and Pre-Review Checklist is marked complete.

✏️ 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 refactor/ponder-sdk-indexing-metrics

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.

@tk-o tk-o marked this pull request as ready for review February 6, 2026 13:59
@tk-o tk-o requested a review from a team as a code owner February 6, 2026 13:59
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 6, 2026

Greptile Overview

Greptile Summary

  • Refactors ChainIndexingMetrics into a discriminated union (queued/backfill/realtime/completed) with variant-specific fields, and updates deserialization accordingly.
  • Adds a new required Prometheus metric (ponder_historical_completed_indexing_seconds) and strengthens invariants around per-chain sync flag conflicts.
  • Updates indexing status model to include per-chain checkpointBlock via a new ChainIndexingStatus wrapper.
  • Adjusts mocks/tests to reflect the new metrics invariants and new data model shapes.

Confidence Score: 4/5

  • This PR is close to mergeable but should address one deserialization invariant gap to avoid unclear failures on partial metric series.
  • The changes are mostly type/model refactors with updated tests. The main remaining concern is that required metrics are validated only by global presence, not per-chain series, so malformed Prometheus payloads can produce non-actionable Zod errors instead of targeted invariant messages.
  • packages/ponder-sdk/src/deserialize/indexing-metrics.ts

Important Files Changed

Filename Overview
packages/ponder-sdk/src/client.test.ts Updates expected error message for conflicting per-chain sync flags to match new invariant message.
packages/ponder-sdk/src/deserialize/indexing-metrics.mock.ts Extends Prometheus metrics mocks with ponder_historical_completed_indexing_seconds and updates expected deserialized ChainIndexingMetrics variants to the new discriminated union shape.
packages/ponder-sdk/src/deserialize/indexing-metrics.ts Refactors ChainIndexingMetrics deserialization to a discriminated union and adds new per-chain invariants; missing per-chain presence validation for several required metrics can lead to unclear runtime errors.
packages/ponder-sdk/src/deserialize/indexing-status.ts Adjusts status deserialization to wrap per-chain block ref into ChainIndexingStatus.checkpointBlock.
packages/ponder-sdk/src/deserialize/utils.ts Adds DeepPartial utility type used to build partially-validated metrics objects.
packages/ponder-sdk/src/indexing-metrics.ts Redefines ChainIndexingMetrics as a discriminated union with explicit variants (queued/backfill/realtime/completed) and renames/splits fields accordingly.
packages/ponder-sdk/src/indexing-status.ts Introduces ChainIndexingStatus type and updates PonderIndexingStatus.chains map values to include checkpointBlock.

Sequence Diagram

sequenceDiagram
  participant Consumer as SDK Consumer
  participant Client as PonderClient.metrics()
  participant Fetch as fetch(/metrics)
  participant DPM as deserializePrometheusMetrics
  participant Inv as invariant_includesRequiredMetrics
  participant Build as buildUnvalidatedPonderIndexingMetrics
  participant BuildChain as buildUnvalidatedChainIndexingMetrics
  participant Zod as schemaPonderIndexingMetrics

  Consumer->>Client: metrics()
  Client->>Fetch: HTTP GET /metrics
  Fetch-->>Client: Prometheus text
  Client->>DPM: parse text -> PrometheusMetrics
  DPM-->>Client: PrometheusMetrics
  Client->>Inv: validate required metric names
  loop for each chain in ponder_sync_block labels
    Inv->>Inv: validate per-chain seconds + flag conflict
  end
  Client->>Build: build {appSettings, chains}
  loop for each chain reference
    Build->>BuildChain: derive discriminated union variant
    BuildChain-->>Build: {type, ...fields}
  end
  Build-->>Client: DeepPartial<PonderIndexingMetrics>
  Client->>Zod: validate discriminated union + types
  Zod-->>Client: PonderIndexingMetrics
  Client-->>Consumer: resolved metrics
Loading

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.

5 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 6, 2026

Additional Comments (1)

packages/ponder-sdk/src/deserialize/indexing-metrics.ts
New required metric breaks

Adding ponder_historical_completed_indexing_seconds to requiredMetricNames makes deserialization fail against any Ponder /metrics output that doesn’t emit this series (e.g., older Ponder versions). If the SDK intends to remain compatible with previously-supported Ponder metric sets, this is a breaking change that will hard-fail PonderClient.metrics() at runtime.

If backward compatibility is required, gate this requirement (e.g., treat missing metric as “not supported” and fall back to prior logic), or bump major version / document the minimum Ponder version this SDK now requires.

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

This pull request refactors the ChainIndexingMetrics type in the Ponder SDK from a single interface with boolean flags to a discriminated union with four distinct states. This improves type safety and makes the state machine more explicit and easier to reason about.

Changes:

  • Converted ChainIndexingMetrics from an interface with conditional boolean fields to a discriminated union of four state variants: Queued, Backfill, Realtime, and Completed
  • Updated deserialization logic to build the appropriate state based on Prometheus metrics values
  • Enhanced invariant checking to validate state-specific constraints at the Prometheus metrics level
  • Updated test mocks and test assertions to reflect the new data model

Reviewed changes

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

Show a summary per file
File Description
packages/ponder-sdk/src/indexing-metrics.ts Defines the new discriminated union type structure with four state variants, replacing the previous single interface with boolean flags
packages/ponder-sdk/src/deserialize/utils.ts Adds DeepPartial utility type for handling partial/unvalidated data structures during deserialization
packages/ponder-sdk/src/deserialize/indexing-metrics.ts Updates deserialization logic to construct appropriate state variants based on Prometheus metrics, with enhanced invariant validation
packages/ponder-sdk/src/deserialize/indexing-metrics.mock.ts Updates mock test data to use the new discriminated union structure with explicit type fields
packages/ponder-sdk/src/client.test.ts Updates test assertion to match the new error message format for conflicting metrics

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

Comment on lines 119 to 122
* Represents the indexing metrics for a chain that is currently in
* the real-time indexing phase by a Ponder app. It means that
* the backfill phase transitioned to completed phase, as there was
* no "config end block" specified for the chain.
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

The phrase "transitioned to completed phase" is confusing because "Completed" is a separate distinct state in this type system. Consider clarifying that the backfill phase finished (rather than saying it "transitioned to completed phase"), and since there was no config end block, indexing continues in real-time mode. For example: "Represents the indexing metrics for a chain that has finished the backfill phase and is currently in the real-time indexing phase, as there was no 'config end block' specified for the chain."

Copilot uses AI. Check for mistakes.
Comment on lines +141 to +143
* Represents the indexing metrics for a chain that has completed indexing by
* a Ponder app. It means that the backfill phase transitioned to completed phase.
* No more blocks are required to be indexed for the chain at this point.
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

The phrase "transitioned to completed phase" is redundant and could be clearer. Since this IS the Completed state, consider simplifying to: "Represents the indexing metrics for a chain that has finished indexing. The backfill phase completed and reached the configured end block for the chain. No more blocks are required to be indexed."

Suggested change
* Represents the indexing metrics for a chain that has completed indexing by
* a Ponder app. It means that the backfill phase transitioned to completed phase.
* No more blocks are required to be indexed for the chain at this point.
* Represents the indexing metrics for a chain that has finished indexing.
* The backfill phase completed and reached the configured end block for the chain,
* if one was specified. No more blocks are required to be indexed for the chain.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

@tk-o tk-o left a comment

Choose a reason for hiding this comment

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

Self-review completed.


# HELP ponder_historical_completed_indexing_seconds Number of seconds that have been completed
# TYPE ponder_historical_completed_indexing_seconds gauge
ponder_historical_completed_indexing_seconds{chain="10"} 34242
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ponder_historical_completed_indexing_seconds is useful to know if chain indexing is queued.


const schemaSerializedChainIndexingMetricsCompleted = z.object({
type: z.literal(ChainIndexingMetricTypes.Completed),
targetBlock: schemaBlockRef,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Perhaps we just need a better name here, i.e. lastSyncedBlock or lastIndexedBlock. This is for a completed phase, so there must be some "last"/"end"/"target" block defined.

* @returns Unvalidated (possibly incomplete) Chain Indexing Metrics
* to be validated by {@link schemaSerializedChainIndexingMetrics}.
*/
function buildUnvalidatedChainIndexingMetrics(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This function collects all per-chain metrics and translated them into business-layer data model. Value returned by this function is unvalidated, but then is quickly checked by schemaPonderIndexingMetrics schema.

Comment on lines +201 to +240
const chainReferences = prometheusMetrics.getLabels("ponder_sync_block", "chain");

// Validate per-chain invariants.
for (const chainReference of chainReferences) {
const ponderHistoricalCompletedIndexingSeconds = prometheusMetrics.getValue(
"ponder_historical_completed_indexing_seconds",
{ chain: chainReference },
);

// Invariant: historical completed indexing seconds must be a non-negative integer.
if (
typeof ponderHistoricalCompletedIndexingSeconds !== "number" ||
!Number.isInteger(ponderHistoricalCompletedIndexingSeconds) ||
ponderHistoricalCompletedIndexingSeconds < 0
) {
ctx.issues.push({
code: "custom",
input: ctx.value,
message: `'ponder_historical_completed_indexing_seconds' metric for '${chainReference}' chain must be a non-negative integer. Received: ${ponderHistoricalCompletedIndexingSeconds}`,
});
}

const ponderSyncIsComplete = prometheusMetrics.getValue("ponder_sync_is_complete", {
chain: chainReference,
});

const ponderSyncIsRealtime = prometheusMetrics.getValue("ponder_sync_is_realtime", {
chain: chainReference,
});

// Invariant: `ponder_sync_is_complete` and `ponder_sync_is_realtime` cannot
// both be `1` at the same time.
if (ponderSyncIsComplete === 1 && ponderSyncIsRealtime === 1) {
ctx.issues.push({
code: "custom",
input: ctx.value,
message: `'ponder_sync_is_complete' and 'ponder_sync_is_realtime' metrics cannot both be 1 at the same time for chain ${chainReference}`,
});
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These invariants allow buildUnvalidatedChainIndexingMetrics to work on validated per-chain metric values.

* const update: PartialConfig = { b: { y: { z: true } } };
* ```
*/
export type DeepPartial<T> = {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Very useful type while working with partially undefined data.

// Act & Assert
await expect(ponderClient.metrics()).rejects.toThrowError(
/Invalid serialized Ponder Indexing Metrics.*Chain Indexing Metrics cannot have both `indexingCompleted` and `indexingRealtime` as `true`/,
/Invalid serialized Ponder Indexing Metrics.*'ponder_sync_is_complete' and 'ponder_sync_is_realtime' metrics cannot both be 1 at the same time for chain 10/,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Better error message referring directly to metric names.

Copy link

@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: 3

🤖 Fix all issues with AI agents
In `@packages/ponder-sdk/src/deserialize/indexing-metrics.ts`:
- Around line 75-141: In buildUnvalidatedChainIndexingMetrics, treat missing
per-chain metric values as "Queued" instead of falling through to Backfill:
change the ponderHistoricalCompletedIndexingSeconds check to treat both 0 and
undefined/null as queued (e.g., if ponderHistoricalCompletedIndexingSeconds ==
null || ponderHistoricalCompletedIndexingSeconds === 0) and ensure the
subsequent checks for ponderSyncIsComplete and ponderSyncIsRealtime only
consider a value of 1 as true (leave them as strict === 1) so undefined/null
won't be misinterpreted; update logic around latestSyncedBlock and
backfillTotalBlocks handling accordingly so missing metric values don't produce
an unintended Backfill result.

In `@packages/ponder-sdk/src/deserialize/utils.ts`:
- Around line 31-37: DeepPartial currently treats any non-primitive as a nested
object (so Map/Set/Date/RegExp/Function get recursed into); update the
conditional in the DeepPartial type to exclude built-in non-plain objects by
adding a guard: after the array branch check add a case like "T[P] extends Date
| Function | Map<any, any> | Set<any> | WeakMap<any, any> | WeakSet<any> |
RegExp ? T[P] : DeepPartial<T[P]>" so that the type alias DeepPartial<T> only
recurses into plain object shapes and returns the original type for those
built-ins.

In `@packages/ponder-sdk/src/indexing-metrics.ts`:
- Around line 116-136: The doc comment for the interface
ChainIndexingMetricsRealtime uses ambiguous phrasing "the backfill phase
transitioned to completed phase"; update the comment above the
ChainIndexingMetricsRealtime declaration to clearly state that the backfill
phase has finished and the chain has entered realtime indexing mode (i.e.,
backfill completed and indexing continues with no target end block), replacing
the ambiguous "transitioned to completed phase" wording with a concise phrasing
like "the backfill phase has finished and the chain entered realtime mode" so
readers of the ChainIndexingMetricsRealtime docs understand the intended state.

@tk-o
Copy link
Contributor Author

tk-o commented Feb 6, 2026

@greptile review

@vercel vercel bot temporarily deployed to Preview – ensnode.io February 6, 2026 14:16 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 6, 2026 14:16 Inactive
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 6, 2026 14:16 Inactive
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.

2 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

Copilot AI review requested due to automatic review settings February 6, 2026 16:23
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 6, 2026 16:23 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 6, 2026 16:23 Inactive
@vercel vercel bot temporarily deployed to Preview – ensnode.io February 6, 2026 16:23 Inactive
@tk-o
Copy link
Contributor Author

tk-o commented Feb 6, 2026

@greptile review

Copy link

@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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/ponder-sdk/src/indexing-status.ts (1)

30-37: ⚠️ Potential issue | 🟡 Minor

JSDoc on chains is now slightly inaccurate.

Line 32 still says "Map of indexed chain IDs to their block reference," but the value type is now ChainIndexingStatus, not BlockRef.

📝 Suggested doc fix
   /**
-   * Map of indexed chain IDs to their block reference.
+   * Map of indexed chain IDs to their indexing status.
    *
    * Guarantees:
    * - Includes entry for at least one indexed chain.
    */
   chains: Map<ChainId, ChainIndexingStatus>;

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.

3 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

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 7 out of 7 changed files in this pull request and generated 1 comment.


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

Add `backfillTotalBlocks` field to `ChainIndexingMetricsQueued`

The `ponder_historical_total_blocks` metric is calculated for all indexed chains during Ponder app initialization, including queued chains.

When indexing multiple chains, typically one chain is in backfill phase while others are queued. Since `ponder_historical_total_blocks` can be useful in both phases, both `ChainIndexingMetricsQueued` and `ChainIndexingMetricsBackfill` now include the `backfillTotalBlocks` field to reference this metric.
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 7, 2026 06:49 Inactive
@vercel vercel bot temporarily deployed to Preview – ensnode.io February 7, 2026 06:49 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 7, 2026 06:49 Inactive
Copy link

@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: 1

🤖 Fix all issues with AI agents
In `@packages/ponder-sdk/src/indexing-metrics.ts`:
- Around line 63-96: There's a typo in the JSDoc for BackfillTotalBlocks: remove
the extra period in the phrase "Ponder metric.." so it reads "Ponder metric."
Update the comment above the export type BackfillTotalBlocks (the block starting
with "Number of blocks required to be indexed during backfill.") to correct that
punctuation.

Copilot AI review requested due to automatic review settings February 7, 2026 06:57
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 7, 2026 06:57 Inactive
@vercel vercel bot temporarily deployed to Preview – ensnode.io February 7, 2026 06:57 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 7, 2026 06:57 Inactive
@tk-o
Copy link
Contributor Author

tk-o commented Feb 7, 2026

@greptile review

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.

7 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 7, 2026

Additional Comments (1)

packages/ponder-sdk/src/deserialize/indexing-metrics.ts
Missing per-chain metric validation

invariant_includesRequiredMetrics() only checks that metric names exist globally, but it doesn’t verify that each chain returned by ponder_sync_block{chain=...} also has corresponding series for those required metrics. If a chain is present in ponder_sync_block but missing ponder_historical_total_blocks (or ponder_sync_is_complete/ponder_sync_is_realtime/timestamps, etc.), buildUnvalidatedChainIndexingMetrics() will read undefined and the error will surface later as a generic Zod/type error rather than a clear “missing metric series for chain X”. Consider adding per-chain presence checks for each required metric/label combination (similar to what you already do for ponder_historical_completed_indexing_seconds).

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 7 out of 7 changed files in this pull request and generated 5 comments.


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

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 7, 2026 12:29
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 7, 2026 12:29 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 7, 2026 12:29 Inactive
@vercel vercel bot temporarily deployed to Preview – ensnode.io February 7, 2026 12:29 Inactive
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 7 out of 7 changed files in this pull request and generated 2 comments.


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

Comment on lines 31 to 34
/**
* Map of indexed chain IDs to their block reference.
*
* Guarantees:
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

The doc comment for PonderIndexingStatus.chains is now inaccurate: it still says the map values are a “block reference”, but the type was changed to ChainIndexingStatus (wrapping checkpointBlock). Update the comment to reflect the new shape to avoid confusing consumers.

Copilot uses AI. Check for mistakes.
Comment on lines 144 to +148
/**
* Is indexing completed for the chain?
*
* This will be true when the backfill has been completed,
* and a specified end block for the chain has been reached.
* A {@link BlockRef} to the "highest" block that has been discovered by RPCs
* and stored in the RPC cache as of the time the metric value was captured.
*/
indexingCompleted: boolean;
latestKnownBlock: BlockRef;
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

The JSDoc for latestKnownBlock describes it as the highest block discovered via RPC and stored in the RPC cache. However, the deserializer currently derives this field from ponder_sync_block (closest-to-tip synced block). Please align the documentation with the actual source of truth, or adjust the deserialization logic to populate this field from a metric that truly represents “latest known block”.

Copilot uses AI. Check for mistakes.
* discovered by RPCs and stored in the RPC cache.
*/
export interface ChainIndexingMetricsRealtime {
type: typeof ChainIndexingMetricTypes.Realtime;
Copy link
Contributor

Choose a reason for hiding this comment

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

Field name and documentation claim latestKnownBlock represents latest discovered block by RPCs, but it actually contains the latest synced/indexed block from ponder_sync_block metric

Fix on Vercel

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.

1 participant