modern decodators
This commit is contained in:
parent
8405f44bd9
commit
931f212ec7
6 changed files with 262 additions and 150 deletions
23
apps/data-ingestion/src/handlers/index.ts
Normal file
23
apps/data-ingestion/src/handlers/index.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Handler auto-registration
|
||||
* Import all handlers here to trigger auto-registration
|
||||
*/
|
||||
|
||||
import type { IDataIngestionServices } from '@stock-bot/di';
|
||||
import { QMHandler } from './qm/qm.handler';
|
||||
|
||||
/**
|
||||
* Initialize and register all handlers
|
||||
*/
|
||||
export function initializeAllHandlers(services: IDataIngestionServices): void {
|
||||
// QM Handler
|
||||
const qmHandler = new QMHandler(services);
|
||||
qmHandler.register();
|
||||
|
||||
// TODO: Add other handlers here as they're converted
|
||||
// const webShareHandler = new WebShareHandler(services);
|
||||
// webShareHandler.register();
|
||||
|
||||
// const ibHandler = new IBHandler(services);
|
||||
// ibHandler.register();
|
||||
}
|
||||
|
|
@ -1,32 +1,17 @@
|
|||
import type { IDataIngestionServices } from '@stock-bot/di';
|
||||
import {
|
||||
BaseHandler,
|
||||
Handler,
|
||||
Operation,
|
||||
QueueSchedule,
|
||||
type ExecutionContext,
|
||||
type HandlerConfigWithSchedule
|
||||
type ExecutionContext
|
||||
} from '@stock-bot/handlers';
|
||||
import { handlerRegistry, createJobHandler } from '@stock-bot/types';
|
||||
import type { IDataIngestionServices, IExecutionContext } from '@stock-bot/di';
|
||||
import type { SymbolSpiderJob } from './shared/types';
|
||||
|
||||
@Handler('qm')
|
||||
export class QMHandler extends BaseHandler {
|
||||
constructor(services: IDataIngestionServices) {
|
||||
super(services);
|
||||
}
|
||||
|
||||
async execute(operation: string, input: unknown, context: ExecutionContext): Promise<unknown> {
|
||||
switch (operation) {
|
||||
case 'create-sessions':
|
||||
return await this.createSessions(input, context);
|
||||
case 'search-symbols':
|
||||
return await this.searchSymbols(input, context);
|
||||
case 'spider-symbol-search':
|
||||
return await this.spiderSymbolSearch(input as SymbolSpiderJob, context);
|
||||
default:
|
||||
throw new Error(`Unknown operation: ${operation}`);
|
||||
}
|
||||
super(services); // Handler name read from @Handler decorator
|
||||
}
|
||||
|
||||
@Operation('create-sessions')
|
||||
|
|
@ -36,44 +21,69 @@ export class QMHandler extends BaseHandler {
|
|||
description: 'Create and maintain QM sessions'
|
||||
})
|
||||
async createSessions(input: unknown, context: ExecutionContext): Promise<unknown> {
|
||||
// Direct access to typed dependencies
|
||||
const sessionsCollection = this.mongodb.collection('qm_sessions');
|
||||
this.logger.info('Creating QM sessions with new DI pattern...');
|
||||
|
||||
// Get existing sessions
|
||||
const existingSessions = await sessionsCollection.find({}).toArray();
|
||||
this.logger.info('Found existing QM sessions', { count: existingSessions.length });
|
||||
|
||||
// Cache session count for monitoring
|
||||
await this.cache.set('qm-sessions-count', existingSessions.length, 3600);
|
||||
|
||||
return { success: true, existingCount: existingSessions.length };
|
||||
try {
|
||||
// Check existing sessions in MongoDB
|
||||
const sessionsCollection = this.mongodb.collection('qm_sessions');
|
||||
const existingSessions = await sessionsCollection.find({}).toArray();
|
||||
|
||||
this.logger.info('Current QM sessions', {
|
||||
existing: existingSessions.length,
|
||||
action: 'creating_new_sessions'
|
||||
});
|
||||
|
||||
// Cache session stats for monitoring
|
||||
await this.cache.set('qm-sessions-count', existingSessions.length, 3600);
|
||||
await this.cache.set('last-session-check', new Date().toISOString(), 1800);
|
||||
|
||||
// For now, just return the current state
|
||||
// TODO: Implement actual session creation logic using new DI pattern
|
||||
return {
|
||||
success: true,
|
||||
existingSessions: existingSessions.length,
|
||||
message: 'QM session check completed'
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to create QM sessions', { error });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@Operation('search-symbols')
|
||||
async searchSymbols(input: unknown, context: ExecutionContext): Promise<unknown> {
|
||||
// Direct access to typed dependencies
|
||||
const symbolsCollection = this.mongodb.collection('qm_symbols');
|
||||
|
||||
// Get symbols from database
|
||||
const symbols = await symbolsCollection.find({}).limit(100).toArray();
|
||||
this.logger.info('QM symbol search completed', { count: symbols.length });
|
||||
|
||||
if (symbols && symbols.length > 0) {
|
||||
// Cache result for performance
|
||||
await this.cache.set('qm-symbols-sample', symbols.slice(0, 10), 1800);
|
||||
async searchSymbols(_input: unknown, _context: ExecutionContext): Promise<unknown> {
|
||||
this.logger.info('Searching QM symbols with new DI pattern...');
|
||||
try {
|
||||
// Check existing symbols in MongoDB
|
||||
const symbolsCollection = this.mongodb.collection('qm_symbols');
|
||||
const symbols = await symbolsCollection.find({}).limit(100).toArray();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'QM symbol search completed successfully',
|
||||
count: symbols.length,
|
||||
symbols: symbols.slice(0, 10), // Return first 10 symbols as sample
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
message: 'No symbols found',
|
||||
count: 0,
|
||||
};
|
||||
this.logger.info('QM symbol search completed', { count: symbols.length });
|
||||
|
||||
if (symbols && symbols.length > 0) {
|
||||
// Cache result for performance
|
||||
await this.cache.set('qm-symbols-sample', symbols.slice(0, 10), 1800);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'QM symbol search completed successfully',
|
||||
count: symbols.length,
|
||||
symbols: symbols.slice(0, 10), // Return first 10 symbols as sample
|
||||
};
|
||||
} else {
|
||||
// No symbols found - this is expected initially
|
||||
this.logger.info('No QM symbols found in database yet');
|
||||
return {
|
||||
success: true,
|
||||
message: 'No symbols found yet - database is empty',
|
||||
count: 0,
|
||||
};
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to search QM symbols', { error });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,57 +118,19 @@ export class QMHandler extends BaseHandler {
|
|||
spiderJobId
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide payloads for scheduled jobs
|
||||
*/
|
||||
protected getScheduledJobPayload(operation: string): any {
|
||||
if (operation === 'spiderSymbolSearch') {
|
||||
return {
|
||||
prefix: null,
|
||||
depth: 1,
|
||||
source: 'qm',
|
||||
maxDepth: 4
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize and register the QM provider with new DI pattern
|
||||
export function initializeQMProviderNew(services: IDataIngestionServices) {
|
||||
// Create handler instance with new DI
|
||||
const handler = new QMHandler(services);
|
||||
|
||||
// Register with legacy format for backward compatibility
|
||||
const qmProviderConfig: HandlerConfigWithSchedule = {
|
||||
name: 'qm',
|
||||
operations: {
|
||||
'create-sessions': createJobHandler(async (payload) => {
|
||||
const context = handler.createExecutionContext('queue', { source: 'queue', timestamp: Date.now() });
|
||||
return await handler.execute('create-sessions', payload, context);
|
||||
}),
|
||||
'search-symbols': createJobHandler(async (payload) => {
|
||||
const context = handler.createExecutionContext('queue', { source: 'queue', timestamp: Date.now() });
|
||||
return await handler.execute('search-symbols', payload, context);
|
||||
}),
|
||||
'spider-symbol-search': createJobHandler(async (payload: SymbolSpiderJob) => {
|
||||
const context = handler.createExecutionContext('queue', { source: 'queue', timestamp: Date.now() });
|
||||
return await handler.execute('spider-symbol-search', payload, context);
|
||||
}),
|
||||
},
|
||||
|
||||
scheduledJobs: [
|
||||
{
|
||||
type: 'session-management',
|
||||
operation: 'create-sessions',
|
||||
cronPattern: '0 */15 * * *', // Every 15 minutes
|
||||
priority: 7,
|
||||
immediately: true,
|
||||
description: 'Create and maintain QM sessions',
|
||||
},
|
||||
{
|
||||
type: 'qm-maintnance',
|
||||
operation: 'spider-symbol-search',
|
||||
payload: {
|
||||
prefix: null,
|
||||
depth: 1,
|
||||
source: 'qm',
|
||||
maxDepth: 4
|
||||
},
|
||||
cronPattern: '0 0 * * 0', // Every Sunday at midnight
|
||||
priority: 10,
|
||||
immediately: true,
|
||||
description: 'Comprehensive symbol search using QM API',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
handlerRegistry.registerWithSchedule(qmProviderConfig);
|
||||
handler.logger.debug('QM provider registered successfully with new DI pattern');
|
||||
}
|
||||
|
|
@ -9,19 +9,19 @@ import { Hono } from 'hono';
|
|||
import { cors } from 'hono/cors';
|
||||
|
||||
// Library imports
|
||||
import {
|
||||
createDataIngestionServices,
|
||||
disposeDataIngestionServices,
|
||||
type IDataIngestionServices
|
||||
} from '@stock-bot/di';
|
||||
import { getLogger, setLoggerConfig, shutdownLoggers } from '@stock-bot/logger';
|
||||
import { Shutdown } from '@stock-bot/shutdown';
|
||||
import { ProxyManager } from '@stock-bot/utils';
|
||||
import {
|
||||
createDataIngestionServices,
|
||||
disposeDataIngestionServices,
|
||||
type IDataIngestionServices
|
||||
} from '@stock-bot/di';
|
||||
import { handlerRegistry } from '@stock-bot/types';
|
||||
import { ProxyManager } from '@stock-bot/utils';
|
||||
|
||||
// Local imports
|
||||
import { createRoutes } from './routes/create-routes';
|
||||
import { initializeQMProviderNew } from './handlers/qm/qm.handler';
|
||||
import { initializeAllHandlers } from './handlers';
|
||||
|
||||
const config = initializeServiceConfig();
|
||||
console.log('Data Service Configuration:', JSON.stringify(config, null, 2));
|
||||
|
|
@ -84,19 +84,14 @@ async function initializeServices() {
|
|||
// Initialize handlers with new DI pattern
|
||||
logger.debug('Initializing data handlers with new DI pattern...');
|
||||
|
||||
// Initialize QM handler with new pattern
|
||||
initializeQMProviderNew(services);
|
||||
|
||||
// TODO: Convert other handlers to new pattern
|
||||
// initializeWebShareProviderNew(services);
|
||||
// initializeIBProviderNew(services);
|
||||
// initializeProxyProviderNew(services);
|
||||
// Auto-register all handlers
|
||||
initializeAllHandlers(services);
|
||||
|
||||
logger.info('Data handlers initialized with new DI pattern');
|
||||
|
||||
// Create scheduled jobs from registered handlers
|
||||
logger.debug('Creating scheduled jobs from registered handlers...');
|
||||
const allHandlers = handlerRegistry.getAllHandlers();
|
||||
const allHandlers = handlerRegistry.getAllHandlersWithSchedule();
|
||||
|
||||
let totalScheduledJobs = 0;
|
||||
for (const [handlerName, config] of allHandlers) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue