Skip to content

Commit e3ddda0

Browse files
committed
Simplify EnsDbReader class and EnsDbWriter class
Drop all unused methods
1 parent 6bda3d6 commit e3ddda0

6 files changed

Lines changed: 146 additions & 241 deletions

File tree

packages/ensdb-sdk/src/client/ensdb-reader.test.ts

Lines changed: 104 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
import { beforeEach, describe, expect, it, vi } from "vitest";
22

33
import {
4+
buildEnsIndexerStackInfo,
5+
buildIndexingMetadataContextInitialized,
6+
buildIndexingMetadataContextUninitialized,
47
deserializeCrossChainIndexingStatusSnapshot,
5-
serializeEnsIndexerPublicConfig,
8+
deserializeIndexingMetadataContext,
9+
type EnsDbPublicConfig,
10+
serializeIndexingMetadataContext,
611
} from "@ensnode/ensnode-sdk";
712

813
import * as ensDbClientMock from "./ensdb-client.mock";
914
import { EnsDbReader } from "./ensdb-reader";
1015

16+
const executeMock = vi.fn();
1117
const whereMock = vi.fn(async () => [] as Array<{ value: unknown }>);
1218
const fromMock = vi.fn(() => ({ where: whereMock }));
1319
const selectMock = vi.fn(() => ({ from: fromMock }));
14-
const drizzleClientMock = { select: selectMock } as any;
20+
const drizzleClientMock = { select: selectMock, execute: executeMock } as any;
1521

