simplified providers a bit
This commit is contained in:
parent
26eaaa6d61
commit
eca0396293
9 changed files with 48 additions and 209 deletions
|
|
@ -1,116 +0,0 @@
|
||||||
/**
|
|
||||||
* Example usage of the new functional batch processing approach
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { processItems, processBatchJob } from '../utils/batch-helpers';
|
|
||||||
import { queueManager } from '../services/queue.service';
|
|
||||||
|
|
||||||
// Example 1: Process a list of symbols for live data
|
|
||||||
export async function exampleSymbolProcessing() {
|
|
||||||
const symbols = ['AAPL', 'GOOGL', 'MSFT', 'TSLA', 'AMZN'];
|
|
||||||
|
|
||||||
const result = await processItems(
|
|
||||||
symbols,
|
|
||||||
(symbol, index) => ({
|
|
||||||
symbol,
|
|
||||||
index,
|
|
||||||
source: 'batch-processing'
|
|
||||||
}),
|
|
||||||
queueManager,
|
|
||||||
{
|
|
||||||
totalDelayMs: 60000, // 1 minute total
|
|
||||||
useBatching: false, // Process directly
|
|
||||||
priority: 1,
|
|
||||||
service: 'market-data',
|
|
||||||
provider: 'yahoo',
|
|
||||||
operation: 'live-data'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log('Symbol processing result:', result);
|
|
||||||
// Output: { jobsCreated: 5, mode: 'direct', totalItems: 5, duration: 1234 }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example 2: Process proxies in batches
|
|
||||||
export async function exampleProxyProcessing() {
|
|
||||||
const proxies = [
|
|
||||||
{ host: '1.1.1.1', port: 8080 },
|
|
||||||
{ host: '2.2.2.2', port: 3128 },
|
|
||||||
// ... more proxies
|
|
||||||
];
|
|
||||||
|
|
||||||
const result = await processItems(
|
|
||||||
proxies,
|
|
||||||
(proxy, index) => ({
|
|
||||||
proxy,
|
|
||||||
index,
|
|
||||||
source: 'batch-processing'
|
|
||||||
}),
|
|
||||||
queueManager,
|
|
||||||
{
|
|
||||||
totalDelayMs: 3600000, // 1 hour total
|
|
||||||
useBatching: true, // Use batch mode
|
|
||||||
batchSize: 100, // 100 proxies per batch
|
|
||||||
priority: 2,
|
|
||||||
service: 'proxy',
|
|
||||||
provider: 'proxy-service',
|
|
||||||
operation: 'check-proxy'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log('Proxy processing result:', result);
|
|
||||||
// Output: { jobsCreated: 10, mode: 'batch', totalItems: 1000, batchesCreated: 10, duration: 2345 }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example 3: Custom processing with generic function
|
|
||||||
export async function exampleCustomProcessing() {
|
|
||||||
const customData = [
|
|
||||||
{ id: 1, name: 'Item 1' },
|
|
||||||
{ id: 2, name: 'Item 2' },
|
|
||||||
{ id: 3, name: 'Item 3' }
|
|
||||||
];
|
|
||||||
|
|
||||||
const result = await processItems(
|
|
||||||
customData,
|
|
||||||
(item, index) => ({
|
|
||||||
// Transform each item for processing
|
|
||||||
itemId: item.id,
|
|
||||||
itemName: item.name,
|
|
||||||
processIndex: index,
|
|
||||||
timestamp: new Date().toISOString()
|
|
||||||
}),
|
|
||||||
queueManager,
|
|
||||||
{
|
|
||||||
totalDelayMs: 30000, // 30 seconds total
|
|
||||||
useBatching: false, // Direct processing
|
|
||||||
priority: 1,
|
|
||||||
retries: 3
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log('Custom processing result:', result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example 4: Batch job processor (used by workers)
|
|
||||||
export async function exampleBatchJobProcessor(jobData: any) {
|
|
||||||
// This would be called by a BullMQ worker when processing batch jobs
|
|
||||||
const result = await processBatchJob(jobData, queueManager);
|
|
||||||
|
|
||||||
console.log('Batch job processed:', result);
|
|
||||||
// Output: { batchIndex: 0, itemsProcessed: 100, jobsCreated: 100 }
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example: Simple functional approach using generic processItems
|
|
||||||
/*
|
|
||||||
await processItems(symbols, (symbol, index) => ({ symbol, index }), queueManager, {
|
|
||||||
totalDelayMs: 3600000,
|
|
||||||
useBatching: true,
|
|
||||||
batchSize: 200,
|
|
||||||
priority: 2,
|
|
||||||
service: 'data-service',
|
|
||||||
provider: 'yahoo',
|
|
||||||
operation: 'live-data'
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
@ -15,8 +15,7 @@ const getEvery24HourCron = (): string => {
|
||||||
|
|
||||||
export const proxyProvider: ProviderConfig = {
|
export const proxyProvider: ProviderConfig = {
|
||||||
name: 'proxy-provider',
|
name: 'proxy-provider',
|
||||||
service: 'data-service',
|
operations: {'fetch-and-check': async (payload: { sources?: string[] }) => {
|
||||||
operations: { 'fetch-and-check': async (payload: { sources?: string[] }) => {
|
|
||||||
const { proxyService } = await import('./proxy.tasks');
|
const { proxyService } = await import('./proxy.tasks');
|
||||||
const { queueManager } = await import('../services/queue.service');
|
const { queueManager } = await import('../services/queue.service');
|
||||||
const { processItems } = await import('../utils/batch-helpers');
|
const { processItems } = await import('../utils/batch-helpers');
|
||||||
|
|
@ -35,13 +34,11 @@ export const proxyProvider: ProviderConfig = {
|
||||||
index,
|
index,
|
||||||
source: 'batch-processing'
|
source: 'batch-processing'
|
||||||
}),
|
}),
|
||||||
queueManager,
|
queueManager, {
|
||||||
{
|
|
||||||
totalDelayMs: parseInt(process.env.PROXY_VALIDATION_HOURS || '4') * 60 * 60 * 1000,
|
totalDelayMs: parseInt(process.env.PROXY_VALIDATION_HOURS || '4') * 60 * 60 * 1000,
|
||||||
batchSize: parseInt(process.env.PROXY_BATCH_SIZE || '200'),
|
batchSize: parseInt(process.env.PROXY_BATCH_SIZE || '200'),
|
||||||
useBatching: process.env.PROXY_DIRECT_MODE !== 'true',
|
useBatching: process.env.PROXY_DIRECT_MODE !== 'true',
|
||||||
priority: 2,
|
priority: 2,
|
||||||
service: 'data-service',
|
|
||||||
provider: 'proxy-provider',
|
provider: 'proxy-provider',
|
||||||
operation: 'check-proxy'
|
operation: 'check-proxy'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,6 @@ export async function queueProxyFetch(): Promise<string> {
|
||||||
const { queueManager } = await import('../services/queue.service');
|
const { queueManager } = await import('../services/queue.service');
|
||||||
const job = await queueManager.addJob({
|
const job = await queueManager.addJob({
|
||||||
type: 'proxy-fetch',
|
type: 'proxy-fetch',
|
||||||
service: 'proxy',
|
|
||||||
provider: 'proxy-service',
|
provider: 'proxy-service',
|
||||||
operation: 'fetch-and-check',
|
operation: 'fetch-and-check',
|
||||||
payload: {},
|
payload: {},
|
||||||
|
|
@ -170,7 +169,6 @@ export async function queueProxyCheck(proxies: ProxyInfo[]): Promise<string> {
|
||||||
const { queueManager } = await import('../services/queue.service');
|
const { queueManager } = await import('../services/queue.service');
|
||||||
const job = await queueManager.addJob({
|
const job = await queueManager.addJob({
|
||||||
type: 'proxy-check',
|
type: 'proxy-check',
|
||||||
service: 'proxy',
|
|
||||||
provider: 'proxy-service',
|
provider: 'proxy-service',
|
||||||
operation: 'check-specific',
|
operation: 'check-specific',
|
||||||
payload: { proxies },
|
payload: { proxies },
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ const logger = getLogger('quotemedia-provider');
|
||||||
|
|
||||||
export const quotemediaProvider: ProviderConfig = {
|
export const quotemediaProvider: ProviderConfig = {
|
||||||
name: 'quotemedia',
|
name: 'quotemedia',
|
||||||
service: 'market-data',
|
|
||||||
operations: { 'live-data': async (payload: { symbol: string; fields?: string[] }) => {
|
operations: { 'live-data': async (payload: { symbol: string; fields?: string[] }) => {
|
||||||
logger.info('Fetching live data from QuoteMedia', { symbol: payload.symbol });
|
logger.info('Fetching live data from QuoteMedia', { symbol: payload.symbol });
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ const logger = getLogger('yahoo-provider');
|
||||||
|
|
||||||
export const yahooProvider: ProviderConfig = {
|
export const yahooProvider: ProviderConfig = {
|
||||||
name: 'yahoo-finance',
|
name: 'yahoo-finance',
|
||||||
service: 'market-data',
|
|
||||||
operations: {
|
operations: {
|
||||||
'live-data': async (payload: { symbol: string; modules?: string[] }) => {
|
'live-data': async (payload: { symbol: string; modules?: string[] }) => {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,7 @@ proxyRoutes.post('/api/proxy/fetch', async (c) => {
|
||||||
try {
|
try {
|
||||||
const job = await queueManager.addJob({
|
const job = await queueManager.addJob({
|
||||||
type: 'proxy-fetch',
|
type: 'proxy-fetch',
|
||||||
service: 'proxy',
|
provider: 'proxy-provider',
|
||||||
provider: 'proxy-service',
|
|
||||||
operation: 'fetch-and-check',
|
operation: 'fetch-and-check',
|
||||||
payload: {},
|
payload: {},
|
||||||
priority: 5
|
priority: 5
|
||||||
|
|
@ -37,8 +36,7 @@ proxyRoutes.post('/api/proxy/check', async (c) => {
|
||||||
const { proxies } = await c.req.json();
|
const { proxies } = await c.req.json();
|
||||||
const job = await queueManager.addJob({
|
const job = await queueManager.addJob({
|
||||||
type: 'proxy-check',
|
type: 'proxy-check',
|
||||||
service: 'proxy',
|
provider: 'proxy-provider',
|
||||||
provider: 'proxy-service',
|
|
||||||
operation: 'check-specific',
|
operation: 'check-specific',
|
||||||
payload: { proxies },
|
payload: { proxies },
|
||||||
priority: 8
|
priority: 8
|
||||||
|
|
@ -60,8 +58,7 @@ proxyRoutes.get('/api/proxy/stats', async (c) => {
|
||||||
try {
|
try {
|
||||||
const job = await queueManager.addJob({
|
const job = await queueManager.addJob({
|
||||||
type: 'proxy-stats',
|
type: 'proxy-stats',
|
||||||
service: 'proxy',
|
provider: 'proxy-provider',
|
||||||
provider: 'proxy-service',
|
|
||||||
operation: 'get-stats',
|
operation: 'get-stats',
|
||||||
payload: {},
|
payload: {},
|
||||||
priority: 3
|
priority: 3
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,15 @@ export interface JobHandler {
|
||||||
(payload: any): Promise<any>;
|
(payload: any): Promise<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface JobData {
|
||||||
|
type?: string;
|
||||||
|
provider: string;
|
||||||
|
operation: string;
|
||||||
|
payload: any;
|
||||||
|
priority?: number;
|
||||||
|
immediately?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ScheduledJob {
|
export interface ScheduledJob {
|
||||||
type: string;
|
type: string;
|
||||||
operation: string;
|
operation: string;
|
||||||
|
|
@ -16,7 +25,6 @@ export interface ScheduledJob {
|
||||||
|
|
||||||
export interface ProviderConfig {
|
export interface ProviderConfig {
|
||||||
name: string;
|
name: string;
|
||||||
service: string;
|
|
||||||
operations: Record<string, JobHandler>;
|
operations: Record<string, JobHandler>;
|
||||||
scheduledJobs?: ScheduledJob[];
|
scheduledJobs?: ScheduledJob[];
|
||||||
}
|
}
|
||||||
|
|
@ -27,51 +35,47 @@ export class ProviderRegistry {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a provider with its operations
|
* Register a provider with its operations
|
||||||
*/ registerProvider(config: ProviderConfig): void {
|
*/
|
||||||
const key = `${config.service}:${config.name}`;
|
registerProvider(config: ProviderConfig): void {
|
||||||
this.providers.set(key, config);
|
// const key = `${config.service}:${config.name}`;
|
||||||
this.logger.info(`Registered provider: ${key}`, {
|
this.providers.set(config.name, config);
|
||||||
|
this.logger.info(`Registered provider: ${config.name}`, {
|
||||||
operations: Object.keys(config.operations),
|
operations: Object.keys(config.operations),
|
||||||
scheduledJobs: config.scheduledJobs?.length || 0
|
scheduledJobs: config.scheduledJobs?.length || 0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a job handler for a specific provider and operation
|
* Get a job handler for a specific provider and operation
|
||||||
*/
|
*/
|
||||||
getHandler(service: string, provider: string, operation: string): JobHandler | null {
|
getHandler(provider: string, operation: string): JobHandler | null {
|
||||||
const key = `${service}:${provider}`;
|
const providerConfig = this.providers.get(provider);
|
||||||
const providerConfig = this.providers.get(key);
|
|
||||||
|
|
||||||
if (!providerConfig) {
|
if (!providerConfig) {
|
||||||
this.logger.warn(`Provider not found: ${key}`);
|
this.logger.warn(`Provider not found: ${provider}`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const handler = providerConfig.operations[operation];
|
const handler = providerConfig.operations[operation];
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
this.logger.warn(`Operation not found: ${operation} in provider ${key}`);
|
this.logger.warn(`Operation not found: ${operation} in provider ${provider}`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all registered providers
|
* Get all scheduled jobs from all providers
|
||||||
*/
|
*/
|
||||||
getAllScheduledJobs(): Array<{
|
getAllScheduledJobs(): Array<{
|
||||||
service: string;
|
|
||||||
provider: string;
|
provider: string;
|
||||||
job: ScheduledJob;
|
job: ScheduledJob;
|
||||||
}> {
|
}> {
|
||||||
const allJobs: Array<{ service: string; provider: string; job: ScheduledJob }> = [];
|
const allJobs: Array<{ provider: string; job: ScheduledJob }> = [];
|
||||||
|
|
||||||
for (const [key, config] of this.providers) {
|
for (const [key, config] of this.providers) {
|
||||||
if (config.scheduledJobs) {
|
if (config.scheduledJobs) {
|
||||||
for (const job of config.scheduledJobs) {
|
for (const job of config.scheduledJobs) {
|
||||||
allJobs.push({
|
allJobs.push({
|
||||||
service: config.service,
|
|
||||||
provider: config.name,
|
provider: config.name,
|
||||||
job
|
job
|
||||||
});
|
});
|
||||||
|
|
@ -88,21 +92,12 @@ export class ProviderRegistry {
|
||||||
config
|
config
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a provider exists
|
* Check if a provider exists
|
||||||
*/
|
*/
|
||||||
hasProvider(service: string, provider: string): boolean {
|
hasProvider(provider: string): boolean {
|
||||||
return this.providers.has(`${service}:${provider}`);
|
return this.providers.has(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get providers by service type
|
|
||||||
*/
|
|
||||||
getProvidersByService(service: string): ProviderConfig[] {
|
|
||||||
return Array.from(this.providers.values()).filter(provider => provider.service === service);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all providers (useful for testing)
|
* Clear all providers (useful for testing)
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,6 @@
|
||||||
import { Queue, Worker, QueueEvents } from 'bullmq';
|
import { Queue, Worker, QueueEvents } from 'bullmq';
|
||||||
import { getLogger } from '@stock-bot/logger';
|
import { getLogger } from '@stock-bot/logger';
|
||||||
import { providerRegistry } from './provider-registry.service';
|
import { providerRegistry, JobData } from './provider-registry.service';
|
||||||
|
|
||||||
export interface JobData {
|
|
||||||
type: string;
|
|
||||||
service: string;
|
|
||||||
provider: string;
|
|
||||||
operation: string;
|
|
||||||
payload: any;
|
|
||||||
priority?: number;
|
|
||||||
immediately?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class QueueService {
|
export class QueueService {
|
||||||
private logger = getLogger('queue-service');
|
private logger = getLogger('queue-service');
|
||||||
|
|
@ -135,13 +125,11 @@ export class QueueService {
|
||||||
this.logger.error('Failed to register providers', { error });
|
this.logger.error('Failed to register providers', { error });
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
} private async processJob(job: any) {
|
||||||
private async processJob(job: any) {
|
const { provider, operation, payload }: JobData = job.data;
|
||||||
const { service, provider, operation, payload }: JobData = job.data;
|
|
||||||
|
|
||||||
this.logger.info('Processing job', {
|
this.logger.info('Processing job', {
|
||||||
id: job.id,
|
id: job.id,
|
||||||
service,
|
|
||||||
provider,
|
provider,
|
||||||
operation,
|
operation,
|
||||||
payloadKeys: Object.keys(payload || {})
|
payloadKeys: Object.keys(payload || {})
|
||||||
|
|
@ -155,10 +143,10 @@ export class QueueService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get handler from registry
|
// Get handler from registry
|
||||||
const handler = providerRegistry.getHandler(service, provider, operation);
|
const handler = providerRegistry.getHandler(provider, operation);
|
||||||
|
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
throw new Error(`No handler found for ${service}:${provider}:${operation}`);
|
throw new Error(`No handler found for ${provider}:${operation}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the handler
|
// Execute the handler
|
||||||
|
|
@ -166,7 +154,6 @@ export class QueueService {
|
||||||
|
|
||||||
this.logger.info('Job completed successfully', {
|
this.logger.info('Job completed successfully', {
|
||||||
id: job.id,
|
id: job.id,
|
||||||
service,
|
|
||||||
provider,
|
provider,
|
||||||
operation
|
operation
|
||||||
});
|
});
|
||||||
|
|
@ -177,7 +164,6 @@ export class QueueService {
|
||||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||||
this.logger.error('Job failed', {
|
this.logger.error('Job failed', {
|
||||||
id: job.id,
|
id: job.id,
|
||||||
service,
|
|
||||||
provider,
|
provider,
|
||||||
operation,
|
operation,
|
||||||
error: errorMessage
|
error: errorMessage
|
||||||
|
|
@ -220,12 +206,10 @@ export class QueueService {
|
||||||
let successCount = 0;
|
let successCount = 0;
|
||||||
let failureCount = 0;
|
let failureCount = 0;
|
||||||
let updatedCount = 0;
|
let updatedCount = 0;
|
||||||
let newCount = 0;
|
let newCount = 0; // Process each scheduled job
|
||||||
|
for (const { provider, job } of allScheduledJobs) {
|
||||||
// Process each scheduled job
|
|
||||||
for (const { service, provider, job } of allScheduledJobs) {
|
|
||||||
try {
|
try {
|
||||||
const jobKey = `${service}-${provider}-${job.operation}`;
|
const jobKey = `${provider}-${job.operation}`;
|
||||||
|
|
||||||
// Check if this job already exists
|
// Check if this job already exists
|
||||||
const existingJob = existingJobs.find(existing =>
|
const existingJob = existingJobs.find(existing =>
|
||||||
|
|
@ -257,7 +241,6 @@ export class QueueService {
|
||||||
|
|
||||||
await this.addRecurringJob({
|
await this.addRecurringJob({
|
||||||
type: job.type,
|
type: job.type,
|
||||||
service: service,
|
|
||||||
provider: provider,
|
provider: provider,
|
||||||
operation: job.operation,
|
operation: job.operation,
|
||||||
payload: job.payload,
|
payload: job.payload,
|
||||||
|
|
@ -267,7 +250,6 @@ export class QueueService {
|
||||||
|
|
||||||
this.logger.info('Scheduled job registered', {
|
this.logger.info('Scheduled job registered', {
|
||||||
type: job.type,
|
type: job.type,
|
||||||
service,
|
|
||||||
provider,
|
provider,
|
||||||
operation: job.operation,
|
operation: job.operation,
|
||||||
cronPattern: job.cronPattern,
|
cronPattern: job.cronPattern,
|
||||||
|
|
@ -280,7 +262,6 @@ export class QueueService {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error('Failed to register scheduled job', {
|
this.logger.error('Failed to register scheduled job', {
|
||||||
type: job.type,
|
type: job.type,
|
||||||
service,
|
|
||||||
provider,
|
provider,
|
||||||
error: error instanceof Error ? error.message : String(error)
|
error: error instanceof Error ? error.message : String(error)
|
||||||
});
|
});
|
||||||
|
|
@ -300,12 +281,12 @@ export class QueueService {
|
||||||
this.logger.error('Failed to setup scheduled tasks', error);
|
this.logger.error('Failed to setup scheduled tasks', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async addJob(jobData: JobData, options?: any) {
|
async addJob(jobData: JobData, options?: any) {
|
||||||
if (!this.isInitialized) {
|
if (!this.isInitialized) {
|
||||||
throw new Error('Queue service not initialized. Call initialize() first.');
|
throw new Error('Queue service not initialized. Call initialize() first.');
|
||||||
}
|
}
|
||||||
return this.queue.add(jobData.type, jobData, {
|
const jobType = jobData.type || `${jobData.provider}-${jobData.operation}`;
|
||||||
|
return this.queue.add(jobType, jobData, {
|
||||||
priority: jobData.priority || 0,
|
priority: jobData.priority || 0,
|
||||||
removeOnComplete: 10,
|
removeOnComplete: 10,
|
||||||
removeOnFail: 5,
|
removeOnFail: 5,
|
||||||
|
|
@ -318,9 +299,8 @@ export class QueueService {
|
||||||
throw new Error('Queue service not initialized. Call initialize() first.');
|
throw new Error('Queue service not initialized. Call initialize() first.');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try { // Create a unique job key for this specific job
|
||||||
// Create a unique job key for this specific job
|
const jobKey = `${jobData.provider}-${jobData.operation}`;
|
||||||
const jobKey = `${jobData.service}-${jobData.provider}-${jobData.operation}`;
|
|
||||||
|
|
||||||
// Get all existing repeatable jobs
|
// Get all existing repeatable jobs
|
||||||
const existingJobs = await this.queue.getRepeatableJobs();
|
const existingJobs = await this.queue.getRepeatableJobs();
|
||||||
|
|
@ -336,19 +316,18 @@ export class QueueService {
|
||||||
jobKey,
|
jobKey,
|
||||||
existingPattern: existingJob.pattern,
|
existingPattern: existingJob.pattern,
|
||||||
newPattern: cronPattern
|
newPattern: cronPattern
|
||||||
});
|
}); // Remove the existing job
|
||||||
|
if (existingJob.key) {
|
||||||
// Remove the existing job
|
await this.queue.removeRepeatableByKey(existingJob.key);
|
||||||
await this.queue.removeRepeatableByKey(existingJob.key);
|
}
|
||||||
|
|
||||||
// Small delay to ensure cleanup is complete
|
// Small delay to ensure cleanup is complete
|
||||||
await new Promise(resolve => setTimeout(resolve, 100));
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
} else {
|
} else {
|
||||||
this.logger.info('Creating new recurring job', { jobKey, cronPattern });
|
this.logger.info('Creating new recurring job', { jobKey, cronPattern });
|
||||||
}
|
} // Add the new/updated recurring job
|
||||||
|
const jobType = jobData.type || `${jobData.provider}-${jobData.operation}`;
|
||||||
// Add the new/updated recurring job
|
const job = await this.queue.add(jobType, jobData, {
|
||||||
const job = await this.queue.add(jobData.type, jobData, {
|
|
||||||
repeat: {
|
repeat: {
|
||||||
pattern: cronPattern,
|
pattern: cronPattern,
|
||||||
tz: 'UTC',
|
tz: 'UTC',
|
||||||
|
|
@ -435,21 +414,17 @@ export class QueueService {
|
||||||
}
|
}
|
||||||
return this.workers.length;
|
return this.workers.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRegisteredProviders() {
|
getRegisteredProviders() {
|
||||||
return providerRegistry.getProviders().map(({ key, config }) => ({
|
return providerRegistry.getProviders().map(({ key, config }) => ({
|
||||||
key,
|
key,
|
||||||
name: config.name,
|
name: config.name,
|
||||||
service: config.service,
|
|
||||||
operations: Object.keys(config.operations),
|
operations: Object.keys(config.operations),
|
||||||
scheduledJobs: config.scheduledJobs?.length || 0
|
scheduledJobs: config.scheduledJobs?.length || 0
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
getScheduledJobsInfo() {
|
getScheduledJobsInfo() {
|
||||||
return providerRegistry.getAllScheduledJobs().map(({ service, provider, job }) => ({
|
return providerRegistry.getAllScheduledJobs().map(({ provider, job }) => ({
|
||||||
id: `${service}-${provider}-${job.type}`,
|
id: `${provider}-${job.type}`,
|
||||||
service,
|
|
||||||
provider,
|
provider,
|
||||||
type: job.type,
|
type: job.type,
|
||||||
operation: job.operation,
|
operation: job.operation,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ export interface ProcessOptions {
|
||||||
removeOnComplete?: number;
|
removeOnComplete?: number;
|
||||||
removeOnFail?: number;
|
removeOnFail?: number;
|
||||||
// Job routing information
|
// Job routing information
|
||||||
service?: string;
|
|
||||||
provider?: string;
|
provider?: string;
|
||||||
operation?: string;
|
operation?: string;
|
||||||
}
|
}
|
||||||
|
|
@ -121,7 +120,6 @@ async function processDirect<T>(
|
||||||
name: 'process-item',
|
name: 'process-item',
|
||||||
data: {
|
data: {
|
||||||
type: 'process-item',
|
type: 'process-item',
|
||||||
service: options.service || 'data-service',
|
|
||||||
provider: options.provider || 'generic',
|
provider: options.provider || 'generic',
|
||||||
operation: options.operation || 'process-item',
|
operation: options.operation || 'process-item',
|
||||||
payload: processor(item, index),
|
payload: processor(item, index),
|
||||||
|
|
@ -174,7 +172,6 @@ async function processBatched<T>(
|
||||||
name: 'process-batch',
|
name: 'process-batch',
|
||||||
data: {
|
data: {
|
||||||
type: 'process-batch',
|
type: 'process-batch',
|
||||||
service: options.service || 'generic',
|
|
||||||
provider: options.provider || 'generic',
|
provider: options.provider || 'generic',
|
||||||
operation: 'process-batch-items',
|
operation: 'process-batch-items',
|
||||||
payload: {
|
payload: {
|
||||||
|
|
@ -234,7 +231,6 @@ export async function processBatchJob(jobData: any, queue: QueueService): Promis
|
||||||
name: 'process-item',
|
name: 'process-item',
|
||||||
data: {
|
data: {
|
||||||
type: 'process-item',
|
type: 'process-item',
|
||||||
service: options.service || 'generic',
|
|
||||||
provider: options.provider || 'generic',
|
provider: options.provider || 'generic',
|
||||||
operation: options.operation || 'generic',
|
operation: options.operation || 'generic',
|
||||||
payload: processor(item, index),
|
payload: processor(item, index),
|
||||||
|
|
@ -297,7 +293,6 @@ async function storePayload<T>(
|
||||||
priority: options.priority || 1,
|
priority: options.priority || 1,
|
||||||
retries: options.retries || 3,
|
retries: options.retries || 3,
|
||||||
// Store routing information for later use
|
// Store routing information for later use
|
||||||
service: options.service || 'generic',
|
|
||||||
provider: options.provider || 'generic',
|
provider: options.provider || 'generic',
|
||||||
operation: options.operation || 'generic'
|
operation: options.operation || 'generic'
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue