Add sync driver for queue messages (#3070)
* Add sync driver for queue messages * rename moduleRef * use switch instead
This commit is contained in:
@ -148,7 +148,7 @@ export class EnvironmentService {
|
|||||||
getMessageQueueDriverType(): MessageQueueDriverType {
|
getMessageQueueDriverType(): MessageQueueDriverType {
|
||||||
return (
|
return (
|
||||||
this.configService.get<MessageQueueDriverType>('MESSAGE_QUEUE_TYPE') ??
|
this.configService.get<MessageQueueDriverType>('MESSAGE_QUEUE_TYPE') ??
|
||||||
MessageQueueDriverType.PgBoss
|
MessageQueueDriverType.Sync
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
import { QueueJobOptions } from 'src/integrations/message-queue/drivers/interfaces/job-options.interface';
|
import { QueueJobOptions } from 'src/integrations/message-queue/drivers/interfaces/job-options.interface';
|
||||||
|
import { MessageQueueJobData } from 'src/integrations/message-queue/interfaces/message-queue-job.interface';
|
||||||
|
|
||||||
import { MessageQueue } from 'src/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/integrations/message-queue/message-queue.constants';
|
||||||
|
|
||||||
export interface MessageQueueDriver {
|
export interface MessageQueueDriver {
|
||||||
add<T>(
|
add<T extends MessageQueueJobData>(
|
||||||
queueName: MessageQueue,
|
queueName: MessageQueue,
|
||||||
jobName: string,
|
jobName: string,
|
||||||
data: T,
|
data: T,
|
||||||
options?: QueueJobOptions,
|
options?: QueueJobOptions,
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
work<T>(
|
work<T extends MessageQueueJobData>(
|
||||||
queueName: MessageQueue,
|
queueName: MessageQueue,
|
||||||
handler: ({ data, id }: { data: T; id: string }) => Promise<void> | void,
|
handler: ({ data, id }: { data: T; id: string }) => Promise<void> | void,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
import { ModuleRef } from "@nestjs/core";
|
||||||
|
import { QueueJobOptions } from "src/integrations/message-queue/drivers/interfaces/job-options.interface";
|
||||||
|
import { MessageQueueDriver } from "src/integrations/message-queue/drivers/interfaces/message-queue-driver.interface";
|
||||||
|
import { MessageQueueJob, MessageQueueJobData } from "src/integrations/message-queue/interfaces/message-queue-job.interface";
|
||||||
|
import { MessageQueue } from "src/integrations/message-queue/message-queue.constants";
|
||||||
|
import { MessageQueueModule } from "src/integrations/message-queue/message-queue.module";
|
||||||
|
import { getJobClassName } from "src/integrations/message-queue/utils/get-job-class-name.util";
|
||||||
|
import { QueueWorkerModule } from "src/queue-worker.module";
|
||||||
|
|
||||||
|
export class SyncDriver implements MessageQueueDriver {
|
||||||
|
constructor(private readonly jobsModuleRef: ModuleRef) {}
|
||||||
|
async add<T extends MessageQueueJobData>(_queueName: MessageQueue, jobName: string, data: T, _options?: QueueJobOptions | undefined): Promise<void> {
|
||||||
|
const jobClassName = getJobClassName(jobName);
|
||||||
|
const job: MessageQueueJob<MessageQueueJobData> = this.jobsModuleRef.get(jobClassName, { strict: true });
|
||||||
|
|
||||||
|
return await job.handle(data);
|
||||||
|
}
|
||||||
|
work<T>(queueName: MessageQueue, handler: ({ data, id }: { data: T; id: string; }) => void | Promise<void>) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@ import { PgBossDriverOptions } from 'src/integrations/message-queue/drivers/pg-b
|
|||||||
export enum MessageQueueDriverType {
|
export enum MessageQueueDriverType {
|
||||||
PgBoss = 'pg-boss',
|
PgBoss = 'pg-boss',
|
||||||
BullMQ = 'bull-mq',
|
BullMQ = 'bull-mq',
|
||||||
|
Sync = 'sync',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PgBossDriverFactoryOptions {
|
export interface PgBossDriverFactoryOptions {
|
||||||
@ -18,9 +19,15 @@ export interface BullMQDriverFactoryOptions {
|
|||||||
options: BullMQDriverOptions;
|
options: BullMQDriverOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SyncDriverFactoryOptions {
|
||||||
|
type: MessageQueueDriverType.Sync;
|
||||||
|
options: Record<string, any>;
|
||||||
|
}
|
||||||
|
|
||||||
export type MessageQueueModuleOptions =
|
export type MessageQueueModuleOptions =
|
||||||
| PgBossDriverFactoryOptions
|
| PgBossDriverFactoryOptions
|
||||||
| BullMQDriverFactoryOptions;
|
| BullMQDriverFactoryOptions
|
||||||
|
| SyncDriverFactoryOptions;
|
||||||
|
|
||||||
export type MessageQueueModuleAsyncOptions = {
|
export type MessageQueueModuleAsyncOptions = {
|
||||||
useFactory: (
|
useFactory: (
|
||||||
|
|||||||
@ -0,0 +1,19 @@
|
|||||||
|
import { Module } from "@nestjs/common";
|
||||||
|
import { ModuleRef } from "@nestjs/core";
|
||||||
|
import { FetchMessagesJob } from "src/workspace/messaging/jobs/fetch-messages.job";
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: FetchMessagesJob.name,
|
||||||
|
useClass: FetchMessagesJob,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class JobsModule {
|
||||||
|
static moduleRef: ModuleRef;
|
||||||
|
|
||||||
|
constructor(private moduleRef: ModuleRef) {
|
||||||
|
JobsModule.moduleRef = this.moduleRef;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,6 +15,12 @@ export const messageQueueModuleFactory = async (
|
|||||||
const driverType = environmentService.getMessageQueueDriverType();
|
const driverType = environmentService.getMessageQueueDriverType();
|
||||||
|
|
||||||
switch (driverType) {
|
switch (driverType) {
|
||||||
|
case MessageQueueDriverType.Sync: {
|
||||||
|
return {
|
||||||
|
type: MessageQueueDriverType.Sync,
|
||||||
|
options: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
case MessageQueueDriverType.PgBoss: {
|
case MessageQueueDriverType.PgBoss: {
|
||||||
const connectionString = environmentService.getPGDatabaseUrl();
|
const connectionString = environmentService.getPGDatabaseUrl();
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,11 @@ import {
|
|||||||
import { PgBossDriver } from 'src/integrations/message-queue/drivers/pg-boss.driver';
|
import { PgBossDriver } from 'src/integrations/message-queue/drivers/pg-boss.driver';
|
||||||
import { MessageQueueService } from 'src/integrations/message-queue/services/message-queue.service';
|
import { MessageQueueService } from 'src/integrations/message-queue/services/message-queue.service';
|
||||||
import { BullMQDriver } from 'src/integrations/message-queue/drivers/bullmq.driver';
|
import { BullMQDriver } from 'src/integrations/message-queue/drivers/bullmq.driver';
|
||||||
|
import { FetchMessagesJob } from 'src/workspace/messaging/jobs/fetch-messages.job';
|
||||||
|
import { SyncDriver } from 'src/integrations/message-queue/drivers/sync.driver';
|
||||||
|
import { ModuleRef } from '@nestjs/core';
|
||||||
|
import { AppModule } from 'src/app.module';
|
||||||
|
import { JobsModule } from 'src/integrations/message-queue/jobs.module';
|
||||||
|
|
||||||
@Global()
|
@Global()
|
||||||
export class MessageQueueModule {
|
export class MessageQueueModule {
|
||||||
@ -30,15 +35,18 @@ export class MessageQueueModule {
|
|||||||
useFactory: async (...args: any[]) => {
|
useFactory: async (...args: any[]) => {
|
||||||
const config = await options.useFactory(...args);
|
const config = await options.useFactory(...args);
|
||||||
|
|
||||||
if (config.type === MessageQueueDriverType.PgBoss) {
|
switch (config.type) {
|
||||||
const boss = new PgBossDriver(config.options);
|
case MessageQueueDriverType.PgBoss:
|
||||||
|
const boss = new PgBossDriver(config.options);
|
||||||
|
await boss.init();
|
||||||
|
return boss;
|
||||||
|
|
||||||
await boss.init();
|
case MessageQueueDriverType.BullMQ:
|
||||||
|
return new BullMQDriver(config.options);
|
||||||
|
|
||||||
return boss;
|
default:
|
||||||
|
return new SyncDriver(JobsModule.moduleRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BullMQDriver(config.options);
|
|
||||||
},
|
},
|
||||||
inject: options.inject || [],
|
inject: options.inject || [],
|
||||||
},
|
},
|
||||||
@ -46,7 +54,7 @@ export class MessageQueueModule {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
module: MessageQueueModule,
|
module: MessageQueueModule,
|
||||||
imports: options.imports || [],
|
imports: [JobsModule, ...(options.imports || [])],
|
||||||
providers,
|
providers,
|
||||||
exports: [MessageQueue.taskAssignedQueue, MessageQueue.messagingQueue],
|
exports: [MessageQueue.taskAssignedQueue, MessageQueue.messagingQueue],
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
export function getJobClassName(name: string): string {
|
||||||
|
const [, jobName] = name.split('.') ?? [];
|
||||||
|
|
||||||
|
return jobName ?? name;
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ import { EnvironmentModule } from 'src/integrations/environment/environment.modu
|
|||||||
import { EnvironmentService } from 'src/integrations/environment/environment.service';
|
import { EnvironmentService } from 'src/integrations/environment/environment.service';
|
||||||
import { LoggerModule } from 'src/integrations/logger/logger.module';
|
import { LoggerModule } from 'src/integrations/logger/logger.module';
|
||||||
import { loggerModuleFactory } from 'src/integrations/logger/logger.module-factory';
|
import { loggerModuleFactory } from 'src/integrations/logger/logger.module-factory';
|
||||||
|
import { JobsModule } from 'src/integrations/message-queue/jobs.module';
|
||||||
import { MessageQueueModule } from 'src/integrations/message-queue/message-queue.module';
|
import { MessageQueueModule } from 'src/integrations/message-queue/message-queue.module';
|
||||||
import { messageQueueModuleFactory } from 'src/integrations/message-queue/message-queue.module-factory';
|
import { messageQueueModuleFactory } from 'src/integrations/message-queue/message-queue.module-factory';
|
||||||
import { FetchMessagesJob } from 'src/workspace/messaging/jobs/fetch-messages.job';
|
import { FetchMessagesJob } from 'src/workspace/messaging/jobs/fetch-messages.job';
|
||||||
@ -19,12 +20,7 @@ import { FetchMessagesJob } from 'src/workspace/messaging/jobs/fetch-messages.jo
|
|||||||
useFactory: messageQueueModuleFactory,
|
useFactory: messageQueueModuleFactory,
|
||||||
inject: [EnvironmentService],
|
inject: [EnvironmentService],
|
||||||
}),
|
}),
|
||||||
],
|
JobsModule,
|
||||||
providers: [
|
|
||||||
{
|
|
||||||
provide: FetchMessagesJob.name,
|
|
||||||
useClass: FetchMessagesJob,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class QueueWorkerModule {}
|
export class QueueWorkerModule {}
|
||||||
|
|||||||
@ -4,9 +4,11 @@ import {
|
|||||||
MessageQueueJob,
|
MessageQueueJob,
|
||||||
MessageQueueJobData,
|
MessageQueueJobData,
|
||||||
} from 'src/integrations/message-queue/interfaces/message-queue-job.interface';
|
} from 'src/integrations/message-queue/interfaces/message-queue-job.interface';
|
||||||
|
import { JobsModule } from 'src/integrations/message-queue/jobs.module';
|
||||||
|
|
||||||
import { MessageQueue } from 'src/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/integrations/message-queue/message-queue.constants';
|
||||||
import { MessageQueueService } from 'src/integrations/message-queue/services/message-queue.service';
|
import { MessageQueueService } from 'src/integrations/message-queue/services/message-queue.service';
|
||||||
|
import { getJobClassName } from 'src/integrations/message-queue/utils/get-job-class-name.util';
|
||||||
import { QueueWorkerModule } from 'src/queue-worker.module';
|
import { QueueWorkerModule } from 'src/queue-worker.module';
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
@ -18,7 +20,7 @@ async function bootstrap() {
|
|||||||
await messageQueueService.work(async (jobData: MessageQueueJobData) => {
|
await messageQueueService.work(async (jobData: MessageQueueJobData) => {
|
||||||
const jobClassName = getJobClassName(jobData.name);
|
const jobClassName = getJobClassName(jobData.name);
|
||||||
const job: MessageQueueJob<MessageQueueJobData> = app
|
const job: MessageQueueJob<MessageQueueJobData> = app
|
||||||
.select(QueueWorkerModule)
|
.select(JobsModule)
|
||||||
.get(jobClassName, { strict: true });
|
.get(jobClassName, { strict: true });
|
||||||
|
|
||||||
await job.handle(jobData.data);
|
await job.handle(jobData.data);
|
||||||
@ -27,8 +29,3 @@ async function bootstrap() {
|
|||||||
}
|
}
|
||||||
bootstrap();
|
bootstrap();
|
||||||
|
|
||||||
function getJobClassName(name: string): string {
|
|
||||||
const [, jobName] = name.split('.') ?? [];
|
|
||||||
|
|
||||||
return jobName ?? name;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user