dependency hell fixes

This commit is contained in:
Boki 2025-06-23 19:07:17 -04:00
parent 50e5b5cbed
commit 24768446f5
20 changed files with 219 additions and 197 deletions

View file

@ -1,13 +1,11 @@
import type { Collection } from 'mongodb';
import { getLogger } from '@stock-bot/logger';
import {
createJobHandler,
handlerRegistry,
type HandlerConfigWithSchedule,
} from '@stock-bot/types';
import type { HandlerConfigWithSchedule } from '@stock-bot/types';
import { fetch } from '@stock-bot/utils';
import { createNamespacedCache } from '@stock-bot/cache';
import type { IServiceContainer } from '../types/service-container';
import type { IServiceContainer } from '@stock-bot/types';
import { handlerRegistry } from '../registry/handler-registry';
import { createJobHandler } from '../utils/create-job-handler';
import type { ExecutionContext, IHandler } from '../types/types';
/**

View file

@ -2,8 +2,11 @@
export { BaseHandler, ScheduledHandler } from './base/BaseHandler';
export type { JobScheduleOptions } from './base/BaseHandler';
// Handler registry (re-exported from types to avoid circular deps)
export { handlerRegistry } from '@stock-bot/types';
// Handler registry
export { handlerRegistry } from './registry/handler-registry';
// Utilities
export { createJobHandler } from './utils/create-job-handler';
// Types
export type {
@ -18,9 +21,8 @@ export type {
OperationMetadata,
} from './types/types';
export type { IServiceContainer } from './types/service-container';
export { createJobHandler } from './types/types';
// Re-export IServiceContainer from types package
export type { IServiceContainer } from '@stock-bot/types';
// Decorators
export {

View file

@ -7,7 +7,7 @@ import { readdirSync, statSync } from 'fs';
import { join, relative } from 'path';
import { getLogger } from '@stock-bot/logger';
import { BaseHandler } from '../base/BaseHandler';
import type { IServiceContainer } from '../types/service-container';
import type { IServiceContainer } from '@stock-bot/types';
const logger = getLogger('handler-auto-register');

View file

@ -0,0 +1,143 @@
/**
* Handler Registry - Runtime registry for queue handlers
* Properly located in handlers package instead of types
*/
import type {
HandlerConfig,
HandlerConfigWithSchedule,
JobHandler,
ScheduledJob,
} from '@stock-bot/types';
import { getLogger } from '@stock-bot/logger';
class HandlerRegistry {
private readonly logger = getLogger('handler-registry');
private handlers = new Map<string, HandlerConfig>();
private handlerSchedules = new Map<string, ScheduledJob[]>();
/**
* Register a handler with its operations (simple config)
*/
register(handlerName: string, config: HandlerConfig): void {
this.logger.info(`Registering handler: ${handlerName}`, {
operations: Object.keys(config),
});
this.handlers.set(handlerName, config);
}
/**
* Register a handler with scheduled jobs (enhanced config)
*/
registerWithSchedule(config: HandlerConfigWithSchedule): void {
this.logger.info(`Registering handler with schedule: ${config.name}`, {
operations: Object.keys(config.operations),
scheduledJobs: config.scheduledJobs?.length || 0,
});
this.handlers.set(config.name, config.operations);
if (config.scheduledJobs && config.scheduledJobs.length > 0) {
this.handlerSchedules.set(config.name, config.scheduledJobs);
}
}
/**
* Get a specific handler's configuration
*/
getHandler(handlerName: string): HandlerConfig | undefined {
return this.handlers.get(handlerName);
}
/**
* Get all registered handlers
*/
getAllHandlers(): Map<string, HandlerConfig> {
return new Map(this.handlers);
}
/**
* Get scheduled jobs for a handler
*/
getScheduledJobs(handlerName: string): ScheduledJob[] {
return this.handlerSchedules.get(handlerName) || [];
}
/**
* Get all handlers with their scheduled jobs
*/
getAllHandlersWithSchedule(): Map<
string,
{ operations: HandlerConfig; scheduledJobs: ScheduledJob[] }
> {
const result = new Map<string, { operations: HandlerConfig; scheduledJobs: ScheduledJob[] }>();
for (const [name, operations] of this.handlers) {
result.set(name, {
operations,
scheduledJobs: this.handlerSchedules.get(name) || [],
});
}
return result;
}
/**
* Get a specific operation from a handler
*/
getOperation(handlerName: string, operationName: string): JobHandler | undefined {
const handler = this.handlers.get(handlerName);
if (!handler) {
return undefined;
}
return handler[operationName];
}
/**
* Check if a handler is registered
*/
hasHandler(handlerName: string): boolean {
return this.handlers.has(handlerName);
}
/**
* Get list of all registered handler names
*/
getHandlerNames(): string[] {
return Array.from(this.handlers.keys());
}
/**
* Get registry statistics
*/
getStats(): { handlers: number; operations: number; scheduledJobs: number } {
let operationCount = 0;
let scheduledJobCount = 0;
for (const [_, config] of this.handlers) {
operationCount += Object.keys(config).length;
}
for (const [_, jobs] of this.handlerSchedules) {
scheduledJobCount += jobs.length;
}
return {
handlers: this.handlers.size,
operations: operationCount,
scheduledJobs: scheduledJobCount,
};
}
/**
* Clear all registrations (useful for testing)
*/
clear(): void {
this.handlers.clear();
this.handlerSchedules.clear();
}
}
// Export singleton instance
export const handlerRegistry = new HandlerRegistry();

View file

@ -1,28 +0,0 @@
/**
* Universal Service Container for Handlers
* Simple, comprehensive container with all services available
*/
import type { ProxyManager } from '@stock-bot/proxy';
/**
* Universal service container with all common services
* Designed to work across different service contexts (data-ingestion, processing, etc.)
*/
export interface IServiceContainer {
// Core infrastructure
readonly logger: any; // Logger instance
readonly cache?: any; // Cache provider (Redis/Dragonfly) - optional
readonly globalCache?: any; // Global cache provider (shared across services) - optional
readonly queue?: any; // Queue manager (BullMQ) - optional
readonly proxy?: ProxyManager; // Proxy manager service - optional (depends on cache)
readonly browser?: any; // Browser automation (Playwright)
// Database clients - all optional to support selective enabling
readonly mongodb?: any; // MongoDB client
readonly postgres?: any; // PostgreSQL client
readonly questdb?: any; // QuestDB client (time-series)
// Optional extensions for future use
readonly custom?: Record<string, any>;
}

View file

@ -10,5 +10,3 @@ export type {
ScheduledJob,
TypedJobHandler,
} from '@stock-bot/types';
export { createJobHandler } from '@stock-bot/types';

View file

@ -0,0 +1,16 @@
/**
* Utility for creating typed job handlers
*/
import type { JobHandler, TypedJobHandler } from '@stock-bot/types';
/**
* Create a typed job handler with validation
*/
export function createJobHandler<TPayload = unknown, TResult = unknown>(
handler: TypedJobHandler<TPayload, TResult>
): JobHandler<unknown, TResult> {
return async (payload: unknown): Promise<TResult> => {
return handler(payload as TPayload);
};
}