Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3f5dc4f
Create `ensRainbowClient` singleton for ENSIndexer app
tk-o Mar 30, 2026
f9e4e11
Simplify `ensrainbow/signleton.ts` file
tk-o Mar 30, 2026
40bab87
Create `waitForEnsRainbowToBeReady` function
tk-o Mar 30, 2026
e84c0c7
Implement `eventHandlerPreconditios`
tk-o Mar 30, 2026
febed1c
docs(changeset): Introduced event handler preconditions to improve re…
tk-o Mar 30, 2026
911035a
Merge remote-tracking branch 'origin/main' into feat/onchain-event-ha…
tk-o Mar 30, 2026
22c3c22
Fix URL comparison for ENSRainbow singleton instnace
tk-o Mar 30, 2026
d0dd98c
Apply suggestions from code review
tk-o Mar 30, 2026
b9a0829
Apply PR feedback
tk-o Mar 30, 2026
ef53bf8
Update testing suite
tk-o Mar 30, 2026
d51b2ea
Update testing suite
tk-o Mar 31, 2026
e60b06f
Update ENSDb SDK to allow storing and reading `EnsRainbowPublicConfig…
tk-o Mar 31, 2026
f929618
docs(changeset): Extended the ENSNode Metadata with ENSRainbow Public…
tk-o Mar 31, 2026
63fbec5
Enable ENSDb Writer Worker to store "unstarted" Indexing Status object
tk-o Mar 31, 2026
fb1d93e
Require valid ENSRainbow connection before starting indexing
tk-o Mar 31, 2026
c3967b9
Update testing suite
tk-o Mar 31, 2026
f346b2a
Apply AI PR feedback
tk-o Apr 1, 2026
4e2454b
Improve docs for Ponder Indexing Engine
tk-o Apr 1, 2026
caef441
Merge remote-tracking branch 'origin/main' into feat/ensure-valid-ens…
tk-o Apr 2, 2026
3d7bfb3
Apply PR feedback
tk-o Apr 2, 2026
8b96b5d
Merge branch 'main' into feat/ensure-valid-ensrainbow-connection
shrugs Apr 3, 2026
4a80427
fix: tidy up ensdb reader fns
shrugs Apr 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 47 additions & 22 deletions apps/ensindexer/src/lib/ensrainbow/singleton.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import config from "@/config";

import { secondsToMilliseconds } from "date-fns";
import pRetry from "p-retry";

import type { Duration } from "@ensnode/ensnode-sdk";
import { EnsRainbowApiClient } from "@ensnode/ensrainbow-sdk";

import { logger } from "@/lib/logger";

const { ensRainbowUrl, labelSet } = config;

if (ensRainbowUrl.href === EnsRainbowApiClient.defaultOptions().endpointUrl.href) {
console.warn(
`Using default public ENSRainbow server which may cause increased network latency. For production, use your own ENSRainbow server that runs on the same network as the ENSIndexer server.`,
);
logger.warn({
msg: `Using default public ENSRainbow server which may cause increased network latency`,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
msg: `Using default public ENSRainbow server which may cause increased network latency`,
msg: `Using default public ENSRainbow server. This adds network latency that will significantly reduce indexing performance.`,

advice: `For production, use your own ENSRainbow server that runs on the same network as the ENSIndexer server.`,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
advice: `For production, use your own ENSRainbow server that runs on the same network as the ENSIndexer server.`,
advice: `Use your own ENSRainbow service that runs on the same network as your ENSIndexer service.`,

});
}

/**
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I note a few lines below that EnsRainbowApiClient uses a param named endpointUrl. Suggest to rename that to ensRainbowUrl if you think it's ok to do that in this PR.

Expand All @@ -35,38 +40,58 @@ let waitForEnsRainbowToBeReadyPromise: Promise<void> | undefined;
* Blocks execution until the ENSRainbow instance is ready to serve requests.
*
* Note: It may take 30+ minutes for the ENSRainbow instance to become ready in
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* Note: It may take 30+ minutes for the ENSRainbow instance to become ready in
* Note: It may take 30+ minutes for the ENSRainbow instance to become healthy in

* a cold start scenario. We use retries for the ENSRainbow health check with
* an exponential backoff strategy to handle this.
* a cold start scenario. We use retries with a fixed interval between attempts
* for the ENSRainbow health check to allow for ample time for ENSRainbow to
* become ready.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* become ready.
* become healthy.

*
* @throws When ENSRainbow fails to become ready after all configured retry attempts.
* This error will trigger termination of the ENSIndexer process.
*/
export function waitForEnsRainbowToBeReady(): Promise<void> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
export function waitForEnsRainbowToBeReady(): Promise<void> {
export function waitForEnsRainbowToBeHealthy(): Promise<void> {

Please note: There's many places in this file where the word "healthy" is written. I assume every single instance where this word is used should change to "ready".

We should always write in a way that is maximally accurate. Here we are not checking the /ready API endpoint. We are checking the /healthy endpoint. Therefore the language we use everywhere here needs to be updated.

if (waitForEnsRainbowToBeReadyPromise) {
return waitForEnsRainbowToBeReadyPromise;
}
if (waitForEnsRainbowToBeReadyPromise) return waitForEnsRainbowToBeReadyPromise;

logger.info({
msg: `Waiting for ENSRainbow instance to be ready`,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
msg: `Waiting for ENSRainbow instance to be ready`,
msg: `Waiting for your ENSRainbow instance to be healthy`,

ensRainbowInstance: ensRainbowUrl.href,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
ensRainbowInstance: ensRainbowUrl.href,
ensRainbowUrl: ensRainbowUrl.href,

});

console.log(`Waiting for ENSRainbow instance to be ready at '${ensRainbowUrl}'...`);
const retryInterval: Duration = 5;
const retryIntervalMs = secondsToMilliseconds(retryInterval);
const retriesPerMinute = 60 / retryInterval;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
const retriesPerMinute = 60 / retryInterval;
const retriesPerMinute = secondsInMinute / retryInterval;

import from date-fns


waitForEnsRainbowToBeReadyPromise = pRetry(async () => ensRainbowClient.health(), {
retries: 12, // This allows for a total of over 1 hour of retries with the exponential backoff strategy.
// 1 + 2 + 4 + ... + 2048 = 2^12 - 1 = 4,095s ≈ 1h 8m
retries: retriesPerMinute * 60, // This allows for a total of over 1 hour of retries with `retryInterval` between attempts.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
retries: retriesPerMinute * 60, // This allows for a total of over 1 hour of retries with `retryInterval` between attempts.
retries: retriesPerMinute * minutesInHour, // This allows for a total of 1 hour of retries with `retryInterval` between attempts.

minTimeout: retryIntervalMs,
maxTimeout: retryIntervalMs,
onFailedAttempt: ({ error, attemptNumber, retriesLeft }) => {
console.warn(
`Attempt ${attemptNumber} failed for the ENSRainbow health check at '${ensRainbowUrl}' (${error.message}). ${retriesLeft} retries left.`,
);
// Log once every minute to avoid excessive logging during ENSRainbow cold start,
// while still providing visibility into the retry process.
if (attemptNumber % 12 === 0) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
if (attemptNumber % 12 === 0) {
if (attemptNumber % Math.floor(retriesPerMinute) === 0) {

logger.warn({
msg: `ENSRainbow health check failed`,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
msg: `ENSRainbow health check failed`,
msg: `Health check for your ENSRainbow failed`,

attempt: attemptNumber,
retriesLeft,
error: retriesLeft === 0 ? error : undefined,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do this? Why not always display the error, even if retriesLeft is 0?

Then, in the case of the other special final error log statement after all retries have failed, we might not log any error there at all?

Please ignore if a good reason.

ensRainbowInstance: ensRainbowUrl.href,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
ensRainbowInstance: ensRainbowUrl.href,
ensRainbowUrl: ensRainbowUrl.href,

advice: `This might be due to ENSRainbow having a cold start, which can take 30+ minutes.`,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
advice: `This might be due to ENSRainbow having a cold start, which can take 30+ minutes.`,
advice: `This might be due to your ENSRainbow performing a cold start which can take 30+ minutes to complete.`,

});
}
},
})
.then(() => console.log(`ENSRainbow instance is ready at '${ensRainbowUrl}'.`))
.then(() => {
logger.info({
msg: `ENSRainbow instance is ready`,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
msg: `ENSRainbow instance is ready`,
msg: `Your ENSRainbow instance is healthy`,

ensRainbowInstance: ensRainbowUrl.href,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
ensRainbowInstance: ensRainbowUrl.href,
ensRainbowUrl: ensRainbowUrl.href,

});
})
.catch((error) => {
const errorMessage = error instanceof Error ? error.message : "Unknown error";

console.error(`ENSRainbow health check failed after multiple attempts: ${errorMessage}`);

// Throw the error to terminate the ENSIndexer process due to the failed health check of a critical dependency
throw new Error(errorMessage, {
cause: error instanceof Error ? error : undefined,
logger.error({
msg: `ENSRainbow health check failed after multiple attempts`,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
msg: `ENSRainbow health check failed after multiple attempts`,
msg: `Health checks for your ENSRainbow instance repeatedly failed for over an hour`,

error,
ensRainbowInstance: ensRainbowUrl.href,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
ensRainbowInstance: ensRainbowUrl.href,
ensRainbowUrl: ensRainbowUrl.href,

});

throw error;
});

return waitForEnsRainbowToBeReadyPromise;
Expand Down
1 change: 1 addition & 0 deletions apps/ensindexer/src/lib/graphnode-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { LabelHash, LiteralLabel } from "@ensnode/ensnode-sdk";
import { type EnsRainbow, ErrorCode, isHealError } from "@ensnode/ensrainbow-sdk";

import { ensRainbowClient } from "@/lib/ensrainbow/singleton";
import { logger } from "@/lib/logger";

/**
* Attempt to heal a labelHash to its original label.
Expand Down
4 changes: 1 addition & 3 deletions apps/ensindexer/src/lib/indexing-engines/ponder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -651,9 +651,7 @@ describe("addOnchainEventListener", () => {
});
expect.fail("Should have thrown");
} catch (error) {
expect(error).toBeInstanceOf(Error);
expect((error as Error).message).toBe("Original connection error");
expect((error as Error).cause).toBe(originalError);
expect(error).toBe(originalError);
}
});
});
Expand Down
130 changes: 54 additions & 76 deletions apps/ensindexer/src/lib/indexing-engines/ponder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,10 @@ const EventTypeIds = {
Setup: "Setup",

/**
* Onchain event
* Onchain log event
*
* Driven by an onchain event emitted by an indexed contract.
* This is Ponder's `LogEvent`, driven by an onchain log event emitted by
* an indexed contract.
*/
Onchain: "Onchain",
Comment thread
tk-o marked this conversation as resolved.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
Onchain: "Onchain",
OnchainEvent: "OnchainEvent",

} as const;
Expand All @@ -129,107 +130,86 @@ function buildEventTypeId(eventName: EventNames): EventTypeId {
}
}

let preparedIndexingSetup = false;

/**
* Prepare for executing the "setup" event handlers.
*
* This function is guaranteed to be executed just once before
* the first "setup" event handler is executed.
* This is to ensure that we affect the "hot path" of
* indexing as little as possible, since this function is
* called as part of preconditions for every "setup" event.
* During Ponder startup, the "setup" event handlers are executed:
* - After Ponder completed database migrations for ENSIndexer Schema in ENSDb.
* - Before Ponder starts processing any onchain events for indexed chains.
*
* Note that this functions should not have any long-running operations.
* That would delay the population of Ponder Indexing Metrics for
* all indexed chains. Ponder Indexing Metrics are populated only after
* all setup handlers have completed. ENSIndexer relies on
* Ponder Indexing Metrics being immediately available on startup to
* build and store the current Indexing Status snapshot in ENSDb.
* This function is useful to make sure ENSDb is ready for writes, for example,
* by ensuring all required Postgres extensions are installed, etc.
*/
async function prepareIndexingSetup(): Promise<void> {
if (preparedIndexingSetup) {
return;
}

preparedIndexingSetup = true;

// Currently, we don't have any indexing setup preconditions.
async function initializeIndexingSetup(): Promise<void> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
async function initializeIndexingSetup(): Promise<void> {
async function initIndexingSetup(): Promise<void> {

/**
* Setup event handlers should not have any *long-running* preconditions. This is because
* Ponder populates the indexing metrics for all indexed chains only after all setup handlers have run.
* ENSIndexer relies on these indexing metrics being immediately available on startup to build and
* store the current Indexing Status in ENSDb.
*/
}

let preparedIndexingActivation = false;

/**
* Prepare for executing the "onchain" event handlers.
*
* This function is guaranteed to be executed just once before
* the first "onchain" event handler is executed.
* This is to ensure that we affect the "hot path" of
* indexing as little as possible, since this function is
* called as part of preconditions for every "onchain" event.
* During Ponder startup, the "onchain" event handlers are executed
* after all "setup" event handlers have completed.
*
* @throws If valid ENSRainbow connection could not be established after
* multiple attempts.
* This function is useful to make sure any long-running preconditions for
* onchain event handlers are met, for example, waiting for
* the ENSRainbow instance to be ready before processing any onchain events
* that require data from ENSRainbow.
*
* @example A single blocking precondition
* ```ts
* await ensureValidEnsRainbowConnection();
* await waitForEnsRainbowToBeReady();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please see related comments on renaming this.

