add mq and redis

This commit is contained in:
liuyi 2025-07-04 16:24:32 +08:00
parent 730b77448e
commit 24cb8e9843
7 changed files with 145 additions and 5 deletions

View File

@ -5,3 +5,5 @@ export * from './meili.config';
export * from './api.config'; export * from './api.config';
export * from './sms.config'; export * from './sms.config';
export * from './smtp.config'; export * from './smtp.config';
export * from './redis.config';
export * from './queue.config';

View File

@ -0,0 +1,5 @@
import { QueueOptions } from '@/modules/core/types';
export const queue: () => QueueOptions = () => ({
redis: 'default',
});

View File

@ -0,0 +1,6 @@
import { RedisOptions } from '@/modules/core/types';
export const redis: () => RedisOptions = () => ({
host: '127.0.0.1',
port: 6379,
});

View File

@ -1,4 +1,12 @@
import { DynamicModule, Module } from '@nestjs/common'; import { BullModule } from '@nestjs/bullmq';
import { DynamicModule, Module, ModuleMetadata } from '@nestjs/common';
import { isArray, isNil, omit } from 'lodash';
import { RedisService, SmsService, SmtpService } from '@/modules/core/services';
import { QueueOptions, RedisOptions, SmsOptions, SmtpOptions } from '@/modules/core/types';
import { createQueueOptions, createRedisOptions } from '@/options';
import { Configure } from '../config/configure'; import { Configure } from '../config/configure';
@ -6,11 +14,54 @@ import { Configure } from '../config/configure';
export class CoreModule { export class CoreModule {
static async forRoot(configure: Configure): Promise<DynamicModule> { static async forRoot(configure: Configure): Promise<DynamicModule> {
await configure.store('app.name'); await configure.store('app.name');
const providers: ModuleMetadata['providers'] = [];
const exports: ModuleMetadata['exports'] = [];
let imports: ModuleMetadata['imports'] = [];
const redis = createRedisOptions(await configure.get<RedisOptions>('redis'));
if (!isNil(redis)) {
providers.push({
provide: RedisService,
useFactory: () => {
const service = new RedisService(redis);
service.createClients();
return service;
},
});
exports.push(RedisService);
const queues = createQueueOptions(await configure.get<QueueOptions>('queue'), redis);
if (!isNil(queues)) {
if (isArray(queues)) {
imports = queues.map((v) => BullModule.forRoot(v.name, omit(v, 'name')));
} else {
imports.push(BullModule.forRoot(queues));
}
}
}
const sms = await configure.get<SmsOptions>('sms');
if (!isNil(sms)) {
providers.push({
provide: SmsService,
useFactory: () => new SmsService(sms),
});
exports.push(SmsService);
}
const smtp = await configure.get<SmtpOptions>('smtp');
if (!isNil(smtp)) {
providers.push({
provide: SmtpService,
useFactory: () => new SmtpService(smtp),
});
exports.push(SmtpService);
}
return { return {
module: CoreModule, module: CoreModule,
global: true, global: true,
providers: [], providers,
exports: [], exports,
imports,
}; };
} }
} }

View File

@ -0,0 +1,3 @@
export * from './redis.service';
export * from './sms.service';
export * from './smtp.service';

View File

@ -0,0 +1,36 @@
import { Injectable } from '@nestjs/common';
import Redis from 'ioredis';
import { isNil } from 'lodash';
import { RedisOption } from '@/modules/core/types';
@Injectable()
export class RedisService {
protected options: RedisOption[];
protected clients: Record<string, Redis> = {};
constructor(protected _options: RedisOption[]) {
this.options = _options;
}
async createClients() {
this.options.map(async (option) => {
this.clients[option.name] = new Redis(option);
});
}
getClient(name?: string): Redis {
const key = isNil(name) ? 'default' : name;
if (this.clients[key]) {
return this.clients[key];
}
throw new Error(`Unknown client ${key}`);
}
getClients() {
return this.clients;
}
}

View File

@ -5,7 +5,7 @@ import { NestFactory } from '@nestjs/core';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify'; import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { existsSync } from 'fs-extra'; import { existsSync } from 'fs-extra';
import { isNil } from 'lodash'; import { isArray, isNil, omit } from 'lodash';
import { RbacModule } from '@/modules/rbac/rbac.module'; import { RbacModule } from '@/modules/rbac/rbac.module';
import { UserModule } from '@/modules/user/user.module'; import { UserModule } from '@/modules/user/user.module';
@ -13,7 +13,13 @@ import { UserModule } from '@/modules/user/user.module';
import * as configs from './config'; import * as configs from './config';
import { ContentModule } from './modules/content/content.module'; import { ContentModule } from './modules/content/content.module';
import { GlobalExceptionFilter } from './modules/core/filters/global-exception.filter'; import { GlobalExceptionFilter } from './modules/core/filters/global-exception.filter';
import { CreateOptions, RedisOption, RedisOptions } from './modules/core/types'; import {
BullOptions,
CreateOptions,
QueueOptions,
RedisOption,
RedisOptions,
} from './modules/core/types';
import * as dbCommands from './modules/database/commands'; import * as dbCommands from './modules/database/commands';
import { DatabaseModule } from './modules/database/database.module'; import { DatabaseModule } from './modules/database/database.module';
import { MeiliModule } from './modules/meilisearch/meili.module'; import { MeiliModule } from './modules/meilisearch/meili.module';
@ -64,6 +70,9 @@ export const createOptions: CreateOptions = {
* @param options * @param options
*/ */
export const createRedisOptions = (options: RedisOptions) => { export const createRedisOptions = (options: RedisOptions) => {
if (isNil(options)) {
return undefined;
}
const config: Array<RedisOption> = Array.isArray(options) const config: Array<RedisOption> = Array.isArray(options)
? options ? options
: [{ ...options, name: 'default' }]; : [{ ...options, name: 'default' }];
@ -79,3 +88,31 @@ export const createRedisOptions = (options: RedisOptions) => {
return names.includes(n.name) ? o : [...o, n]; return names.includes(n.name) ? o : [...o, n];
}, []); }, []);
}; };
/**
* BullMQ模块的配置
* @param options
* @param redis
*/
export const createQueueOptions = (
options: QueueOptions,
redis: Array<RedisOption>,
): BullOptions | undefined => {
if (isNil(options) || isNil(redis)) {
return undefined;
}
const names = redis.map(({ name }) => name);
if (names.length < 1 || !names.includes('default')) {
return undefined;
}
if (isArray(options)) {
return options.map((option) => ({
...omit(option, 'redis'),
connection: redis.find(({ name: c }) => c === (option.redis ?? 'default')),
}));
}
return {
...omit(options, 'redis'),
connection: redis.find(({ name: c }) => c === (options.redis ?? 'default')),
};
};