Files
outline/server/queues/processors/BaseProcessor.ts
T
Tom Moor 0c0facc2a1 perf: Avoid empty webhook processor work via cached subscription lookup (#12593)
* Avoid empty webhook processor work via cached subscription lookup

WebhookProcessor ran for every event but most teams have no matching
webhook subscription, costing an empty processor job and a database query
per event.

Cache a team's enabled subscriptions ({ id, events }) in Redis, invalidated
by model lifecycle hooks, and add an optional BaseProcessor.shouldQueue hook
consulted by the global event queue so the webhook processor only enqueues a
job when a matching subscription exists.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feedback

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 17:53:40 -04:00

42 lines
1.4 KiB
TypeScript

import type { Event } from "@server/types";
export default abstract class BaseProcessor {
/**
* The event names this processor handles. The global event queue only creates
* a job for the processor when an event's name is listed here, or when it
* contains the `"*"` wildcard to match every event.
*/
static applicableEvents: (Event["name"] | "*")[] = [];
/**
* Optional hook run in the global event queue before a job is created for this
* processor. Implement it to cheaply opt out of events the processor will not
* act on and avoid the cost of an empty job. When omitted, every applicable
* event is queued.
*
* @param event The event about to be queued.
* @returns true if a job should be queued for this processor.
*/
static shouldQueue?: (event: Event) => Promise<boolean>;
/**
* Handle an applicable event. Called once per queued job, with retries on
* failure.
*
* @param event The event to process.
* @returns A promise that resolves once the event has been processed.
*/
public abstract perform(event: Event): Promise<void>;
/**
* Handle failure when all attempts are exhausted for the processor.
*
* @param event processor event
* @returns A promise that resolves once the processor handles the failure.
*/
// oxlint-disable-next-line @typescript-eslint/no-unused-vars
public onFailed(event: Event): Promise<void> {
return Promise.resolve();
}
}