fixed libs ready for new data-injection
This commit is contained in:
parent
c5a114d544
commit
8405f44bd9
25 changed files with 277 additions and 241 deletions
|
|
@ -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> = {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
"dependencies": {
|
||||
"@stock-bot/config": "workspace:*",
|
||||
"@stock-bot/logger": "workspace:*",
|
||||
"@stock-bot/types": "workspace:*",
|
||||
"@stock-bot/di": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
111
libs/core/types/src/handler-registry.ts
Normal file
111
libs/core/types/src/handler-registry.ts
Normal 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();
|
||||
83
libs/core/types/src/handlers.ts
Normal file
83
libs/core/types/src/handlers.ts
Normal 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);
|
||||
};
|
||||
}
|
||||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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": "*"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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}`);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue