Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: persisting strategy registry into db #40

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from

Conversation

0xnigir1
Copy link
Collaborator

@0xnigir1 0xnigir1 commented Dec 11, 2024

🤖 Linear

Closes GIT-185

Description

We want to persist strategyIds on PoolCreated events so we could later pre-process all of the past events when we implement in code a new Strategy Handler.

  • Create StrategyRepository to store seen strategyIds with their corresponding address and whether it was handled or not
  • DBStrategyRegistry that interfaces with the repo
  • a Proxied version that caches in memory and uses the DBStrategyRegistry (InMemoryCachedStrategyRegistry)
  • update Processing app to use the InMemoryCachedStrategyRegistry

Checklist before requesting a review

  • I have conducted a self-review of my code.
  • I have conducted a QA.
  • If it is a core feature, I have included comprehensive tests.

Copy link

linear bot commented Dec 11, 2024

@0xnigir1 0xnigir1 self-assigned this Dec 11, 2024
Copy link
Collaborator

@0xkenj1 0xkenj1 left a comment

Choose a reason for hiding this comment

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

GJ ser, this is a lot of work. Just small comments :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

god

DatabaseStrategyRegistry,
IEventsRegistry,
InMemoryCachedStrategyRegistry,
} from "@grants-stack-indexer/data-flow/dist/src/internal.js";
Copy link
Collaborator

Choose a reason for hiding this comment

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

is pointing to dist

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

good catch

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed: aa3ee27

@@ -13,6 +18,7 @@ import {
KyselyDonationRepository,
KyselyProjectRepository,
KyselyRoundRepository,
KyselyStrategyRepository,
Copy link
Collaborator

Choose a reason for hiding this comment

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

StrategyRegistryRepository

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Comment on lines +82 to +84
new Logger({ className: "InMemoryCachedStrategyRegistry" }),
new DatabaseStrategyRegistry(
new Logger({ className: "DatabaseStrategyRegistry" }),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am a little concerned about using multiple logger instances. I think it adds tons of overhead, think about a logger that sends logs to a server or prints all the logs into a file, for each instance you will have a connection (1st case) or a dedicated file (2nd case) correct me if iam wrong pls.

i would love to hear @0xyaco 's opinion about having multiple logger instances across the application

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

mmm i see what you're pointing, we can better discuss it on the Error handling and Logging milestone but a solution could be a Context object on each call so we know which file or chain emitted a log?


The `StrategyRegistry` stores strategy IDs to populate strategy events with them given the Strategy address.
There are 3 implementations:

- `InMemoryStrategyRegistry`: stores map in-memory
Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe we should get rid of this one since it will be no longer used and adds noise here

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

okii makes sense

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed: aa3ee27

private readonly strategyRegistry: IStrategyRegistry,
cache: Map<ChainId, Map<Address, Strategy>>,
) {
this.cache = structuredClone(cache);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Didn't know that structuredClone exist.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need to pass cache as parameter instead of having it contained in the class ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the cache is built in the static async constructor, for the class to be instantiated with the pre-filled cache elements, it needs to receive it in constructor

strategyRegistry: IStrategyRegistry,
): Promise<InMemoryCachedStrategyRegistry> {
const strategies = await strategyRegistry.getStrategies();
const cache = new Map<ChainId, Map<Address, Strategy>>();
Copy link
Collaborator

Choose a reason for hiding this comment

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

i think here is my answer xd

@@ -41,9 +37,13 @@ pnpm install
To apply all pending migrations:

```bash
pnpm script:db:migrate
pnpm db:migrate --schema=schema_name
Copy link
Collaborator

Choose a reason for hiding this comment

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

should we rollback this ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

nono, user can still name a different schema if they want (i mean i think flexibility is cool to have) but default is public schema

Comment on lines +43 to +46
Optional arguments:

- `--schema` or `-s`: Database schema name where migrations are applied. Defaults to `public`.

Copy link
Collaborator

Choose a reason for hiding this comment

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

is no longer needed right ?

@@ -57,7 +57,7 @@ This will:
To completely reset the database schema:

```bash
pnpm script:db:reset
pnpm db:reset --schema=schema_name
Copy link
Collaborator

Choose a reason for hiding this comment

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

ditto

@@ -33,6 +38,27 @@ vi.mock("@grants-stack-indexer/indexer-client", () => ({
EnvioIndexerClient: vi.fn(),
}));

// Update the mock to handle async initialization
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this a TODO?

Copy link
Collaborator Author

@0xnigir1 0xnigir1 Dec 13, 2024

Choose a reason for hiding this comment

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

not a TODO, neither a needed comment. cursor wrote it my bad

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

*/
saveStrategyId(strategyAddress: Address, strategyId: Hex): Promise<void>;
getStrategies(params?: { handled?: boolean; chainId?: ChainId }): Promise<Strategy[]>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Similar to what Kenji said might even consider having a separate filterStrategies

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

like a different method? i'm not a big fan of this approach where custom actions are mapped to specific methods. i think filters are optional conditions applied to the general case query here

this.cache = structuredClone(cache);
}

async getStrategies(params?: { handled?: boolean; chainId?: ChainId }): Promise<Strategy[]> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe consider separating this out into getAllStrategies and get filteredStrategies rather than the optional params

return strategy;
}

async saveStrategyId(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure if you need inherit docs comment in this file?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

missing yeah thanks sir

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

*/
export class InMemoryStrategyRegistry implements IStrategyRegistry {
private strategiesMap: Map<ChainId, Map<Address, Strategy>> = new Map();
constructor(private logger: ILogger) {}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be be initializing a logger/getting the instance here? 🤔

) {}

async getStrategyByChainIdAndAddress(
chainId: ChainId,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Docs for this file/inherit docs?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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


const schema = getSchemaName(db.schema);

console.log("schema", schema);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this console log intentional?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@@ -2,7 +2,6 @@ import { z } from "zod";

const dbEnvSchema = z.object({
DATABASE_URL: z.string().url(),
DATABASE_SCHEMA: z.string().min(1),
Copy link
Collaborator

Choose a reason for hiding this comment

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

If it's optional maybe could leave it in with .optional() just to validate that the user knows it's a schema name and doesn't try adding an actual schema

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this one is no longer needed, schema is now script arg not an env variable, that's the difference. no longer a secret xd

Copy link
Collaborator

@jahabeebs jahabeebs left a comment

Choose a reason for hiding this comment

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

bien

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.

3 participants