1622
vi.mock("drizzle-orm/node-postgres", () => ({
1723
drizzle: vi.fn(() => drizzleClientMock),
@@ -29,59 +35,125 @@ describe("EnsDbReader", () => {
2935
whereMock.mockClear();
3036
fromMock.mockClear();
3137
selectMock.mockClear();
38+
executeMock.mockClear();
3239
});
3340

34-
describe("getEnsDbVersion", () => {
35-
it("returns undefined when no record exists", async () => {
36-
const ensDbClient = createEnsDbReader();
37-
const { ensNodeSchema } = ensDbClient;
41+
describe("getters", () => {
42+
it("returns the ensDb drizzle client", () => {
43+
const ensDbReader = createEnsDbReader();
44+
expect(ensDbReader.ensDb).toBe(drizzleClientMock);
45+
});
3846

39-
await expect(ensDbClient.getEnsDbVersion()).resolves.toBeUndefined();
47+
it("returns the ensIndexerSchema", () => {
48+
const ensDbReader = createEnsDbReader();
49+
expect(ensDbReader.ensIndexerSchema).toBeDefined();
50+
});
4051

41-
expect(selectMock).toHaveBeenCalledTimes(1);
42-
expect(fromMock).toHaveBeenCalledWith(ensNodeSchema.metadata);
52+
it("returns the ensIndexerSchemaName", () => {
53+
const ensDbReader = createEnsDbReader();
54+
expect(ensDbReader.ensIndexerSchemaName).toBe(ensDbClientMock.ensIndexerSchemaName);
4355
});
4456

45-
it("returns value when one record exists", async () => {
46-
selectResult.current = [{ value: "0.1.0" }];
57+
it("returns the ensNodeSchema", () => {
58+
const ensDbReader = createEnsDbReader();
59+
expect(ensDbReader.ensNodeSchema).toBeDefined();
60+
});
61+
});
4762

48-
await expect(createEnsDbReader().getEnsDbVersion()).resolves.toBe("0.1.0");
63+
describe("buildEnsDbPublicConfig", () => {
64+
it("returns version info with the postgresql version", async () => {
65+
executeMock.mockResolvedValueOnce({
66+
rows: [
67+
{
68+
version: "PostgreSQL 17.4 (Ubuntu 17.4-0ubuntu0.22.04.1) on x86_64-pc-linux-gnu",
69+
},
70+
],
71+
});
72+
73+
const result = await createEnsDbReader().buildEnsDbPublicConfig();
74+
75+
expect(result).toStrictEqual({
76+
versionInfo: {
77+
postgresql: "17.4",
78+
},
79+
} satisfies EnsDbPublicConfig);
80+
expect(executeMock).toHaveBeenCalledWith("SELECT version();");
4981
});
5082

51-
// This scenario should be impossible due to the primary key constraint on
52-
// the ('ensIndexerSchemaName', 'key') columns of the 'ensnode_metadata' table.
53-
it("throws when multiple records exist", async () => {
54-
selectResult.current = [{ value: "0.1.0" }, { value: "0.1.1" }];
83+
it("throws when execute returns no rows", async () => {
84+
executeMock.mockResolvedValueOnce({ rows: [] });
5585

56-
await expect(createEnsDbReader().getEnsDbVersion()).rejects.toThrowError(/ensdb_version/i);
86+
await expect(createEnsDbReader().buildEnsDbPublicConfig()).rejects.toThrow(
87+
/Failed to get PostgreSQL version/,
88+
);
5789
});
58-
});
5990

60-
describe("getEnsIndexerPublicConfig", () => {
61-
it("returns undefined when no record exists", async () => {
62-
await expect(createEnsDbReader().getEnsIndexerPublicConfig()).resolves.toBeUndefined();
91+
it("throws when execute returns an invalid version string", async () => {
92+
executeMock.mockResolvedValueOnce({
93+
rows: [{ version: "invalid version string" }],
94+
});
95+
96+
await expect(createEnsDbReader().buildEnsDbPublicConfig()).rejects.toThrow(
97+
/Failed to get PostgreSQL version/,
98+
);
6399
});
64100

65-
it("deserializes the stored config", async () => {
66-
const serializedConfig = serializeEnsIndexerPublicConfig(ensDbClientMock.publicConfig);
67-
selectResult.current = [{ value: serializedConfig }];
101+
it("propagates errors from execute", async () => {
102+
executeMock.mockRejectedValueOnce(new Error("Connection refused"));
68103

69-
await expect(createEnsDbReader().getEnsIndexerPublicConfig()).resolves.toStrictEqual(
70-
ensDbClientMock.publicConfig,
104+
await expect(createEnsDbReader().buildEnsDbPublicConfig()).rejects.toThrow(
105+
"Connection refused",
71106
);
72107
});
73108
});
74109

75-
describe("getIndexingStatusSnapshot", () => {
76-
it("deserializes the stored indexing status snapshot", async () => {
77-
selectResult.current = [{ value: ensDbClientMock.serializedSnapshot }];
110+
describe("getIndexingMetadataContext", () => {
111+
it("returns an uninitialized context when no record exists", async () => {
112+
const ensDbReader = createEnsDbReader();
113+
const { ensNodeSchema } = ensDbReader;
114+
115+
const result = await ensDbReader.getIndexingMetadataContext();
78116

79-
const expected = deserializeCrossChainIndexingStatusSnapshot(
117+
expect(result).toStrictEqual(buildIndexingMetadataContextUninitialized());
118+
expect(selectMock).toHaveBeenCalledTimes(1);
119+
expect(fromMock).toHaveBeenCalledWith(ensNodeSchema.metadata);
120+
expect(whereMock).toHaveBeenCalled();
121+
});
122+
123+
it("returns the deserialized initialized context when one record exists", async () => {
124+
const indexingStatus = deserializeCrossChainIndexingStatusSnapshot(
80125
ensDbClientMock.serializedSnapshot,
81126
);
127+
const ensDbPublicConfig: EnsDbPublicConfig = {
128+
versionInfo: { postgresql: "17.4" },
129+
};
130+
const ensRainbowPublicConfig = {
131+
serverLabelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
132+
versionInfo: { ensRainbow: "1.9.0" },
133+
};
134+
const stackInfo = buildEnsIndexerStackInfo(
135+
ensDbPublicConfig,
136+
ensDbClientMock.publicConfig,
137+
ensRainbowPublicConfig,
138+
);
139+
const context = buildIndexingMetadataContextInitialized(indexingStatus, stackInfo);
140+
const serialized = serializeIndexingMetadataContext(context);
141+
142+
selectResult.current = [{ value: serialized }];
143+
144+
const result = await createEnsDbReader().getIndexingMetadataContext();
145+
146+
const expected = deserializeIndexingMetadataContext(serialized);
147+
expect(result).toStrictEqual(expected);
148+
});
149+
150+
// This scenario should be impossible due to the primary key constraint on
151+
// the ('ensIndexerSchemaName', 'key') columns of the 'ensnode_metadata' table.
152+
it("throws when multiple records exist", async () => {
153+
selectResult.current = [{ value: "value1" }, { value: "value2" }];
82154

83-
await expect(createEnsDbReader().getIndexingStatusSnapshot()).resolves.toStrictEqual(
84-
expected,
155+
await expect(createEnsDbReader().getIndexingMetadataContext()).rejects.toThrow(
156+
/There must be exactly one ENSNodeMetadata record/,
85157
);
86158
});
87159
});

packages/ensdb-sdk/src/client/ensdb-reader.ts

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,9 @@ import { and, eq } from "drizzle-orm/sql";
22

33
import {
44
buildIndexingMetadataContextUninitialized,
5-
type CrossChainIndexingStatusSnapshot,
6-
deserializeCrossChainIndexingStatusSnapshot,
7-
deserializeEnsIndexerPublicConfig,
85
deserializeIndexingMetadataContext,
96
type EnsDbPublicConfig,
107
type EnsDbVersionInfo,
11-
type EnsIndexerPublicConfig,
128
type IndexingMetadataContext,
139
} from "@ensnode/ensnode-sdk";
1410

@@ -23,9 +19,6 @@ import { parsePgVersionInfo } from "../lib/parse-pg-version-info";
2319
import { EnsNodeMetadataKeys } from "./ensnode-metadata";
2420
import type {
2521
SerializedEnsNodeMetadata,
26-
SerializedEnsNodeMetadataEnsDbVersion,
27-
SerializedEnsNodeMetadataEnsIndexerIndexingStatus,
28-
SerializedEnsNodeMetadataEnsIndexerPublicConfig,
2922
SerializedEnsNodeMetadataIndexingMetadataContext,
3023
} from "./serialize/ensnode-metadata";
3124

@@ -133,36 +126,6 @@ export class EnsDbReader<
133126
return this._ensNodeSchema;
134127
}
135128

136-
/**
137-
* Get ENSDb Version
138-
*
139-
* @returns the existing record, or `undefined`.
140-
*/
141-
async getEnsDbVersion(): Promise<string | undefined> {
142-
const record = await this.getEnsNodeMetadata<SerializedEnsNodeMetadataEnsDbVersion>({
143-
key: EnsNodeMetadataKeys.EnsDbVersion,
144-
});
145-
146-
return record;
147-
}
148-
149-
/**
150-
* Get ENSIndexer Public Config
151-
*
152-
* @returns the existing record, or `undefined`.
153-
*/
154-
async getEnsIndexerPublicConfig(): Promise<EnsIndexerPublicConfig | undefined> {
155-
const record = await this.getEnsNodeMetadata<SerializedEnsNodeMetadataEnsIndexerPublicConfig>({
156-
key: EnsNodeMetadataKeys.EnsIndexerPublicConfig,
157-
});
158-
159-
if (!record) {
160-
return undefined;
161-
}
162-
163-
return deserializeEnsIndexerPublicConfig(record);
164-
}
165-
166129
/**
167130
* Build ENSDb Public Config
168131
*/
@@ -174,25 +137,6 @@ export class EnsDbReader<
174137
};
175138
}
176139

177-
/**
178-
* Get Indexing Status Snapshot
179-
*
180-
* @returns the existing record, or `undefined`.
181-
*/
182-
async getIndexingStatusSnapshot(): Promise<CrossChainIndexingStatusSnapshot | undefined> {
183-
const record = await this.getEnsNodeMetadata<SerializedEnsNodeMetadataEnsIndexerIndexingStatus>(
184-
{
185-
key: EnsNodeMetadataKeys.EnsIndexerIndexingStatus,
186-
},
187-
);
188-
189-
if (!record) {
190-
return undefined;
191-
}
192-
193-
return deserializeCrossChainIndexingStatusSnapshot(record);
194-
}
195-
196140
/**
197141
* Get Indexing Metadata Context
198142
*

packages/ensdb-sdk/src/client/ensdb-writer.test.ts

Lines changed: 31 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import { migrate } from "drizzle-orm/node-postgres/migrator";
22
import { beforeEach, describe, expect, it, vi } from "vitest";
33

44
import {
5+
buildEnsIndexerStackInfo,
6+
buildIndexingMetadataContextInitialized,
57
deserializeCrossChainIndexingStatusSnapshot,
6-
serializeCrossChainIndexingStatusSnapshot,
7-
serializeEnsIndexerPublicConfig,
8+
serializeIndexingMetadataContext,
89
} from "@ensnode/ensnode-sdk";
910

1011
import * as ensDbClientMock from "./ensdb-client.mock";
@@ -32,59 +33,46 @@ describe("EnsDbWriter", () => {
3233
vi.mocked(migrate).mockClear();
3334
});
3435

35-
describe("upsertEnsDbVersion", () => {
36-
it("writes the database version metadata", async () => {
37-
const ensDbClient = createEnsDbWriter();
38-
const { ensNodeSchema } = ensDbClient;
36+
describe("upsertIndexingMetadataContext", () => {
37+
it("serializes and writes the indexing metadata context", async () => {
38+
const ensDbWriter = createEnsDbWriter();
39+
const { ensNodeSchema } = ensDbWriter;
3940

40-
await ensDbClient.upsertEnsDbVersion("0.2.0");
41-
42-
expect(insertMock).toHaveBeenCalledWith(ensNodeSchema.metadata);
43-
expect(valuesMock).toHaveBeenCalledWith({
44-
ensIndexerSchemaName: ensDbClientMock.ensIndexerSchemaName,
45-
key: EnsNodeMetadataKeys.EnsDbVersion,
46-
value: "0.2.0",
47-
});
48-
expect(onConflictDoUpdateMock).toHaveBeenCalledWith({
49-
target: [ensNodeSchema.metadata.ensIndexerSchemaName, ensNodeSchema.metadata.key],
50-
set: { value: "0.2.0" },
51-
});
52-
});
53-
});
54-
55-
describe("upsertEnsIndexerPublicConfig", () => {
56-
it("serializes and writes the public config", async () => {
57-
const expectedValue = serializeEnsIndexerPublicConfig(ensDbClientMock.publicConfig);
58-
59-
await createEnsDbWriter().upsertEnsIndexerPublicConfig(ensDbClientMock.publicConfig);
60-
61-
expect(valuesMock).toHaveBeenCalledWith({
62-
ensIndexerSchemaName: ensDbClientMock.ensIndexerSchemaName,
63-
key: EnsNodeMetadataKeys.EnsIndexerPublicConfig,
64-
value: expectedValue,
65-
});
66-
});
67-
});
68-
69-
describe("upsertIndexingStatusSnapshot", () => {
70-
it("serializes and writes the indexing status snapshot", async () => {
71-
const snapshot = deserializeCrossChainIndexingStatusSnapshot(
41+
const indexingStatus = deserializeCrossChainIndexingStatusSnapshot(
7242
ensDbClientMock.serializedSnapshot,
7343
);
74-
const expectedValue = serializeCrossChainIndexingStatusSnapshot(snapshot);
44+
const ensDbPublicConfig = {
45+
versionInfo: { postgresql: "17.4" },
46+
};
47+
const ensRainbowPublicConfig = {
48+
serverLabelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 },
49+
versionInfo: { ensRainbow: "1.9.0" },
50+
};
51+
const stackInfo = buildEnsIndexerStackInfo(
52+
ensDbPublicConfig,
53+
ensDbClientMock.publicConfig,
54+
ensRainbowPublicConfig,
55+
);
56+
const context = buildIndexingMetadataContextInitialized(indexingStatus, stackInfo);
57+
const expectedValue = serializeIndexingMetadataContext(context);
7558

76-
await createEnsDbWriter().upsertIndexingStatusSnapshot(snapshot);
59+
await ensDbWriter.upsertIndexingMetadataContext(context);
7760

61+
expect(insertMock).toHaveBeenCalledWith(ensNodeSchema.metadata);
7862
expect(valuesMock).toHaveBeenCalledWith({
7963
ensIndexerSchemaName: ensDbClientMock.ensIndexerSchemaName,
80-
key: EnsNodeMetadataKeys.EnsIndexerIndexingStatus,
64+
key: EnsNodeMetadataKeys.IndexingMetadataContext,
8165
value: expectedValue,
8266
});
67+
expect(onConflictDoUpdateMock).toHaveBeenCalledWith({
68+
target: [ensNodeSchema.metadata.ensIndexerSchemaName, ensNodeSchema.metadata.key],
69+
set: { value: expectedValue },
70+
});
8371
});
8472
});
8573

8674
describe("migrateEnsNodeSchema", () => {
87-
it("calls drizzle-orm migrateEnsNodeSchema with the correct parameters", async () => {
75+
it("calls drizzle-orm migrate with the correct parameters", async () => {
8876
const migrationsDirPath = "/path/to/migrations";
8977

9078
await createEnsDbWriter().migrateEnsNodeSchema(migrationsDirPath);
@@ -95,7 +83,7 @@ describe("EnsDbWriter", () => {
9583
});
9684
});
9785

98-
it("propagates errors from the migrateEnsNodeSchema function", async () => {
86+
it("propagates errors from the migrate function", async () => {
9987
const migrationsDirPath = "/path/to/migrations";
10088
vi.mocked(migrate).mockRejectedValueOnce(new Error("Migration failed"));
10189

0 commit comments

Comments
 (0)