handler to auto register and removed service registry, cleaned up queues and cache naming

This commit is contained in:
Boki 2025-06-23 21:23:38 -04:00
parent 0d1be9e3cb
commit 34c6c36695
19 changed files with 474 additions and 198 deletions

View file

@ -159,7 +159,7 @@ export abstract class BaseHandler implements IHandler {
/**
* Create a sub-namespaced cache for specific operations
* Example: handler 'webshare' creates namespace 'webshare:api' -> keys will be 'cache:webshare:api:*'
* Example: handler 'webshare' creates namespace 'webshare:api' -> keys will be 'cache:data-ingestion:webshare:api:*'
*/
protected createNamespacedCache(subNamespace: string) {
return createNamespacedCache(this.cache, `${this.handlerName}:${subNamespace}`);
@ -172,7 +172,8 @@ export abstract class BaseHandler implements IHandler {
if (!this.cache) {
return;
}
return this.cache.set(`cache:${this.handlerName}:${key}`, value, ttl);
// Don't add 'cache:' prefix since the cache already has its own prefix
return this.cache.set(`${this.handlerName}:${key}`, value, ttl);
}
/**
@ -182,7 +183,8 @@ export abstract class BaseHandler implements IHandler {
if (!this.cache) {
return null;
}
return this.cache.get(`cache:${this.handlerName}:${key}`);
// Don't add 'cache:' prefix since the cache already has its own prefix
return this.cache.get(`${this.handlerName}:${key}`);
}
/**
@ -192,7 +194,8 @@ export abstract class BaseHandler implements IHandler {
if (!this.cache) {
return;
}
return this.cache.del(`cache:${this.handlerName}:${key}`);
// Don't add 'cache:' prefix since the cache already has its own prefix
return this.cache.del(`${this.handlerName}:${key}`);
}
/**
@ -294,7 +297,7 @@ export abstract class BaseHandler implements IHandler {
* Register this handler using decorator metadata
* Automatically reads @Handler, @Operation, and @QueueSchedule decorators
*/
register(): void {
register(serviceName?: string): void {
const constructor = this.constructor as any;
const handlerName = constructor.__handlerName || this.handlerName;
const operations = constructor.__operations || [];
@ -333,9 +336,10 @@ export abstract class BaseHandler implements IHandler {
scheduledJobs,
};
handlerRegistry.registerWithSchedule(config);
handlerRegistry.registerWithSchedule(config, serviceName);
this.logger.info('Handler registered using decorator metadata', {
handlerName,
service: serviceName,
operations: operations.map((op: any) => ({ name: op.name, method: op.method })),
scheduledJobs: scheduledJobs.map((job: any) => ({
operation: job.operation,

View file

@ -73,9 +73,10 @@ export async function autoRegisterHandlers(
pattern?: string;
exclude?: string[];
dryRun?: boolean;
serviceName?: string;
} = {}
): Promise<{ registered: string[]; failed: string[] }> {
const { pattern = '.handler.', exclude = [], dryRun = false } = options;
const { pattern = '.handler.', exclude = [], dryRun = false, serviceName } = options;
const registered: string[] = [];
const failed: string[] = [];
@ -124,10 +125,12 @@ export async function autoRegisterHandlers(
// Create instance and register
const handler = new HandlerClass(services);
handler.register();
handler.register(serviceName);
// No need to set service ownership separately - it's done in register()
registered.push(handlerName);
logger.info(`Successfully registered handler: ${handlerName}`);
logger.info(`Successfully registered handler: ${handlerName}`, { service: serviceName });
}
}
} catch (error) {

View file

@ -15,25 +15,33 @@ class HandlerRegistry {
private readonly logger = getLogger('handler-registry');
private handlers = new Map<string, HandlerConfig>();
private handlerSchedules = new Map<string, ScheduledJob[]>();
private handlerServices = new Map<string, string>(); // Maps handler to service name
/**
* Register a handler with its operations (simple config)
*/
register(handlerName: string, config: HandlerConfig): void {
register(handlerName: string, config: HandlerConfig, serviceName?: string): void {
this.logger.info(`Registering handler: ${handlerName}`, {
operations: Object.keys(config),
service: serviceName,
});
this.handlers.set(handlerName, config);
// Track service ownership if provided
if (serviceName) {
this.handlerServices.set(handlerName, serviceName);
}
}
/**
* Register a handler with scheduled jobs (enhanced config)
*/
registerWithSchedule(config: HandlerConfigWithSchedule): void {
registerWithSchedule(config: HandlerConfigWithSchedule, serviceName?: string): void {
this.logger.info(`Registering handler with schedule: ${config.name}`, {
operations: Object.keys(config.operations),
scheduledJobs: config.scheduledJobs?.length || 0,
service: serviceName,
});
this.handlers.set(config.name, config.operations);
@ -41,6 +49,11 @@ class HandlerRegistry {
if (config.scheduledJobs && config.scheduledJobs.length > 0) {
this.handlerSchedules.set(config.name, config.scheduledJobs);
}
// Track service ownership if provided
if (serviceName) {
this.handlerServices.set(config.name, serviceName);
}
}
/**
@ -130,12 +143,40 @@ class HandlerRegistry {
};
}
/**
* Get the service that owns a handler
*/
getHandlerService(handlerName: string): string | undefined {
return this.handlerServices.get(handlerName);
}
/**
* Get all handlers for a specific service
*/
getServiceHandlers(serviceName: string): string[] {
const handlers: string[] = [];
for (const [handler, service] of this.handlerServices) {
if (service === serviceName) {
handlers.push(handler);
}
}
return handlers;
}
/**
* Set service ownership for a handler (used during auto-discovery)
*/
setHandlerService(handlerName: string, serviceName: string): void {
this.handlerServices.set(handlerName, serviceName);
}
/**
* Clear all registrations (useful for testing)
*/
clear(): void {
this.handlers.clear();
this.handlerSchedules.clear();
this.handlerServices.clear();
}
}