fixed libs ready for new data-injection

This commit is contained in:
Boki 2025-06-21 20:38:16 -04:00
parent c5a114d544
commit 8405f44bd9
25 changed files with 277 additions and 241 deletions

View file

@ -208,11 +208,14 @@ export class ConnectionFactory implements IConnectionFactory {
const manager = QueueManager.initialize({
redis: poolConfig.config as any,
defaultQueueOptions: {
workers: 2, // Default number of workers per queue
concurrency: 1, // Jobs processed concurrently per worker
defaultJobOptions: {
removeOnComplete: 100,
removeOnFail: 50,
},
},
delayWorkerStart: false, // Start workers immediately when queues are created
});
const pool: ConnectionPool<any> = {

View file

@ -12,6 +12,7 @@
"dependencies": {
"@stock-bot/config": "workspace:*",
"@stock-bot/logger": "workspace:*",
"@stock-bot/types": "workspace:*",
"@stock-bot/di": "workspace:*"
},
"devDependencies": {

View file

@ -1,8 +1,8 @@
// Base handler classes
export { BaseHandler, ScheduledHandler } from './base/BaseHandler';
// Handler registry
export { handlerRegistry } from './registry/HandlerRegistry';
// Handler registry (re-exported from types to avoid circular deps)
export { handlerRegistry } from '@stock-bot/types';
// Types
export type {

View file

@ -1,73 +1,14 @@
import type { ServiceContainer } from '@stock-bot/di';
// Re-export all handler types from the shared types package
export type {
ExecutionContext,
HandlerConfig,
HandlerConfigWithSchedule,
HandlerMetadata,
IHandler,
JobHandler,
OperationMetadata,
ScheduledJob,
TypedJobHandler,
} from '@stock-bot/types';
// Simple execution context - mostly queue for now
export interface ExecutionContext {
type: 'queue'; // | 'event' - commented for future
serviceContainer: ServiceContainer;
metadata: {
source?: string;
jobId?: string;
attempts?: number;
timestamp: number;
[key: string]: unknown;
};
}
// Simple handler interface
export interface IHandler {
execute(operation: string, input: unknown, context: ExecutionContext): Promise<unknown>;
}
// Job handler type for queue operations
export interface JobHandler<TPayload = unknown, TResult = unknown> {
(payload: TPayload): Promise<TResult>;
}
// Scheduled job configuration
export interface ScheduledJob<T = unknown> {
type: string;
operation: string;
payload?: T;
cronPattern: string;
priority?: number;
description?: string;
immediately?: boolean;
delay?: number;
}
// Handler configuration
export interface HandlerConfig {
[operation: string]: JobHandler;
}
// Handler configuration with schedule
export interface HandlerConfigWithSchedule {
name: string;
operations: Record<string, JobHandler>;
scheduledJobs?: ScheduledJob[];
}
// Type-safe wrapper for creating job handlers
export type TypedJobHandler<TPayload, TResult = unknown> = (payload: TPayload) => Promise<TResult>;
// Helper to create type-safe job handlers
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);
};
}
// Handler metadata for decorators (future)
export interface HandlerMetadata {
name: string;
operations: OperationMetadata[];
}
export interface OperationMetadata {
name: string;
schedules?: string[];
// eventListeners?: string[]; // Future
// eventPublishers?: string[]; // Future
}
export { createJobHandler } from '@stock-bot/types';

View file

@ -0,0 +1,111 @@
/**
* Handler Registry - Lightweight registry for queue handlers
* Moved here to avoid circular dependencies between handlers and queue
*/
import type { JobHandler, HandlerConfig, HandlerConfigWithSchedule, ScheduledJob } from './handlers';
class HandlerRegistry {
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 {
console.log(`Registering handler: ${handlerName}`, {
operations: Object.keys(config),
});
this.handlers.set(handlerName, config);
}
/**
* Register a handler with scheduled jobs (enhanced config)
*/
registerWithSchedule(config: HandlerConfigWithSchedule): void {
console.log(`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());
}
/**
* Clear all registrations (useful for testing)
*/
clear(): void {
this.handlers.clear();
this.handlerSchedules.clear();
}
}
// Export singleton instance
export const handlerRegistry = new HandlerRegistry();

View file

@ -0,0 +1,83 @@
/**
* Handler and Queue Types
* Shared types for handler system and queue operations
*/
// Simple execution context - mostly queue for now
export interface ExecutionContext {
type: 'queue'; // | 'event' - commented for future
serviceContainer?: any; // Will be typed properly when needed
metadata: {
source?: string;
jobId?: string;
attempts?: number;
timestamp: number;
[key: string]: unknown;
};
}
// Simple handler interface
export interface IHandler {
execute(operation: string, input: unknown, context: ExecutionContext): Promise<unknown>;
}
// Job handler type for queue operations
export interface JobHandler<TPayload = unknown, TResult = unknown> {
(payload: TPayload): Promise<TResult>;
}
// Type-safe wrapper for creating job handlers
export type TypedJobHandler<TPayload, TResult = unknown> = (payload: TPayload) => Promise<TResult>;
// Scheduled job configuration
export interface ScheduledJob<T = unknown> {
type: string;
operation: string;
payload?: T;
cronPattern: string;
priority?: number;
description?: string;
immediately?: boolean;
delay?: number;
}
// Handler configuration
export interface HandlerConfig {
[operation: string]: JobHandler;
}
// Handler configuration with schedule
export interface HandlerConfigWithSchedule {
name: string;
operations: Record<string, JobHandler>;
scheduledJobs?: ScheduledJob[];
}
// Handler metadata for registry
export interface HandlerMetadata {
name: string;
version?: string;
description?: string;
operations: string[];
scheduledJobs?: ScheduledJob[];
}
// Operation metadata for decorators
export interface OperationMetadata {
name: string;
schedules?: string[];
operation?: string;
description?: string;
validation?: (input: unknown) => boolean;
}
/**
* 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);
};
}

View file

@ -47,3 +47,20 @@ export type { BacktestResults } from './backtesting';
// Export helper types
export type { HasClose, HasOHLC, HasTimestamp, HasVolume } from './helpers';
// Export handler types
export type {
ExecutionContext,
HandlerConfig,
HandlerConfigWithSchedule,
HandlerMetadata,
IHandler,
JobHandler,
OperationMetadata,
ScheduledJob,
TypedJobHandler,
} from './handlers';
export { createJobHandler } from './handlers';
// Export handler registry
export { handlerRegistry } from './handler-registry';

View file

@ -307,6 +307,14 @@ export class MongoDBClient {
return db.collection<T>(name);
}
/**
* Get a collection (interface compatibility method)
* This method provides compatibility with the IMongoDBClient interface
*/
collection(name: string, database?: string): Collection<any> {
return this.getCollection(name, database);
}
/**
* Simple insert operation
*/

View file

@ -14,7 +14,6 @@
"ioredis": "^5.3.0",
"rate-limiter-flexible": "^3.0.0",
"@stock-bot/cache": "*",
"@stock-bot/handlers": "*",
"@stock-bot/logger": "*",
"@stock-bot/types": "*"
},

View file

@ -3,8 +3,8 @@ export { Queue, type QueueWorkerConfig } from './queue';
export { QueueManager } from './queue-manager';
export { createJobHandler } from './types';
// Re-export handler registry from new location
export { handlerRegistry } from '@stock-bot/handlers';
// Re-export handler registry from types package
export { handlerRegistry } from '@stock-bot/types';
// Batch processing
export { processBatchJob, processItems } from './batch-processor';

View file

@ -442,7 +442,7 @@ export class QueueManager {
*/
startAllWorkers(): void {
if (!this.config.delayWorkerStart) {
logger.warn('startAllWorkers() called but delayWorkerStart is not enabled');
logger.info('startAllWorkers() called but workers already started automatically (delayWorkerStart is false)');
return;
}

View file

@ -1,6 +1,6 @@
import { Queue as BullQueue, QueueEvents, Worker, type Job } from 'bullmq';
import { getLogger } from '@stock-bot/logger';
import { handlerRegistry } from '@stock-bot/handlers';
import { handlerRegistry } from '@stock-bot/types';
import type { JobData, JobOptions, QueueStats, RedisConfig } from './types';
import { getRedisConnection } from './utils';
@ -309,7 +309,7 @@ export class Queue {
try {
// Look up handler in registry
const jobHandler = handlerRegistry.getHandler(handler, operation);
const jobHandler = handlerRegistry.getOperation(handler, operation);
if (!jobHandler) {
throw new Error(`No handler found for ${handler}:${operation}`);

View file

@ -1,11 +1,11 @@
// Re-export handler types from new location
// Re-export handler types from shared types package
export type {
JobHandler,
TypedJobHandler,
HandlerConfig,
HandlerConfigWithSchedule,
ScheduledJob,
} from '@stock-bot/handlers';
} from '@stock-bot/types';
// Types for queue operations
export interface JobData<T = unknown> {
@ -110,8 +110,8 @@ export interface QueueConfig extends QueueManagerConfig {
enableMetrics?: boolean;
}
// Re-export createJobHandler from handlers library
export { createJobHandler } from '@stock-bot/handlers';
// Re-export createJobHandler from shared types package
export { createJobHandler } from '@stock-bot/types';
export interface BatchJobData {
payloadKey: string;