import { BaseHandler, Disabled, Handler, Operation, ScheduledOperation, } from '@stock-bot/handlers'; import type { DataIngestionServices } from '../../types'; import type { OperationRegistry } from '../../shared/operation-manager'; import { createQMOperationRegistry } from './shared/operation-provider'; import { checkSessions, createSession, deduplicateSymbols, scheduleEventsUpdates, scheduleFilingsUpdates, scheduleFinancialsUpdates, scheduleIntradayUpdates, schedulePriceUpdates, scheduleSymbolInfoUpdates, searchSymbols, spiderSymbol, updateEvents, updateExchangeStats, updateExchangeStatsAndDeduplicate, updateFilings, updateFinancials, updateIntradayBars, updatePrices, updateSymbolInfo } from './actions'; @Handler('qm') export class QMHandler extends BaseHandler { public operationRegistry: OperationRegistry; constructor(services: any) { super(services); // Handler name read from @Handler decorator // Initialize operation registry with QM provider createQMOperationRegistry(this.mongodb, this.logger) .then(registry => { this.operationRegistry = registry; }) .catch(error => { this.logger.error('Failed to initialize QM operations', { error }); }); } /** * SESSIONS */ @ScheduledOperation('check-sessions', '*/1 * * * *', { priority: 8, immediately: true, description: 'Check and maintain QM sessions every 1 minutes', }) checkSessions = checkSessions; @Operation('create-session') createSession = createSession; /** * SYMBOLS */ @Operation('search-symbols') searchSymbols = searchSymbols; @Disabled() @ScheduledOperation('spider-symbols', '0 0 * * 0', { priority: 9, immediately: false, description: 'Weekly comprehensive symbol search using QM API spider - runs every Saturday at midnight' }) spiderSymbol = spiderSymbol; /** * EXCHANGE STATS & DEDUPLICATION */ @Operation('update-exchange-stats') updateExchangeStats = updateExchangeStats; @Operation('deduplicate-symbols') deduplicateSymbols = deduplicateSymbols; @Operation('update-exchange-stats-and-deduplicate') updateExchangeStatsAndDeduplicate = updateExchangeStatsAndDeduplicate; @ScheduledOperation('schedule-exchange-stats-and-dedup', '0 1 * * *', { priority: 7, immediately: false, description: 'Update exchange statistics and deduplicate symbols daily at 1 AM' }) scheduleExchangeStatsAndDedup = updateExchangeStatsAndDeduplicate; /** * SYMBOL INFO */ @Operation('update-symbol-info') updateSymbolInfo = updateSymbolInfo; // @Disabled() @ScheduledOperation('schedule-symbol-info-updates', '0 */6 * * *', { priority: 7, immediately: false, description: 'Check for symbols needing info updates every 6 hours' }) scheduleSymbolInfoUpdates = scheduleSymbolInfoUpdates; /** * FINANCIALS */ @Operation('update-financials') updateFinancials = updateFinancials; // @Disabled() @ScheduledOperation('schedule-financials-updates', '0 2 * * *', { priority: 6, immediately: false, description: 'Check for symbols needing financials updates daily at 2 AM' }) scheduleFinancialsUpdates = scheduleFinancialsUpdates; /** * EVENTS (Dividends, Splits, Earnings) */ @Operation('update-events') updateEvents = updateEvents; // @Disabled() @ScheduledOperation('schedule-events-updates', '0 3 * * *', { priority: 6, immediately: false, description: 'Check for symbols needing events updates daily at 3 AM' }) scheduleEventsUpdates = scheduleEventsUpdates; /** * FILINGS */ @Operation('update-filings') updateFilings = updateFilings; @Disabled() @ScheduledOperation('schedule-filings-updates', '0 */8 * * *', { priority: 5, immediately: false, description: 'Check for symbols needing filings updates every 8 hours' }) scheduleFilingsUpdates = scheduleFilingsUpdates; /** * PRICE DATA */ @Operation('update-prices') updatePrices = updatePrices; // @Disabled() @ScheduledOperation('schedule-price-updates', '0 */6 * * *', { priority: 8, immediately: false, description: 'Check for symbols needing price updates every 6 hours' }) schedulePriceUpdates = schedulePriceUpdates; /** * INTRADAY DATA */ @Operation('update-intraday-bars') updateIntradayBars = updateIntradayBars; @Disabled() @ScheduledOperation('schedule-intraday-updates', '*/30 * * * *', { priority: 9, immediately: false, description: 'Check for symbols needing intraday updates every 30 minutes' }) scheduleIntradayUpdates = scheduleIntradayUpdates; }