fixed up qm and added types to BaseHandler for typesafety
This commit is contained in:
parent
87b1cad4f5
commit
2e86598262
20 changed files with 164 additions and 109 deletions
|
|
@ -75,7 +75,7 @@ export async function getChannels(this: CeoHandler, payload: number | undefined)
|
||||||
|
|
||||||
this.logger.info(`Fetched CEO channels for page ${page}/${totalPages}`);
|
this.logger.info(`Fetched CEO channels for page ${page}/${totalPages}`);
|
||||||
return { page, totalPages };
|
return { page, totalPages };
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
this.logger.error(`Error fetching CEO channels for page ${page} with proxy ${proxy}:`, error);
|
this.logger.error(`Error fetching CEO channels for page ${page} with proxy ${proxy}:`, error);
|
||||||
throw new Error(`Failed to fetch CEO channels: ${error.message}`);
|
throw new Error(`Failed to fetch CEO channels: ${error.message}`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,11 @@ import {
|
||||||
ScheduledOperation,
|
ScheduledOperation,
|
||||||
} from '@stock-bot/handlers';
|
} from '@stock-bot/handlers';
|
||||||
import { getChannels, getPosts, getShorts, updateUniqueSymbols } from './actions';
|
import { getChannels, getPosts, getShorts, updateUniqueSymbols } from './actions';
|
||||||
|
import type { DataIngestionServices } from '../../types';
|
||||||
|
|
||||||
@Handler('ceo')
|
@Handler('ceo')
|
||||||
@Disabled()
|
@Disabled()
|
||||||
export class CeoHandler extends BaseHandler {
|
export class CeoHandler extends BaseHandler<DataIngestionServices> {
|
||||||
constructor(services: any) {
|
constructor(services: any) {
|
||||||
super(services); // Handler name read from @Handler decorator
|
super(services); // Handler name read from @Handler decorator
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import type { IServiceContainer } from '@stock-bot/handlers';
|
|
||||||
import { fetchExchanges } from './fetch-exchanges.action';
|
import { fetchExchanges } from './fetch-exchanges.action';
|
||||||
import { fetchSession } from './fetch-session.action';
|
import { fetchSession } from './fetch-session.action';
|
||||||
import { fetchSymbols } from './fetch-symbols.action';
|
import { fetchSymbols } from './fetch-symbols.action';
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@
|
||||||
* QM Corporate Actions - Fetch and update dividends, splits, and earnings together
|
* QM Corporate Actions - Fetch and update dividends, splits, and earnings together
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||||
|
import type { QMHandler } from '../qm.handler';
|
||||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||||
import { QMSessionManager } from '../shared/session-manager';
|
|
||||||
import { QMOperationTracker } from '../shared/operation-tracker';
|
import { QMOperationTracker } from '../shared/operation-tracker';
|
||||||
|
import { QMSessionManager } from '../shared/session-manager';
|
||||||
|
|
||||||
// Cache tracker instance
|
// Cache tracker instance
|
||||||
let operationTracker: QMOperationTracker | null = null;
|
let operationTracker: QMOperationTracker | null = null;
|
||||||
|
|
@ -13,7 +14,7 @@ let operationTracker: QMOperationTracker | null = null;
|
||||||
/**
|
/**
|
||||||
* Get or initialize the operation tracker
|
* Get or initialize the operation tracker
|
||||||
*/
|
*/
|
||||||
async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTracker> {
|
async function getOperationTracker(handler: QMHandler): Promise<QMOperationTracker> {
|
||||||
if (!operationTracker) {
|
if (!operationTracker) {
|
||||||
const { initializeQMOperations } = await import('../shared/operation-registry');
|
const { initializeQMOperations } = await import('../shared/operation-registry');
|
||||||
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
||||||
|
|
@ -26,7 +27,7 @@ async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTra
|
||||||
* Single API call returns all three data types
|
* Single API call returns all three data types
|
||||||
*/
|
*/
|
||||||
export async function updateCorporateActions(
|
export async function updateCorporateActions(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: {
|
input: {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
symbolId: number;
|
symbolId: number;
|
||||||
|
|
@ -191,7 +192,7 @@ export async function updateCorporateActions(
|
||||||
* Schedule corporate actions updates for symbols that need refreshing
|
* Schedule corporate actions updates for symbols that need refreshing
|
||||||
*/
|
*/
|
||||||
export async function scheduleCorporateActionsUpdates(
|
export async function scheduleCorporateActionsUpdates(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: {
|
input: {
|
||||||
limit?: number;
|
limit?: number;
|
||||||
forceUpdate?: boolean;
|
forceUpdate?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@
|
||||||
* QM Filings Actions - Fetch and update SEC filings
|
* QM Filings Actions - Fetch and update SEC filings
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||||
|
import type { QMHandler } from '../qm.handler';
|
||||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||||
import { QMSessionManager } from '../shared/session-manager';
|
|
||||||
import { QMOperationTracker } from '../shared/operation-tracker';
|
import { QMOperationTracker } from '../shared/operation-tracker';
|
||||||
|
import { QMSessionManager } from '../shared/session-manager';
|
||||||
|
|
||||||
// Cache tracker instance
|
// Cache tracker instance
|
||||||
let operationTracker: QMOperationTracker | null = null;
|
let operationTracker: QMOperationTracker | null = null;
|
||||||
|
|
@ -13,7 +14,7 @@ let operationTracker: QMOperationTracker | null = null;
|
||||||
/**
|
/**
|
||||||
* Get or initialize the operation tracker
|
* Get or initialize the operation tracker
|
||||||
*/
|
*/
|
||||||
async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTracker> {
|
async function getOperationTracker(handler: QMHandler): Promise<QMOperationTracker> {
|
||||||
if (!operationTracker) {
|
if (!operationTracker) {
|
||||||
const { initializeQMOperations } = await import('../shared/operation-registry');
|
const { initializeQMOperations } = await import('../shared/operation-registry');
|
||||||
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
||||||
|
|
@ -25,7 +26,7 @@ async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTra
|
||||||
* Update filings for a single symbol
|
* Update filings for a single symbol
|
||||||
*/
|
*/
|
||||||
export async function updateFilings(
|
export async function updateFilings(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: {
|
input: {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
symbolId: number;
|
symbolId: number;
|
||||||
|
|
@ -160,7 +161,7 @@ export async function updateFilings(
|
||||||
* Schedule filings updates for symbols that need refreshing
|
* Schedule filings updates for symbols that need refreshing
|
||||||
*/
|
*/
|
||||||
export async function scheduleFilingsUpdates(
|
export async function scheduleFilingsUpdates(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: {
|
input: {
|
||||||
limit?: number;
|
limit?: number;
|
||||||
forceUpdate?: boolean;
|
forceUpdate?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@
|
||||||
* QM Financials Actions - Fetch and update financial statements
|
* QM Financials Actions - Fetch and update financial statements
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||||
|
import type { QMHandler } from '../qm.handler';
|
||||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||||
import { QMSessionManager } from '../shared/session-manager';
|
|
||||||
import { QMOperationTracker } from '../shared/operation-tracker';
|
import { QMOperationTracker } from '../shared/operation-tracker';
|
||||||
|
import { QMSessionManager } from '../shared/session-manager';
|
||||||
|
|
||||||
// Cache tracker instance
|
// Cache tracker instance
|
||||||
let operationTracker: QMOperationTracker | null = null;
|
let operationTracker: QMOperationTracker | null = null;
|
||||||
|
|
@ -13,7 +14,7 @@ let operationTracker: QMOperationTracker | null = null;
|
||||||
/**
|
/**
|
||||||
* Get or initialize the operation tracker
|
* Get or initialize the operation tracker
|
||||||
*/
|
*/
|
||||||
async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTracker> {
|
async function getOperationTracker(handler: QMHandler): Promise<QMOperationTracker> {
|
||||||
if (!operationTracker) {
|
if (!operationTracker) {
|
||||||
const { initializeQMOperations } = await import('../shared/operation-registry');
|
const { initializeQMOperations } = await import('../shared/operation-registry');
|
||||||
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
||||||
|
|
@ -25,7 +26,7 @@ async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTra
|
||||||
* Update financials for a single symbol
|
* Update financials for a single symbol
|
||||||
*/
|
*/
|
||||||
export async function updateFinancials(
|
export async function updateFinancials(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: {
|
input: {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
symbolId: number;
|
symbolId: number;
|
||||||
|
|
@ -136,7 +137,6 @@ export async function updateFinancials(
|
||||||
const tracker = await getOperationTracker(this);
|
const tracker = await getOperationTracker(this);
|
||||||
await tracker.updateSymbolOperation(symbol, 'financials_update', {
|
await tracker.updateSymbolOperation(symbol, 'financials_update', {
|
||||||
status: 'failure',
|
status: 'failure',
|
||||||
lastRunAt: new Date()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -151,7 +151,7 @@ export async function updateFinancials(
|
||||||
* Schedule financial updates for symbols that need refreshing
|
* Schedule financial updates for symbols that need refreshing
|
||||||
*/
|
*/
|
||||||
export async function scheduleFinancialsUpdates(
|
export async function scheduleFinancialsUpdates(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: {
|
input: {
|
||||||
limit?: number;
|
limit?: number;
|
||||||
forceUpdate?: boolean;
|
forceUpdate?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@
|
||||||
* QM Intraday Actions - Fetch and update intraday price bars
|
* QM Intraday Actions - Fetch and update intraday price bars
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||||
|
import type { QMHandler } from '../qm.handler';
|
||||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||||
import { QMSessionManager } from '../shared/session-manager';
|
|
||||||
import { QMOperationTracker } from '../shared/operation-tracker';
|
import { QMOperationTracker } from '../shared/operation-tracker';
|
||||||
|
import { QMSessionManager } from '../shared/session-manager';
|
||||||
|
|
||||||
// Cache tracker instance
|
// Cache tracker instance
|
||||||
let operationTracker: QMOperationTracker | null = null;
|
let operationTracker: QMOperationTracker | null = null;
|
||||||
|
|
@ -13,7 +14,7 @@ let operationTracker: QMOperationTracker | null = null;
|
||||||
/**
|
/**
|
||||||
* Get or initialize the operation tracker
|
* Get or initialize the operation tracker
|
||||||
*/
|
*/
|
||||||
async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTracker> {
|
async function getOperationTracker(handler: QMHandler): Promise<QMOperationTracker> {
|
||||||
if (!operationTracker) {
|
if (!operationTracker) {
|
||||||
const { initializeQMOperations } = await import('../shared/operation-registry');
|
const { initializeQMOperations } = await import('../shared/operation-registry');
|
||||||
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
||||||
|
|
@ -26,7 +27,7 @@ async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTra
|
||||||
* This handles both initial crawl and incremental updates
|
* This handles both initial crawl and incremental updates
|
||||||
*/
|
*/
|
||||||
export async function updateIntradayBars(
|
export async function updateIntradayBars(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: {
|
input: {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
symbolId: number;
|
symbolId: number;
|
||||||
|
|
@ -66,7 +67,7 @@ export async function updateIntradayBars(
|
||||||
webmasterId: '500',
|
webmasterId: '500',
|
||||||
date: targetDate.toISOString().split('T')[0],
|
date: targetDate.toISOString().split('T')[0],
|
||||||
interval: '1' // 1-minute bars
|
interval: '1' // 1-minute bars
|
||||||
});
|
} as Record<string, string>);
|
||||||
|
|
||||||
// TODO: Update with correct intraday endpoint
|
// TODO: Update with correct intraday endpoint
|
||||||
const apiUrl = `${QM_CONFIG.BASE_URL}/datatool/intraday.json?${searchParams.toString()}`;
|
const apiUrl = `${QM_CONFIG.BASE_URL}/datatool/intraday.json?${searchParams.toString()}`;
|
||||||
|
|
@ -157,7 +158,7 @@ export async function updateIntradayBars(
|
||||||
* This handles both initial crawls and regular updates
|
* This handles both initial crawls and regular updates
|
||||||
*/
|
*/
|
||||||
export async function scheduleIntradayUpdates(
|
export async function scheduleIntradayUpdates(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: {
|
input: {
|
||||||
limit?: number;
|
limit?: number;
|
||||||
mode?: 'crawl' | 'update'; // crawl for historical, update for recent
|
mode?: 'crawl' | 'update'; // crawl for historical, update for recent
|
||||||
|
|
@ -259,7 +260,6 @@ export async function scheduleIntradayUpdates(
|
||||||
crawlState: {
|
crawlState: {
|
||||||
finished: false,
|
finished: false,
|
||||||
oldestDateReached: new Date(startDate.getTime() - daysToFetch * 24 * 60 * 60 * 1000),
|
oldestDateReached: new Date(startDate.getTime() - daysToFetch * 24 * 60 * 60 * 1000),
|
||||||
lastCrawlDirection: 'backward'
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@
|
||||||
* QM Prices Actions - Fetch and update daily price data
|
* QM Prices Actions - Fetch and update daily price data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||||
|
import type { QMHandler } from '../qm.handler';
|
||||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||||
import { QMSessionManager } from '../shared/session-manager';
|
|
||||||
import { QMOperationTracker } from '../shared/operation-tracker';
|
import { QMOperationTracker } from '../shared/operation-tracker';
|
||||||
|
import { QMSessionManager } from '../shared/session-manager';
|
||||||
|
|
||||||
// Cache tracker instance
|
// Cache tracker instance
|
||||||
let operationTracker: QMOperationTracker | null = null;
|
let operationTracker: QMOperationTracker | null = null;
|
||||||
|
|
@ -13,7 +14,7 @@ let operationTracker: QMOperationTracker | null = null;
|
||||||
/**
|
/**
|
||||||
* Get or initialize the operation tracker
|
* Get or initialize the operation tracker
|
||||||
*/
|
*/
|
||||||
async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTracker> {
|
async function getOperationTracker(handler: QMHandler): Promise<QMOperationTracker> {
|
||||||
if (!operationTracker) {
|
if (!operationTracker) {
|
||||||
const { initializeQMOperations } = await import('../shared/operation-registry');
|
const { initializeQMOperations } = await import('../shared/operation-registry');
|
||||||
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
||||||
|
|
@ -25,7 +26,7 @@ async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTra
|
||||||
* Update daily prices for a single symbol
|
* Update daily prices for a single symbol
|
||||||
*/
|
*/
|
||||||
export async function updatePrices(
|
export async function updatePrices(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: {
|
input: {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
symbolId: number;
|
symbolId: number;
|
||||||
|
|
@ -164,7 +165,7 @@ export async function updatePrices(
|
||||||
* Schedule price updates for symbols that need refreshing
|
* Schedule price updates for symbols that need refreshing
|
||||||
*/
|
*/
|
||||||
export async function schedulePriceUpdates(
|
export async function schedulePriceUpdates(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: {
|
input: {
|
||||||
limit?: number;
|
limit?: number;
|
||||||
forceUpdate?: boolean;
|
forceUpdate?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,18 @@
|
||||||
* QM Session Actions - Session management and creation
|
* QM Session Actions - Session management and creation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||||
import { BunRequestInit } from '@stock-bot/utils';
|
import type { QMHandler } from '../qm.handler';
|
||||||
import { getQmHeaders, QM_CONFIG, QM_SESSION_IDS, SESSION_CONFIG } from '../shared/config';
|
import { getQmHeaders, QM_CONFIG, QM_SESSION_IDS, SESSION_CONFIG } from '../shared/config';
|
||||||
import { QMSessionManager } from '../shared/session-manager';
|
import { QMSessionManager } from '../shared/session-manager';
|
||||||
import { QMSession } from '../shared/types';
|
import { type QMSession } from '../shared/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check existing sessions and queue creation jobs for needed sessions
|
* Check existing sessions and queue creation jobs for needed sessions
|
||||||
* This is the main session management function that handles cleanup, maintenance, and initialization
|
* This is the main session management function that handles cleanup, maintenance, and initialization
|
||||||
*/
|
*/
|
||||||
export async function checkSessions(
|
export async function checkSessions(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
_input: unknown,
|
_input: unknown,
|
||||||
_context: ExecutionContext
|
_context: ExecutionContext
|
||||||
): Promise<{
|
): Promise<{
|
||||||
|
|
@ -80,7 +80,7 @@ interface CreateSessionInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createSession(
|
export async function createSession(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: CreateSessionInput
|
input: CreateSessionInput
|
||||||
): Promise<{ sessionId: string; status: string; sessionType: string, session?: QMSession }> {
|
): Promise<{ sessionId: string; status: string; sessionType: string, session?: QMSession }> {
|
||||||
const { sessionId, sessionType = 'LOOKUP' } = input || {};
|
const { sessionId, sessionType = 'LOOKUP' } = input || {};
|
||||||
|
|
@ -108,7 +108,7 @@ export async function createSession(
|
||||||
const sessionUrl = `${QM_CONFIG.BASE_URL}${QM_CONFIG.SESSION_PATH}/${sessionId}`;
|
const sessionUrl = `${QM_CONFIG.BASE_URL}${QM_CONFIG.SESSION_PATH}/${sessionId}`;
|
||||||
|
|
||||||
// Build request options
|
// Build request options
|
||||||
const sessionRequest: BunRequestInit = {
|
const sessionRequest = {
|
||||||
proxy: proxyUrl || undefined,
|
proxy: proxyUrl || undefined,
|
||||||
headers: getQmHeaders(),
|
headers: getQmHeaders(),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@
|
||||||
* QM Symbol Info Actions - Fetch and update symbol metadata
|
* QM Symbol Info Actions - Fetch and update symbol metadata
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||||
|
import type { QMHandler } from '../qm.handler';
|
||||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||||
import { QMSessionManager } from '../shared/session-manager';
|
|
||||||
import { QMOperationTracker } from '../shared/operation-tracker';
|
import { QMOperationTracker } from '../shared/operation-tracker';
|
||||||
|
import { QMSessionManager } from '../shared/session-manager';
|
||||||
|
|
||||||
// Cache tracker instance
|
// Cache tracker instance
|
||||||
let operationTracker: QMOperationTracker | null = null;
|
let operationTracker: QMOperationTracker | null = null;
|
||||||
|
|
@ -13,7 +14,7 @@ let operationTracker: QMOperationTracker | null = null;
|
||||||
/**
|
/**
|
||||||
* Get or initialize the operation tracker
|
* Get or initialize the operation tracker
|
||||||
*/
|
*/
|
||||||
async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTracker> {
|
async function getOperationTracker(handler: QMHandler): Promise<QMOperationTracker> {
|
||||||
if (!operationTracker) {
|
if (!operationTracker) {
|
||||||
const { initializeQMOperations } = await import('../shared/operation-registry');
|
const { initializeQMOperations } = await import('../shared/operation-registry');
|
||||||
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
operationTracker = await initializeQMOperations(handler.mongodb, handler.logger);
|
||||||
|
|
@ -26,7 +27,7 @@ async function getOperationTracker(handler: BaseHandler): Promise<QMOperationTra
|
||||||
* This is a simple API fetch operation - no tracking logic here
|
* This is a simple API fetch operation - no tracking logic here
|
||||||
*/
|
*/
|
||||||
export async function updateSymbolInfo(
|
export async function updateSymbolInfo(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: {
|
input: {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
qmSearchCode: string;
|
qmSearchCode: string;
|
||||||
|
|
@ -144,7 +145,7 @@ export async function updateSymbolInfo(
|
||||||
* This is the scheduled job that finds stale symbols and queues individual updates
|
* This is the scheduled job that finds stale symbols and queues individual updates
|
||||||
*/
|
*/
|
||||||
export async function scheduleSymbolInfoUpdates(
|
export async function scheduleSymbolInfoUpdates(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: {
|
input: {
|
||||||
limit?: number;
|
limit?: number;
|
||||||
forceUpdate?: boolean;
|
forceUpdate?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,12 @@
|
||||||
* QM Symbol Actions - Symbol search and spider operations
|
* QM Symbol Actions - Symbol search and spider operations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BaseHandler, ExecutionContext } from '@stock-bot/handlers';
|
import type { ExecutionContext } from '@stock-bot/handlers';
|
||||||
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
import { QM_CONFIG, QM_SESSION_IDS } from '../shared/config';
|
||||||
import { QMSessionManager } from '../shared/session-manager';
|
import { QMSessionManager } from '../shared/session-manager';
|
||||||
// import { QMOperationTracker } from '../shared/operation-tracker';
|
// import { QMOperationTracker } from '../shared/operation-tracker';
|
||||||
// import { initializeQMOperations } from '../shared/operation-registry';
|
// import { initializeQMOperations } from '../shared/operation-registry';
|
||||||
|
import type { QMHandler } from '../qm.handler';
|
||||||
import type { Exchange, SymbolSpiderJob } from '../shared/types';
|
import type { Exchange, SymbolSpiderJob } from '../shared/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -15,7 +16,7 @@ import type { Exchange, SymbolSpiderJob } from '../shared/types';
|
||||||
* Each job searches its prefix and creates child jobs if needed
|
* Each job searches its prefix and creates child jobs if needed
|
||||||
*/
|
*/
|
||||||
export async function spiderSymbol(
|
export async function spiderSymbol(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: SymbolSpiderJob,
|
input: SymbolSpiderJob,
|
||||||
_context: ExecutionContext
|
_context: ExecutionContext
|
||||||
): Promise<{
|
): Promise<{
|
||||||
|
|
@ -62,7 +63,7 @@ export async function spiderSymbol(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.mongodb.batchUpsert('qmSymbols', symbols, ['qmSearchCode']);
|
await this.mongodb?.batchUpsert('qmSymbols', symbols, ['qmSearchCode']);
|
||||||
|
|
||||||
this.logger.info(`Stored symbols from spider search ${prefix} - ${symbols.length}`, {
|
this.logger.info(`Stored symbols from spider search ${prefix} - ${symbols.length}`, {
|
||||||
prefix,
|
prefix,
|
||||||
|
|
@ -84,7 +85,7 @@ export async function spiderSymbol(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exchanges.length > 0) {
|
if (exchanges.length > 0) {
|
||||||
await this.mongodb.batchUpsert('qmExchanges', exchanges, ['exchange']);
|
await this.mongodb?.batchUpsert('qmExchanges', exchanges, ['exchange']);
|
||||||
this.logger.debug('Stored exchanges from spider search', {
|
this.logger.debug('Stored exchanges from spider search', {
|
||||||
count: exchanges.length
|
count: exchanges.length
|
||||||
});
|
});
|
||||||
|
|
@ -136,7 +137,7 @@ export async function spiderSymbol(
|
||||||
* Search QM symbols API directly
|
* Search QM symbols API directly
|
||||||
*/
|
*/
|
||||||
export async function searchSymbols(
|
export async function searchSymbols(
|
||||||
this: BaseHandler,
|
this: QMHandler,
|
||||||
input: { query: string },
|
input: { query: string },
|
||||||
_context?: ExecutionContext
|
_context?: ExecutionContext
|
||||||
): Promise<any[]> {
|
): Promise<any[]> {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import {
|
||||||
Operation,
|
Operation,
|
||||||
ScheduledOperation,
|
ScheduledOperation,
|
||||||
} from '@stock-bot/handlers';
|
} from '@stock-bot/handlers';
|
||||||
|
import type { DataIngestionServices } from '../../types';
|
||||||
import {
|
import {
|
||||||
checkSessions,
|
checkSessions,
|
||||||
createSession,
|
createSession,
|
||||||
|
|
@ -25,7 +26,7 @@ import {
|
||||||
import { initializeQMOperations } from './shared/operation-registry';
|
import { initializeQMOperations } from './shared/operation-registry';
|
||||||
|
|
||||||
@Handler('qm')
|
@Handler('qm')
|
||||||
export class QMHandler extends BaseHandler {
|
export class QMHandler extends BaseHandler<DataIngestionServices> {
|
||||||
constructor(services: any) {
|
constructor(services: any) {
|
||||||
super(services); // Handler name read from @Handler decorator
|
super(services); // Handler name read from @Handler decorator
|
||||||
// Initialize operations after super() so services are available
|
// Initialize operations after super() so services are available
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* Supports dynamic operation registration with auto-indexing
|
* Supports dynamic operation registration with auto-indexing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { MongoDBClient, Logger } from '@stock-bot/types';
|
import type { Logger, MongoDBClient } from '@stock-bot/types';
|
||||||
import type { IntradayCrawlSymbol, QMOperationConfig } from './types';
|
import type { IntradayCrawlSymbol, QMOperationConfig } from './types';
|
||||||
|
|
||||||
export class QMOperationTracker {
|
export class QMOperationTracker {
|
||||||
|
|
@ -118,7 +118,7 @@ export class QMOperationTracker {
|
||||||
|
|
||||||
await this.mongodb.updateOne(this.collectionName, { symbol }, update);
|
await this.mongodb.updateOne(this.collectionName, { symbol }, update);
|
||||||
|
|
||||||
this.logger.trace('Updated symbol operation', {
|
this.logger.debug('Updated symbol operation', {
|
||||||
symbol,
|
symbol,
|
||||||
operation: operationName,
|
operation: operationName,
|
||||||
status: data.status
|
status: data.status
|
||||||
|
|
|
||||||
25
apps/stock/data-ingestion/src/types.ts
Normal file
25
apps/stock/data-ingestion/src/types.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* Data Ingestion Service Types
|
||||||
|
* Defines required services for data ingestion handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { ServiceTypes } from '@stock-bot/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Services required by data ingestion handlers
|
||||||
|
* Makes specific services non-nullable since they're always enabled
|
||||||
|
*/
|
||||||
|
export type DataIngestionServices = ServiceTypes & {
|
||||||
|
// Always required services
|
||||||
|
logger: NonNullable<ServiceTypes['logger']>;
|
||||||
|
mongodb: NonNullable<ServiceTypes['mongodb']>;
|
||||||
|
cache: NonNullable<ServiceTypes['cache']>;
|
||||||
|
queue: NonNullable<ServiceTypes['queue']>;
|
||||||
|
queueManager: NonNullable<ServiceTypes['queueManager']>;
|
||||||
|
browser: NonNullable<ServiceTypes['browser']>;
|
||||||
|
proxy: NonNullable<ServiceTypes['proxy']>;
|
||||||
|
// Optional services remain optional
|
||||||
|
postgres: ServiceTypes['postgres'];
|
||||||
|
questdb: ServiceTypes['questdb'];
|
||||||
|
globalCache: ServiceTypes['globalCache'];
|
||||||
|
};
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
{
|
{
|
||||||
"extends": "../../tsconfig.app.json",
|
"extends": "../../../tsconfig.app.json",
|
||||||
"references": [
|
"references": [
|
||||||
{ "path": "../../libs/core/types" },
|
{ "path": "../../../libs/core/types" },
|
||||||
{ "path": "../../libs/core/config" },
|
{ "path": "../../../libs/core/config" },
|
||||||
{ "path": "../../libs/core/logger" },
|
{ "path": "../../../libs/core/logger" },
|
||||||
{ "path": "../../libs/core/di" },
|
{ "path": "../../../libs/core/di" },
|
||||||
{ "path": "../../libs/core/handlers" },
|
{ "path": "../../../libs/core/handlers" },
|
||||||
{ "path": "../../libs/data/cache" },
|
{ "path": "../../../libs/core/cache" },
|
||||||
{ "path": "../../libs/data/mongodb" },
|
{ "path": "../../../libs/data/mongodb" },
|
||||||
{ "path": "../../libs/data/postgres" },
|
{ "path": "../../../libs/data/postgres" },
|
||||||
{ "path": "../../libs/data/questdb" },
|
{ "path": "../../../libs/data/questdb" },
|
||||||
{ "path": "../../libs/services/queue" },
|
{ "path": "../../../libs/core/queue" },
|
||||||
{ "path": "../../libs/services/shutdown" },
|
{ "path": "../../../libs/core/shutdown" },
|
||||||
{ "path": "../../libs/utils" },
|
{ "path": "../../../libs/utils" },
|
||||||
{ "path": "../config" }
|
{ "path": "../config" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
{
|
{
|
||||||
"extends": "../../tsconfig.app.json",
|
"extends": "../../../tsconfig.app.json",
|
||||||
"references": [
|
"references": [
|
||||||
{ "path": "../../libs/core/types" },
|
{ "path": "../../../libs/core/types" },
|
||||||
{ "path": "../../libs/core/config" },
|
{ "path": "../../../libs/core/config" },
|
||||||
{ "path": "../../libs/core/logger" },
|
{ "path": "../../../libs/core/logger" },
|
||||||
{ "path": "../../libs/data/cache" },
|
{ "path": "../../../libs/core/cache" },
|
||||||
{ "path": "../../libs/services/queue" },
|
{ "path": "../../../libs/core/queue" },
|
||||||
{ "path": "../../libs/data/mongodb" },
|
{ "path": "../../../libs/data/mongodb" },
|
||||||
{ "path": "../../libs/data/postgres" },
|
{ "path": "../../../libs/data/postgres" },
|
||||||
{ "path": "../../libs/data/questdb" },
|
{ "path": "../../../libs/data/questdb" },
|
||||||
{ "path": "../../libs/services/shutdown" }
|
{ "path": "../../../libs/core/shutdown" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
25
apps/stock/web-api/src/types.ts
Normal file
25
apps/stock/web-api/src/types.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* Web API Service Types
|
||||||
|
* Defines required services for web API handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { ServiceTypes } from '@stock-bot/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Services required by web API handlers
|
||||||
|
* Makes specific services non-nullable since they're always enabled
|
||||||
|
*/
|
||||||
|
export type WebApiServices = ServiceTypes & {
|
||||||
|
// Always required services
|
||||||
|
logger: NonNullable<ServiceTypes['logger']>;
|
||||||
|
mongodb: NonNullable<ServiceTypes['mongodb']>;
|
||||||
|
postgres: NonNullable<ServiceTypes['postgres']>;
|
||||||
|
cache: NonNullable<ServiceTypes['cache']>;
|
||||||
|
queue: NonNullable<ServiceTypes['queue']>;
|
||||||
|
queueManager: NonNullable<ServiceTypes['queueManager']>;
|
||||||
|
// Optional services remain optional
|
||||||
|
browser: ServiceTypes['browser'];
|
||||||
|
proxy: ServiceTypes['proxy'];
|
||||||
|
questdb: ServiceTypes['questdb'];
|
||||||
|
globalCache: ServiceTypes['globalCache'];
|
||||||
|
};
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
{
|
{
|
||||||
"extends": "../../tsconfig.app.json",
|
"extends": "../../../tsconfig.app.json",
|
||||||
"references": [
|
"references": [
|
||||||
{ "path": "../../libs/core/types" },
|
{ "path": "../../../libs/core/types" },
|
||||||
{ "path": "../../libs/core/config" },
|
{ "path": "../../../libs/core/config" },
|
||||||
{ "path": "../../libs/core/logger" },
|
{ "path": "../../../libs/core/logger" },
|
||||||
{ "path": "../../libs/data/cache" },
|
{ "path": "../../../libs/core/cache" },
|
||||||
{ "path": "../../libs/services/queue" },
|
{ "path": "../../../libs/core/queue" },
|
||||||
{ "path": "../../libs/data/mongodb" },
|
{ "path": "../../../libs/data/mongodb" },
|
||||||
{ "path": "../../libs/data/postgres" },
|
{ "path": "../../../libs/data/postgres" },
|
||||||
{ "path": "../../libs/data/questdb" },
|
{ "path": "../../../libs/data/questdb" },
|
||||||
{ "path": "../../libs/services/shutdown" }
|
{ "path": "../../../libs/core/shutdown" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,41 +40,41 @@ export interface JobScheduleOptions {
|
||||||
* Abstract base class for all handlers with improved DI
|
* Abstract base class for all handlers with improved DI
|
||||||
* Provides common functionality and structure for queue/event operations
|
* Provides common functionality and structure for queue/event operations
|
||||||
*/
|
*/
|
||||||
export abstract class BaseHandler implements IHandler {
|
export abstract class BaseHandler<TServices extends ServiceTypes = ServiceTypes> implements IHandler {
|
||||||
// Direct service properties - flattened for cleaner access with proper types
|
// Direct service properties - flattened for cleaner access with proper types
|
||||||
readonly logger: ServiceTypes['logger'];
|
readonly logger: TServices['logger'];
|
||||||
readonly cache: ServiceTypes['cache'];
|
readonly cache: TServices['cache'];
|
||||||
readonly globalCache: ServiceTypes['globalCache'];
|
readonly globalCache: TServices['globalCache'];
|
||||||
readonly queueManager: ServiceTypes['queueManager'];
|
readonly queueManager: TServices['queueManager'];
|
||||||
readonly queue: ServiceTypes['queue']; // Specific queue for this handler
|
readonly queue!: TServices['queue']; // Specific queue for this handler - initialized if queueManager exists
|
||||||
readonly proxy: ServiceTypes['proxy'];
|
readonly proxy: TServices['proxy'];
|
||||||
readonly browser: ServiceTypes['browser'];
|
readonly browser: TServices['browser'];
|
||||||
readonly mongodb: ServiceTypes['mongodb'];
|
readonly mongodb: TServices['mongodb'];
|
||||||
readonly postgres: ServiceTypes['postgres'];
|
readonly postgres: TServices['postgres'];
|
||||||
readonly questdb: ServiceTypes['questdb'];
|
readonly questdb: TServices['questdb'];
|
||||||
|
|
||||||
private handlerName: string;
|
private handlerName: string;
|
||||||
|
|
||||||
constructor(services: IServiceContainer, handlerName?: string) {
|
constructor(services: TServices, handlerName?: string) {
|
||||||
// Read handler name from decorator first, then fallback to parameter or class name
|
// Read handler name from decorator first, then fallback to parameter or class name
|
||||||
const constructor = this.constructor as any;
|
const constructor = this.constructor as any;
|
||||||
this.handlerName =
|
this.handlerName =
|
||||||
constructor.__handlerName || handlerName || this.constructor.name.toLowerCase();
|
constructor.__handlerName || handlerName || this.constructor.name.toLowerCase();
|
||||||
|
|
||||||
// Flatten all services onto the handler instance
|
// Flatten all services onto the handler instance
|
||||||
this.logger = getLogger(this.constructor.name);
|
this.logger = getLogger(this.constructor.name) as TServices['logger'];
|
||||||
this.cache = services.cache;
|
this.cache = services.cache as TServices['cache'];
|
||||||
this.globalCache = services.globalCache;
|
this.globalCache = services.globalCache as TServices['globalCache'];
|
||||||
this.queueManager = services.queueManager;
|
this.queueManager = services.queueManager as TServices['queueManager'];
|
||||||
this.proxy = services.proxy;
|
this.proxy = services.proxy as TServices['proxy'];
|
||||||
this.browser = services.browser;
|
this.browser = services.browser as TServices['browser'];
|
||||||
this.mongodb = services.mongodb;
|
this.mongodb = services.mongodb as TServices['mongodb'];
|
||||||
this.postgres = services.postgres;
|
this.postgres = services.postgres as TServices['postgres'];
|
||||||
this.questdb = services.questdb;
|
this.questdb = services.questdb as TServices['questdb'];
|
||||||
|
|
||||||
// Get the specific queue for this handler
|
// Get the specific queue for this handler
|
||||||
if (this.queueManager) {
|
if (this.queueManager) {
|
||||||
this.queue = this.queueManager.getQueue(this.handlerName);
|
this.queue = this.queueManager.getQueue(this.handlerName) as TServices['queue'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,11 @@
|
||||||
"composite": true,
|
"composite": true,
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"types": ["bun-types"],
|
"types": ["bun-types"],
|
||||||
// Modern TC39 Stage 3 decorators (TypeScript 5+ default)
|
// Use legacy decorators for compatibility with the handler system
|
||||||
"experimentalDecorators": false,
|
"experimentalDecorators": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
// Suppress decorator-related type checking issues due to Bun's hybrid implementation
|
// Suppress decorator-related type checking issues due to Bun's hybrid implementation
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true
|
||||||
"suppressImplicitAnyIndexErrors": true
|
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"],
|
"include": ["src/**/*"],
|
||||||
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue