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: integrate webhooks in the indexer #114

Conversation

amateima
Copy link
Contributor

@amateima amateima commented Nov 22, 2024

  • integrate webhooks package in the indexer
  • trigger initial notification after webhook request registration using WebhookRequest queue
  • make apiKey required

Copy link

linear bot commented Nov 22, 2024

Copy link
Contributor

@james-a-morris james-a-morris left a comment

Choose a reason for hiding this comment

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

few nits + few questions. Looks great

const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
Copy link
Contributor

Choose a reason for hiding this comment

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

OOC - why did we go with fetch vs axios?

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 package was started with fetch so I went with it too. Also, I am a fan of using as few external packages as possible

Copy link
Contributor Author

Choose a reason for hiding this comment

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

axios has a nicer syntax tho...

@@ -6,7 +6,7 @@ export interface IEventProcessor {
id: string,
url: string,
params: JSONValue,
clientId?: string,
clientId: number,
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we not represent a number as a numeric string?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not sure I understand the question. This change happened because I updated the WebhookClient primary key from a string id computed by us to an incremental number managed by postgres

Copy link
Contributor

Choose a reason for hiding this comment

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

i tihnk he means its more flexible to keep this as a string and use number.toString or parseInt to convert from and to postgres

res: express.Response,
next: express.NextFunction,
) => {
try {
const parsedBody = RegistrationParams.create(req.body);
if (!req.token) {
Copy link
Contributor

Choose a reason for hiding this comment

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

If we created a local token variable const token = req.token and checked it directly then we wouldn't need to typecast below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

Copy link
Contributor

Choose a reason for hiding this comment

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

OOC what if two or more separate clients ask to send data to the same callback url?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think that's possible because we check the callback url agains the domains list from the WebhookClient and that table is managed manually by us for now

Comment on lines +34 to +37
const q = this.queues[queue];
if (q) {
await q.add(queue, message, options);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const q = this.queues[queue];
if (q) {
await q.add(queue, message, options);
}
await this.queues[queue]?.add(queue, message, options);

Copy link
Contributor

Choose a reason for hiding this comment

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

We may want to use this in multiple spots

Copy link
Contributor Author

@amateima amateima Nov 22, 2024

Choose a reason for hiding this comment

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

@james-a-morris I plan to add a warn || error log on else, that's why I used if

);
}

private async run(webhookRequestJob: WebhookRequestQueueJob) {
Copy link
Contributor

Choose a reason for hiding this comment

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

really against putting this business logic here, im happy to take a crack at refactoring this in a future pr though.
i think what id do is basically pass in the eventprocessor manager in the webhookrequestworker constructor, then assume whenever "run" is called, its a webhook registration, and call "register" on the eventprocessormanager, which will call the correct event processor and put the logic for pulling in initial state and calling webhook in there.

its a subtle change, but means that we could remove this worker if everythign resides on the same process

Copy link
Contributor Author

@amateima amateima Nov 25, 2024

Choose a reason for hiding this comment

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

I agree that this is not the best approach, but what if I place this worker in the indexer package?

put the logic for pulling in initial state and calling webhook in there.

I do feel that the write() function should be called only externally and not from the webhooks package. The package should only deal with forwarding notification payloads from our systems to clients and not dealing at all from where write() is being called. It can be procedural code, cron jobs, Bull workers, etc. wdyt?

Copy link
Contributor

Choose a reason for hiding this comment

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

we should discuss further offline, but as of now i think this is ok, we can figure out how to change later

@@ -101,7 +113,7 @@ export class EventProcessorManager {
this.logger.debug(
`Attempting to unregister webhook of type: ${params.type} with ID: ${params.id}`,
);
const webhook = this.getEventProcessor(params.type);
const webhook = this.getEventProcessor(params.type as WebhookTypes);
Copy link
Contributor

Choose a reason for hiding this comment

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

could make a function to assert this

data: event,
});
webhookRequests.map((hook) => {
const client = clientsMap[hook.clientId];
Copy link
Contributor

Choose a reason for hiding this comment

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

theres a lot of work above just to get this cache, not sure why u dont just make this function async(you are already using promise.all even though function is currently sync), and query for the client directly here, and delete all the code from 54-69

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed Promise.all(). Basically I don't want to fetch the client for each request because this will trigger many duplicated queries, so I fetch only the unique clients

@@ -6,7 +6,7 @@ export interface IEventProcessor {
id: string,
url: string,
params: JSONValue,
clientId?: string,
clientId: number,
Copy link
Contributor

Choose a reason for hiding this comment

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

i tihnk he means its more flexible to keep this as a string and use number.toString or parseInt to convert from and to postgres

@amateima amateima requested a review from daywiss November 25, 2024 14:27
@amateima amateima merged commit ae14e87 into david/acx-3360-add-persistence-to-webhooks-package Nov 25, 2024
3 checks passed
amateima added a commit that referenced this pull request Nov 26, 2024
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