* ```
Comment thread
tk-o marked this conversation as resolved.
*
* @example Multiple concurrent blocking preconditions
* @example Multiple blocking preconditions
* ```ts
* await Promise.all([
* ensureValidEnsRainbowConnection(),
* waitForEnsRainbowToBeReady(),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please see related comments on renaming this.

* waitForAnotherPrecondition(),
* ]);
* ```
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@tk-o Important: I see a key issue with the current way initIndexingSetup and initIndexingOnchainEvents are written.

They both seem to make the incorrect assumption that ENSIndexer never restarts itself. But what happens if ENSIndexer is restarted at particular moments in time?

For example:

  1. What if initIndexingSetup has logic to do something like install a postgres extension, but the extension has already been installed by a previous run of ENSIndexer?
  2. What if initIndexingOnchainEvents has logic to do something like initialize a bunch of state inside the ENSNode Metadata Table, but that logic has already been executed and the related state has already been initialized by a previous run of ENSIndexer with the same ENSIndexer Schema Name?

We really need you to think more strictly and systematically about all the possible state interleavings and ensure that for all possible state interleavings we have a mature solution.

I assume that one possible strategy for making this implementation more mature would be to query the state of the ENSNode Metadatadata table for the configured ENSIndexer Schema Name, and then based on the state reflected there determine if it's a completely new instance or not? This needs careful planning as even the way I've described the idea here would not be reliable enough as some additional state would likely need to be added into the ENSNode Metadata table (an additional key?) to identify the exact state of executing these init functions in an idempotent way.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is there a special reason why initIndexingSetup doesn't include logic inside of it to initialize state in the ENSNode Metadata Tables for the ENSIndexer Schema Name? For example, wouldn't we want it to initialize everything except for the ENSRainbow Metadata?

*
* @example Multiple sequential blocking preconditions
* ```ts
* await ensureValidEnsRainbowConnection();
* await waitForAnotherPrecondition();
* ```
*/
async function prepareIndexingActivation() {
if (preparedIndexingActivation) {
return;
}

preparedIndexingActivation = true;

try {
await ensureValidEnsRainbowConnection();
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error";

console.error(
`[Ponder Indexing Engine]: Failed to establish a valid connection to ENSRainbow: ${errorMessage}`,
);

// Throw the error to terminate the ENSIndexer process due to failed connection to critical dependency
throw new Error(errorMessage, {
cause: error,
});
}
async function initializeIndexingActivation(): Promise<void> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
async function initializeIndexingActivation(): Promise<void> {
async function initIndexingOnchainEvents(): Promise<void> {

await ensureValidEnsRainbowConnection();
}

let indexingSetupPromise: Promise<void> | null = null;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
let indexingSetupPromise: Promise<void> | null = null;
let initIndexingSetupPromise: Promise<void> | null = null;

let indexingActivationPromise: Promise<void> | null = null;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
let indexingActivationPromise: Promise<void> | null = null;
let initIndexingOnchainEventsPromise: Promise<void> | null = null;


/**
* Execute any necessary preconditions before running an event handler
* for a given event type.
*
* Some event handlers may have preconditions that need to be met before
* they can run.
*
* This function is idempotent and will only execute its logic once, even if
* called multiple times. This is to ensure that we affect the "hot path" of
* indexing as little as possible, since this function is called for every
* "onchain" event.
*/
async function eventHandlerPreconditions<EventName extends EventNames>(
eventName: EventName,
): Promise<void> {
const eventType = buildEventTypeId(eventName);

async function eventHandlerPreconditions(eventType: EventTypeId): Promise<void> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
async function eventHandlerPreconditions(eventType: EventTypeId): Promise<void> {
async function initEventTypePreconditions(eventType: EventTypeId): Promise<void> {

switch (eventType) {
case EventTypeIds.Setup:
return prepareIndexingSetup();
case EventTypeIds.Setup: {
// Initialize the indexing setup just once
if (indexingSetupPromise === null) {
indexingSetupPromise = initializeIndexingSetup();
}

return indexingSetupPromise;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why is this function defined such that it returns a Promise<void>? In my mindset it shouldn't return anything ever.

If it returns a Promise<void> doesn't that put the burden of responsibility on the caller of this function to always call the returned promise to ensure the expected guarantee is truly achieved in a situation such as multichain vs omnichain indexing? That sounds like a bad abstraction to put the burden on callers like that.

Why doesn't the code here take the responsibility for calling and awaiting indexingSetupPromise in the event it is still being concurrently executed?

Also I believe the state management here is flawed and needs improvement. Currently your state model only uses indexingSetupPromise which can only represent two states:

  1. Never initialized (null)
  2. Currently initializing or already initialized (non-null)

Why isn't the state model improved to represent three states:

  1. Already initialized (this might be a bool that is set to true at the end of the related init... function)
  2. Never initialized (null)
  3. Currently initializing (non-null)

It might also be good to set the indexingActivationPromise back to null again after completing initialization to free up any memory / resources?

}

case EventTypeIds.Onchain: {
return prepareIndexingActivation();
// Initialize the indexing activation just once
if (indexingActivationPromise === null) {
indexingActivationPromise = initializeIndexingActivation();
}

return indexingActivationPromise;
}
}
}
Expand All @@ -249,12 +229,10 @@ export function addOnchainEventListener<EventName extends EventNames>(
eventName: EventName,
eventHandler: (args: IndexingEngineEventHandlerArgs<EventName>) => Promise<void> | void,
) {
return ponder.on(eventName, async ({ context, event }) => {
await eventHandlerPreconditions(eventName);
const eventType = buildEventTypeId(eventName);

await eventHandler({
context: buildIndexingEngineContext(context),
event,
});
return ponder.on(eventName, async ({ context, event }) => {
await eventHandlerPreconditions(eventType);
await eventHandler({ context: buildIndexingEngineContext(context), event });
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export async function ensureValidEnsRainbowConnection(): Promise<void> {
*/
if (!storedConfig) {
console.log(
'No stored ENSRainbow Public Config found in ENSDb. Validating the omnichain indexing status is "Unstarted"...',
"No stored ENSRainbow Public Config found in ENSDb. Validating the omnichain indexing status is 'Unstarted'...",
);
Comment on lines +134 to +137
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

This precondition module uses console.log/console.warn for operational logging. In ENSIndexer, other runtime components use the shared structured logger (e.g. apps/ensindexer/src/lib/ensrainbow/singleton.ts) so logs carry level/module context and are routed consistently. Please switch these console calls to logger.info/logger.warn/logger.error (including a module field) to keep startup/indexing diagnostics consistent and avoid losing logs in production environments that don’t capture stdout/stderr the same way.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@tk-o I understand you've been doing some optimizations for how logging works in ENSIndexer? Please take the lead to decide how to follow-up on this feedback from Copilot.

/**
* Fetch the indexing status snapshot with retries, to handle potential
Expand Down
16 changes: 3 additions & 13 deletions packages/ensdb-sdk/src/client/ensdb-reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,7 @@ export class EnsDbReader<
key: EnsNodeMetadataKeys.EnsIndexerPublicConfig,
});

if (!record) {
return undefined;
}
if (!record) return undefined;

return deserializeEnsIndexerPublicConfig(record);
}
Expand All @@ -168,10 +166,6 @@ export class EnsDbReader<
key: EnsNodeMetadataKeys.EnsRainbowPublicConfig,
});

if (!record) {
return undefined;
}

return record;
}

Expand All @@ -187,9 +181,7 @@ export class EnsDbReader<
},
);

if (!record) {
return undefined;
}
if (!record) return undefined;

return deserializeCrossChainIndexingStatusSnapshot(record);
}
Expand All @@ -215,9 +207,7 @@ export class EnsDbReader<
),
);

if (result.length === 0) {
return undefined;
}
if (result.length === 0) return undefined;

if (result.length === 1 && result[0]) {
return result[0].value as EnsNodeMetadataType["value"];
Expand Down
Loading