From aa3ee2776048258d2dccdc6b2be57f5dcdc5b8c1 Mon Sep 17 00:00:00 2001 From: nigiri <168690269+0xnigir1@users.noreply.github.com> Date: Fri, 13 Dec 2024 15:02:32 -0300 Subject: [PATCH] fix: imports, renamings and natspecs --- .../services/sharedDependencies.service.ts | 8 +- .../unit/sharedDependencies.service.spec.ts | 1 - packages/data-flow/README.md | 1 - packages/data-flow/src/external.ts | 3 +- packages/data-flow/src/registries/index.ts | 4 +- .../{ => strategy}/cachedStrategyRegistry.ts | 13 +- .../{ => strategy}/dbStrategyRegistry.ts | 2 +- .../src/registries/strategy/index.ts | 2 + .../src/registries/strategyRegistry.ts | 58 ------ .../registries/cachedStrategyRegistry.spec.ts | 2 +- .../registries/dbStrategyRegistry.spec.ts | 2 +- .../test/registries/strategyRegistry.spec.ts | 171 ------------------ .../strategyRepository.interface.ts | 19 ++ .../kysely/strategy.repository.ts | 3 + .../20241210T175001_strategy_registry.ts | 6 - 15 files changed, 45 insertions(+), 250 deletions(-) rename packages/data-flow/src/registries/{ => strategy}/cachedStrategyRegistry.ts (83%) rename packages/data-flow/src/registries/{ => strategy}/dbStrategyRegistry.ts (96%) create mode 100644 packages/data-flow/src/registries/strategy/index.ts delete mode 100644 packages/data-flow/src/registries/strategyRegistry.ts delete mode 100644 packages/data-flow/test/registries/strategyRegistry.spec.ts diff --git a/apps/processing/src/services/sharedDependencies.service.ts b/apps/processing/src/services/sharedDependencies.service.ts index 612d8b6..92a9eba 100644 --- a/apps/processing/src/services/sharedDependencies.service.ts +++ b/apps/processing/src/services/sharedDependencies.service.ts @@ -1,13 +1,11 @@ import { CoreDependencies, - InMemoryEventsRegistry, - IStrategyRegistry, -} from "@grants-stack-indexer/data-flow"; -import { DatabaseStrategyRegistry, IEventsRegistry, InMemoryCachedStrategyRegistry, -} from "@grants-stack-indexer/data-flow/dist/src/internal.js"; + InMemoryEventsRegistry, + IStrategyRegistry, +} from "@grants-stack-indexer/data-flow"; import { EnvioIndexerClient } from "@grants-stack-indexer/indexer-client"; import { IpfsProvider } from "@grants-stack-indexer/metadata"; import { PricingProviderFactory } from "@grants-stack-indexer/pricing"; diff --git a/apps/processing/test/unit/sharedDependencies.service.spec.ts b/apps/processing/test/unit/sharedDependencies.service.spec.ts index 31c662f..437c27e 100644 --- a/apps/processing/test/unit/sharedDependencies.service.spec.ts +++ b/apps/processing/test/unit/sharedDependencies.service.spec.ts @@ -38,7 +38,6 @@ vi.mock("@grants-stack-indexer/indexer-client", () => ({ EnvioIndexerClient: vi.fn(), })); -// Update the mock to handle async initialization vi.mock("@grants-stack-indexer/data-flow", () => { const mockStrategyRegistry = { getStrategies: vi.fn(), diff --git a/packages/data-flow/README.md b/packages/data-flow/README.md index af31563..d6ab601 100644 --- a/packages/data-flow/README.md +++ b/packages/data-flow/README.md @@ -95,7 +95,6 @@ The `EventsFetcher` class is responsible for fetching events from the blockchain The `StrategyRegistry` stores strategy IDs to populate strategy events with them given the Strategy address. There are 3 implementations: -- `InMemoryStrategyRegistry`: stores map in-memory - `DatabaseStrategyRegistry`: persists data to database using IStrategyRepository - `InMemoryCachedStrategyRegistry`: stores map in-memory as cache and persists to database diff --git a/packages/data-flow/src/external.ts b/packages/data-flow/src/external.ts index 28cb58e..4a22f36 100644 --- a/packages/data-flow/src/external.ts +++ b/packages/data-flow/src/external.ts @@ -1,7 +1,8 @@ export { DataLoader, InMemoryEventsRegistry, - InMemoryStrategyRegistry, + InMemoryCachedStrategyRegistry, + DatabaseStrategyRegistry, Orchestrator, } from "./internal.js"; diff --git a/packages/data-flow/src/registries/index.ts b/packages/data-flow/src/registries/index.ts index 3431897..c6319bf 100644 --- a/packages/data-flow/src/registries/index.ts +++ b/packages/data-flow/src/registries/index.ts @@ -1,3 +1 @@ -export * from "./cachedStrategyRegistry.js"; -export * from "./dbStrategyRegistry.js"; -export * from "./strategyRegistry.js"; +export * from "./strategy/index.js"; diff --git a/packages/data-flow/src/registries/cachedStrategyRegistry.ts b/packages/data-flow/src/registries/strategy/cachedStrategyRegistry.ts similarity index 83% rename from packages/data-flow/src/registries/cachedStrategyRegistry.ts rename to packages/data-flow/src/registries/strategy/cachedStrategyRegistry.ts index 2babeac..c89c9f9 100644 --- a/packages/data-flow/src/registries/cachedStrategyRegistry.ts +++ b/packages/data-flow/src/registries/strategy/cachedStrategyRegistry.ts @@ -1,7 +1,7 @@ import { Strategy } from "@grants-stack-indexer/repository"; import { Address, ChainId, Hex, ILogger } from "@grants-stack-indexer/shared"; -import { IStrategyRegistry } from "../internal.js"; +import { IStrategyRegistry } from "../../internal.js"; /** * Proxy class to cache the strategy ids in memory or fallback to another strategy registry @@ -17,10 +17,19 @@ export class InMemoryCachedStrategyRegistry implements IStrategyRegistry { this.cache = structuredClone(cache); } + /** @inheritdoc */ async getStrategies(params?: { handled?: boolean; chainId?: ChainId }): Promise { return this.strategyRegistry.getStrategies(params); } + /** + * Creates a new cached strategy registry instance. It will load the strategies into memory and cache them and + * fallback to the strategy registry if the strategy is not found in the cache. + * + * @param logger - The logger instance + * @param strategyRegistry - The strategy registry instance + * @returns The initialized cached strategy registry + */ static async initialize( logger: ILogger, strategyRegistry: IStrategyRegistry, @@ -40,6 +49,7 @@ export class InMemoryCachedStrategyRegistry implements IStrategyRegistry { return new InMemoryCachedStrategyRegistry(logger, strategyRegistry, cache); } + /** @inheritdoc */ async getStrategyId(chainId: ChainId, strategyAddress: Address): Promise { const cache = this.cache.get(chainId)?.get(strategyAddress); if (cache) { @@ -53,6 +63,7 @@ export class InMemoryCachedStrategyRegistry implements IStrategyRegistry { return strategy; } + /** @inheritdoc */ async saveStrategyId( chainId: ChainId, strategyAddress: Address, diff --git a/packages/data-flow/src/registries/dbStrategyRegistry.ts b/packages/data-flow/src/registries/strategy/dbStrategyRegistry.ts similarity index 96% rename from packages/data-flow/src/registries/dbStrategyRegistry.ts rename to packages/data-flow/src/registries/strategy/dbStrategyRegistry.ts index 318e6be..5dcfe50 100644 --- a/packages/data-flow/src/registries/dbStrategyRegistry.ts +++ b/packages/data-flow/src/registries/strategy/dbStrategyRegistry.ts @@ -3,7 +3,7 @@ import type { Address, Hex } from "viem"; import { IStrategyRepository, Strategy } from "@grants-stack-indexer/repository"; import { ChainId, ILogger } from "@grants-stack-indexer/shared"; -import { IStrategyRegistry } from "../internal.js"; +import { IStrategyRegistry } from "../../internal.js"; /** * Class to store strategy ids in Database diff --git a/packages/data-flow/src/registries/strategy/index.ts b/packages/data-flow/src/registries/strategy/index.ts new file mode 100644 index 0000000..8ab6469 --- /dev/null +++ b/packages/data-flow/src/registries/strategy/index.ts @@ -0,0 +1,2 @@ +export * from "./cachedStrategyRegistry.js"; +export * from "./dbStrategyRegistry.js"; diff --git a/packages/data-flow/src/registries/strategyRegistry.ts b/packages/data-flow/src/registries/strategyRegistry.ts deleted file mode 100644 index 1ff55cf..0000000 --- a/packages/data-flow/src/registries/strategyRegistry.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { Address, Hex } from "viem"; - -import { Strategy } from "@grants-stack-indexer/repository"; -import { ChainId, ILogger } from "@grants-stack-indexer/shared"; - -import type { IStrategyRegistry } from "../internal.js"; - -/** - * Class to store strategy ids in memory - */ -export class InMemoryStrategyRegistry implements IStrategyRegistry { - private strategiesMap: Map> = new Map(); - constructor(private logger: ILogger) {} - - /** @inheritdoc */ - async getStrategies(params?: { handled?: boolean; chainId?: ChainId }): Promise { - return Array.from(this.strategiesMap.entries()) - .filter(([chainId]) => params?.chainId === undefined || chainId === params.chainId) - .map(([chainId, strategies]) => - Array.from(strategies.entries()) - .filter( - ([_address, strategy]) => - params?.handled === undefined || strategy.handled === params.handled, - ) - .map(([address, strategy]) => ({ - id: strategy.id, - address, - chainId, - handled: strategy.handled, - })), - ) - .flat(); - } - - /** @inheritdoc */ - async getStrategyId(chainId: ChainId, strategyAddress: Address): Promise { - return this.strategiesMap.get(chainId)?.get(strategyAddress); - } - - /** @inheritdoc */ - async saveStrategyId( - chainId: ChainId, - strategyAddress: Address, - strategyId: Hex, - handled: boolean, - ): Promise { - this.logger.debug(`Saving strategy id ${strategyId} for address ${strategyAddress}`); - if (!this.strategiesMap.has(chainId)) { - this.strategiesMap.set(chainId, new Map()); - } - this.strategiesMap.get(chainId)!.set(strategyAddress, { - address: strategyAddress, - id: strategyId, - chainId, - handled, - }); - } -} diff --git a/packages/data-flow/test/registries/cachedStrategyRegistry.spec.ts b/packages/data-flow/test/registries/cachedStrategyRegistry.spec.ts index 7829786..d3edecb 100644 --- a/packages/data-flow/test/registries/cachedStrategyRegistry.spec.ts +++ b/packages/data-flow/test/registries/cachedStrategyRegistry.spec.ts @@ -5,7 +5,7 @@ import { Strategy } from "@grants-stack-indexer/repository"; import { ChainId, ILogger } from "@grants-stack-indexer/shared"; import { IStrategyRegistry } from "../../src/internal.js"; -import { InMemoryCachedStrategyRegistry } from "../../src/registries/cachedStrategyRegistry.js"; +import { InMemoryCachedStrategyRegistry } from "../../src/registries/strategy/cachedStrategyRegistry.js"; describe("InMemoryCachedStrategyRegistry", () => { const logger: ILogger = { diff --git a/packages/data-flow/test/registries/dbStrategyRegistry.spec.ts b/packages/data-flow/test/registries/dbStrategyRegistry.spec.ts index d782444..c80fa93 100644 --- a/packages/data-flow/test/registries/dbStrategyRegistry.spec.ts +++ b/packages/data-flow/test/registries/dbStrategyRegistry.spec.ts @@ -4,7 +4,7 @@ import { describe, expect, it, vi } from "vitest"; import { IStrategyRepository, Strategy } from "@grants-stack-indexer/repository"; import { ChainId, ILogger } from "@grants-stack-indexer/shared"; -import { DatabaseStrategyRegistry } from "../../src/registries/dbStrategyRegistry.js"; +import { DatabaseStrategyRegistry } from "../../src/registries/strategy/dbStrategyRegistry.js"; describe("DatabaseStrategyRegistry", () => { const logger: ILogger = { diff --git a/packages/data-flow/test/registries/strategyRegistry.spec.ts b/packages/data-flow/test/registries/strategyRegistry.spec.ts deleted file mode 100644 index 80f3c2f..0000000 --- a/packages/data-flow/test/registries/strategyRegistry.spec.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { Address, Hex } from "viem"; -import { describe, expect, it, vi } from "vitest"; - -import { ChainId, ILogger } from "@grants-stack-indexer/shared"; - -import { InMemoryStrategyRegistry } from "../../src/registries/strategyRegistry.js"; - -describe("InMemoryStrategyRegistry", () => { - const logger: ILogger = { - debug: vi.fn(), - error: vi.fn(), - info: vi.fn(), - warn: vi.fn(), - }; - const chainId = 1 as ChainId; - - it("return undefined for non-existent strategy address", async () => { - const registry = new InMemoryStrategyRegistry(logger); - const strategyAddress = "0x123" as Address; - - const strategyId = await registry.getStrategyId(chainId, strategyAddress); - expect(strategyId).toBeUndefined(); - }); - - it("save and retrieve strategy id", async () => { - const registry = new InMemoryStrategyRegistry(logger); - const strategyAddress = "0x123" as Address; - const strategyId = "0xabc" as Hex; - - await registry.saveStrategyId(chainId, strategyAddress, strategyId, true); - const retrieved = await registry.getStrategyId(chainId, strategyAddress); - - expect(retrieved).toEqual({ - id: strategyId, - address: strategyAddress, - chainId, - handled: true, - }); - }); - - it("handle multiple strategy addresses independently", async () => { - const registry = new InMemoryStrategyRegistry(logger); - const firstAddress = "0x123" as Address; - const secondAddress = "0x456" as Address; - const firstStrategyId = "0xabc" as Hex; - const secondStrategyId = "0xdef" as Hex; - - await registry.saveStrategyId(chainId, firstAddress, firstStrategyId, true); - await registry.saveStrategyId(chainId, secondAddress, secondStrategyId, true); - - const retrievedFirst = await registry.getStrategyId(chainId, firstAddress); - const retrievedSecond = await registry.getStrategyId(chainId, secondAddress); - - expect(retrievedFirst).toEqual({ - id: firstStrategyId, - address: firstAddress, - chainId, - handled: true, - }); - expect(retrievedSecond).toEqual({ - id: secondStrategyId, - address: secondAddress, - chainId, - handled: true, - }); - }); - - it("get all strategies without filters", async () => { - const registry = new InMemoryStrategyRegistry(logger); - const firstChainId = 1 as ChainId; - const secondChainId = 5 as ChainId; - - // Add strategies to different chains with different handled status - await registry.saveStrategyId(firstChainId, "0x123" as Address, "0xabc" as Hex, true); - await registry.saveStrategyId(firstChainId, "0x456" as Address, "0xdef" as Hex, false); - await registry.saveStrategyId(secondChainId, "0x789" as Address, "0xghi" as Hex, true); - - const strategies = await registry.getStrategies(); - expect(strategies).toHaveLength(3); - expect(strategies).toEqual( - expect.arrayContaining([ - { - id: "0xabc" as Hex, - address: "0x123" as Address, - chainId: firstChainId, - handled: true, - }, - { - id: "0xdef" as Hex, - address: "0x456" as Address, - chainId: firstChainId, - handled: false, - }, - { - id: "0xghi" as Hex, - address: "0x789" as Address, - chainId: secondChainId, - handled: true, - }, - ]), - ); - }); - - it("filter strategies by chainId", async () => { - const registry = new InMemoryStrategyRegistry(logger); - const firstChainId = 1 as ChainId; - const secondChainId = 5 as ChainId; - - await registry.saveStrategyId(firstChainId, "0x123" as Address, "0xabc" as Hex, true); - await registry.saveStrategyId(secondChainId, "0x456" as Address, "0xdef" as Hex, true); - - const strategies = await registry.getStrategies({ chainId: firstChainId }); - expect(strategies).toHaveLength(1); - expect(strategies[0]).toEqual({ - id: "0xabc" as Hex, - address: "0x123" as Address, - chainId: firstChainId, - handled: true, - }); - }); - - it("filter strategies by handled status", async () => { - const registry = new InMemoryStrategyRegistry(logger); - const chainId = 1 as ChainId; - - await registry.saveStrategyId(chainId, "0x123" as Address, "0xabc" as Hex, true); - await registry.saveStrategyId(chainId, "0x456" as Address, "0xdef" as Hex, false); - - const handledStrategies = await registry.getStrategies({ handled: true }); - expect(handledStrategies).toHaveLength(1); - expect(handledStrategies[0]).toEqual({ - id: "0xabc" as Hex, - address: "0x123" as Address, - chainId, - handled: true, - }); - - const unhandledStrategies = await registry.getStrategies({ handled: false }); - expect(unhandledStrategies).toHaveLength(1); - expect(unhandledStrategies[0]).toEqual({ - id: "0xdef" as Hex, - address: "0x456" as Address, - chainId, - handled: false, - }); - }); - - it("filter strategies by both chainId and handled status", async () => { - const registry = new InMemoryStrategyRegistry(logger); - const firstChainId = 1 as ChainId; - const secondChainId = 5 as ChainId; - - // Add mix of strategies with different chains and handled status - await registry.saveStrategyId(firstChainId, "0x123" as Address, "0xabc" as Hex, true); - await registry.saveStrategyId(firstChainId, "0x456" as Address, "0xdef" as Hex, false); - await registry.saveStrategyId(secondChainId, "0x789" as Address, "0xghi" as Hex, true); - - const strategies = await registry.getStrategies({ - chainId: firstChainId, - handled: true, - }); - - expect(strategies).toHaveLength(1); - expect(strategies[0]).toEqual({ - id: "0xabc" as Hex, - address: "0x123" as Address, - chainId: firstChainId, - handled: true, - }); - }); -}); diff --git a/packages/repository/src/interfaces/strategyRepository.interface.ts b/packages/repository/src/interfaces/strategyRepository.interface.ts index e5332f9..b9aa195 100644 --- a/packages/repository/src/interfaces/strategyRepository.interface.ts +++ b/packages/repository/src/interfaces/strategyRepository.interface.ts @@ -3,10 +3,29 @@ import { Address, ChainId } from "@grants-stack-indexer/shared"; import { Strategy } from "../internal.js"; export interface IStrategyRepository { + /** + * Retrieves a strategy by its chain ID and address. + * @param chainId - The chain ID of the strategy. + * @param strategyAddress - The address of the strategy. + * @returns A promise that resolves to the strategy object or undefined if not found. + */ getStrategyByChainIdAndAddress( chainId: ChainId, strategyAddress: Address, ): Promise; + + /** + * Saves a strategy to the repository. + * @param strategy - The strategy to save. + */ saveStrategy(strategy: Strategy): Promise; + + /** + * Retrieves all strategies from the repository. + * @param params - The parameters to filter the strategies. + * @param params.handled - Whether to include handled strategies. + * @param params.chainId - The chain ID to filter the strategies. + * @returns A promise that resolves to an array of strategies. + */ getStrategies(params?: { handled?: boolean; chainId?: ChainId }): Promise; } diff --git a/packages/repository/src/repositories/kysely/strategy.repository.ts b/packages/repository/src/repositories/kysely/strategy.repository.ts index e6cb91c..d8a6124 100644 --- a/packages/repository/src/repositories/kysely/strategy.repository.ts +++ b/packages/repository/src/repositories/kysely/strategy.repository.ts @@ -11,6 +11,7 @@ export class KyselyStrategyRepository implements IStrategyRepository { private readonly schemaName: string, ) {} + /** @inheritdoc */ async getStrategyByChainIdAndAddress( chainId: ChainId, strategyAddress: Address, @@ -23,6 +24,8 @@ export class KyselyStrategyRepository implements IStrategyRepository { .selectAll() .executeTakeFirst(); } + + /** @inheritdoc */ async saveStrategy(strategy: Strategy): Promise { await this.db .withSchema(this.schemaName) diff --git a/scripts/migrations/src/migrations/20241210T175001_strategy_registry.ts b/scripts/migrations/src/migrations/20241210T175001_strategy_registry.ts index 85595e2..45a5936 100644 --- a/scripts/migrations/src/migrations/20241210T175001_strategy_registry.ts +++ b/scripts/migrations/src/migrations/20241210T175001_strategy_registry.ts @@ -1,7 +1,5 @@ import { Kysely } from "kysely"; -import { getSchemaName } from "../utils/index.js"; - /** * The up function is called when you update your database schema to the next version and down when you go back to previous version. * The only argument for the functions is an instance of Kysely. It's important to use Kysely and not Kysely. @@ -12,10 +10,6 @@ export async function up(db: Kysely): Promise { const ADDRESS_TYPE = "text"; const CHAIN_ID_TYPE = "integer"; - const schema = getSchemaName(db.schema); - - console.log("schema", schema); - await db.schema .createTable("strategies") .addColumn("address", ADDRESS_TYPE)