redisForJobQueue の接続を使い回す (MisskeyIO#268)

This commit is contained in:
riku6460 2023-11-27 20:03:00 +09:00 committed by GitHub
parent 107cd9788e
commit 7122657f13
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 54 additions and 33 deletions

View file

@ -79,11 +79,22 @@ const $redisForTimelines: Provider = {
inject: [DI.config], inject: [DI.config],
}; };
const $redisForJobQueue: Provider = {
provide: DI.redisForJobQueue,
useFactory: (config: Config) => {
return new Redis.Redis({
...config.redisForJobQueue,
keyPrefix: undefined,
});
},
inject: [DI.config],
};
@Global() @Global()
@Module({ @Module({
imports: [RepositoryModule], imports: [RepositoryModule],
providers: [$config, $db, $meilisearch, $redis, $redisForPub, $redisForSub, $redisForTimelines], providers: [$config, $db, $meilisearch, $redis, $redisForPub, $redisForSub, $redisForTimelines, $redisForJobQueue],
exports: [$config, $db, $meilisearch, $redis, $redisForPub, $redisForSub, $redisForTimelines, RepositoryModule], exports: [$config, $db, $meilisearch, $redis, $redisForPub, $redisForSub, $redisForTimelines, $redisForJobQueue, RepositoryModule],
}) })
export class GlobalModule implements OnApplicationShutdown { export class GlobalModule implements OnApplicationShutdown {
constructor( constructor(
@ -92,6 +103,7 @@ export class GlobalModule implements OnApplicationShutdown {
@Inject(DI.redisForPub) private redisForPub: Redis.Redis, @Inject(DI.redisForPub) private redisForPub: Redis.Redis,
@Inject(DI.redisForSub) private redisForSub: Redis.Redis, @Inject(DI.redisForSub) private redisForSub: Redis.Redis,
@Inject(DI.redisForTimelines) private redisForTimelines: Redis.Redis, @Inject(DI.redisForTimelines) private redisForTimelines: Redis.Redis,
@Inject(DI.redisForJobQueue) private redisForJobQueue: Redis.Redis,
) {} ) {}
public async dispose(): Promise<void> { public async dispose(): Promise<void> {
@ -109,6 +121,7 @@ export class GlobalModule implements OnApplicationShutdown {
this.redisForPub.disconnect(), this.redisForPub.disconnect(),
this.redisForSub.disconnect(), this.redisForSub.disconnect(),
this.redisForTimelines.disconnect(), this.redisForTimelines.disconnect(),
this.redisForJobQueue.disconnect(),
]); ]);
} }

View file

@ -6,6 +6,7 @@
import { setTimeout } from 'node:timers/promises'; import { setTimeout } from 'node:timers/promises';
import { Inject, Module, OnApplicationShutdown } from '@nestjs/common'; import { Inject, Module, OnApplicationShutdown } from '@nestjs/common';
import * as Bull from 'bullmq'; import * as Bull from 'bullmq';
import * as Redis from 'ioredis';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import { QUEUE, baseQueueOptions } from '@/queue/const.js'; import { QUEUE, baseQueueOptions } from '@/queue/const.js';
@ -23,50 +24,50 @@ export type WebhookDeliverQueue = Bull.Queue<WebhookDeliverJobData>;
const $system: Provider = { const $system: Provider = {
provide: 'queue:system', provide: 'queue:system',
useFactory: (config: Config) => new Bull.Queue(QUEUE.SYSTEM, baseQueueOptions(config, QUEUE.SYSTEM)), useFactory: (config: Config, redisForJobQueue: Redis.Redis) => new Bull.Queue(QUEUE.SYSTEM, baseQueueOptions(config, QUEUE.SYSTEM, redisForJobQueue)),
inject: [DI.config], inject: [DI.config, DI.redisForJobQueue],
}; };
const $endedPollNotification: Provider = { const $endedPollNotification: Provider = {
provide: 'queue:endedPollNotification', provide: 'queue:endedPollNotification',
useFactory: (config: Config) => new Bull.Queue(QUEUE.ENDED_POLL_NOTIFICATION, baseQueueOptions(config, QUEUE.ENDED_POLL_NOTIFICATION)), useFactory: (config: Config, redisForJobQueue: Redis.Redis) => new Bull.Queue(QUEUE.ENDED_POLL_NOTIFICATION, baseQueueOptions(config, QUEUE.ENDED_POLL_NOTIFICATION, redisForJobQueue)),
inject: [DI.config], inject: [DI.config, DI.redisForJobQueue],
}; };
const $deliver: Provider = { const $deliver: Provider = {
provide: 'queue:deliver', provide: 'queue:deliver',
useFactory: (config: Config) => new Bull.Queue(QUEUE.DELIVER, baseQueueOptions(config, QUEUE.DELIVER)), useFactory: (config: Config, redisForJobQueue: Redis.Redis) => new Bull.Queue(QUEUE.DELIVER, baseQueueOptions(config, QUEUE.DELIVER, redisForJobQueue)),
inject: [DI.config], inject: [DI.config, DI.redisForJobQueue],
}; };
const $inbox: Provider = { const $inbox: Provider = {
provide: 'queue:inbox', provide: 'queue:inbox',
useFactory: (config: Config) => new Bull.Queue(QUEUE.INBOX, baseQueueOptions(config, QUEUE.INBOX)), useFactory: (config: Config, redisForJobQueue: Redis.Redis) => new Bull.Queue(QUEUE.INBOX, baseQueueOptions(config, QUEUE.INBOX, redisForJobQueue)),
inject: [DI.config], inject: [DI.config, DI.redisForJobQueue],
}; };
const $db: Provider = { const $db: Provider = {
provide: 'queue:db', provide: 'queue:db',
useFactory: (config: Config) => new Bull.Queue(QUEUE.DB, baseQueueOptions(config, QUEUE.DB)), useFactory: (config: Config, redisForJobQueue: Redis.Redis) => new Bull.Queue(QUEUE.DB, baseQueueOptions(config, QUEUE.DB, redisForJobQueue)),
inject: [DI.config], inject: [DI.config, DI.redisForJobQueue],
}; };
const $relationship: Provider = { const $relationship: Provider = {
provide: 'queue:relationship', provide: 'queue:relationship',
useFactory: (config: Config) => new Bull.Queue(QUEUE.RELATIONSHIP, baseQueueOptions(config, QUEUE.RELATIONSHIP)), useFactory: (config: Config, redisForJobQueue: Redis.Redis) => new Bull.Queue(QUEUE.RELATIONSHIP, baseQueueOptions(config, QUEUE.RELATIONSHIP, redisForJobQueue)),
inject: [DI.config], inject: [DI.config, DI.redisForJobQueue],
}; };
const $objectStorage: Provider = { const $objectStorage: Provider = {
provide: 'queue:objectStorage', provide: 'queue:objectStorage',
useFactory: (config: Config) => new Bull.Queue(QUEUE.OBJECT_STORAGE, baseQueueOptions(config, QUEUE.OBJECT_STORAGE)), useFactory: (config: Config, redisForJobQueue: Redis.Redis) => new Bull.Queue(QUEUE.OBJECT_STORAGE, baseQueueOptions(config, QUEUE.OBJECT_STORAGE, redisForJobQueue)),
inject: [DI.config], inject: [DI.config, DI.redisForJobQueue],
}; };
const $webhookDeliver: Provider = { const $webhookDeliver: Provider = {
provide: 'queue:webhookDeliver', provide: 'queue:webhookDeliver',
useFactory: (config: Config) => new Bull.Queue(QUEUE.WEBHOOK_DELIVER, baseQueueOptions(config, QUEUE.WEBHOOK_DELIVER)), useFactory: (config: Config, redisForJobQueue: Redis.Redis) => new Bull.Queue(QUEUE.WEBHOOK_DELIVER, baseQueueOptions(config, QUEUE.WEBHOOK_DELIVER, redisForJobQueue)),
inject: [DI.config], inject: [DI.config, DI.redisForJobQueue],
}; };
@Module({ @Module({

View file

@ -6,6 +6,7 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import Xev from 'xev'; import Xev from 'xev';
import * as Bull from 'bullmq'; import * as Bull from 'bullmq';
import * as Redis from 'ioredis';
import { QueueService } from '@/core/QueueService.js'; import { QueueService } from '@/core/QueueService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
@ -25,6 +26,9 @@ export class QueueStatsService implements OnApplicationShutdown {
@Inject(DI.config) @Inject(DI.config)
private config: Config, private config: Config,
@Inject(DI.redisForJobQueue)
private redisForJobQueue: Redis.Redis,
private queueService: QueueService, private queueService: QueueService,
) { ) {
} }
@ -43,8 +47,8 @@ export class QueueStatsService implements OnApplicationShutdown {
let activeDeliverJobs = 0; let activeDeliverJobs = 0;
let activeInboxJobs = 0; let activeInboxJobs = 0;
const deliverQueueEvents = new Bull.QueueEvents(QUEUE.DELIVER, baseQueueOptions(this.config, QUEUE.DELIVER)); const deliverQueueEvents = new Bull.QueueEvents(QUEUE.DELIVER, baseQueueOptions(this.config, QUEUE.DELIVER, this.redisForJobQueue));
const inboxQueueEvents = new Bull.QueueEvents(QUEUE.INBOX, baseQueueOptions(this.config, QUEUE.INBOX)); const inboxQueueEvents = new Bull.QueueEvents(QUEUE.INBOX, baseQueueOptions(this.config, QUEUE.INBOX, this.redisForJobQueue));
deliverQueueEvents.on('active', () => { deliverQueueEvents.on('active', () => {
activeDeliverJobs++; activeDeliverJobs++;

View file

@ -11,6 +11,7 @@ export const DI = {
redisForPub: Symbol('redisForPub'), redisForPub: Symbol('redisForPub'),
redisForSub: Symbol('redisForSub'), redisForSub: Symbol('redisForSub'),
redisForTimelines: Symbol('redisForTimelines'), redisForTimelines: Symbol('redisForTimelines'),
redisForJobQueue: Symbol('redisForJobQueue'),
//#region Repositories //#region Repositories
usersRepository: Symbol('usersRepository'), usersRepository: Symbol('usersRepository'),

View file

@ -5,6 +5,7 @@
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
import * as Bull from 'bullmq'; import * as Bull from 'bullmq';
import * as Redis from 'ioredis';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
@ -84,6 +85,9 @@ export class QueueProcessorService implements OnApplicationShutdown {
@Inject(DI.config) @Inject(DI.config)
private config: Config, private config: Config,
@Inject(DI.redisForJobQueue)
private redisForJobQueue: Redis.Redis,
private queueLoggerService: QueueLoggerService, private queueLoggerService: QueueLoggerService,
private webhookDeliverProcessorService: WebhookDeliverProcessorService, private webhookDeliverProcessorService: WebhookDeliverProcessorService,
private endedPollNotificationProcessorService: EndedPollNotificationProcessorService, private endedPollNotificationProcessorService: EndedPollNotificationProcessorService,
@ -146,7 +150,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
default: throw new Error(`unrecognized job type ${job.name} for system`); default: throw new Error(`unrecognized job type ${job.name} for system`);
} }
}, { }, {
...baseQueueOptions(this.config, QUEUE.SYSTEM), ...baseQueueOptions(this.config, QUEUE.SYSTEM, this.redisForJobQueue),
autorun: false, autorun: false,
}); });
@ -185,7 +189,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
default: throw new Error(`unrecognized job type ${job.name} for db`); default: throw new Error(`unrecognized job type ${job.name} for db`);
} }
}, { }, {
...baseQueueOptions(this.config, QUEUE.DB), ...baseQueueOptions(this.config, QUEUE.DB, this.redisForJobQueue),
autorun: false, autorun: false,
}); });
@ -201,7 +205,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
//#region deliver //#region deliver
this.deliverQueueWorker = new Bull.Worker(QUEUE.DELIVER, (job) => this.deliverProcessorService.process(job), { this.deliverQueueWorker = new Bull.Worker(QUEUE.DELIVER, (job) => this.deliverProcessorService.process(job), {
...baseQueueOptions(this.config, QUEUE.DELIVER), ...baseQueueOptions(this.config, QUEUE.DELIVER, this.redisForJobQueue),
autorun: false, autorun: false,
concurrency: this.config.deliverJobConcurrency ?? 128, concurrency: this.config.deliverJobConcurrency ?? 128,
limiter: { limiter: {
@ -225,7 +229,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
//#region inbox //#region inbox
this.inboxQueueWorker = new Bull.Worker(QUEUE.INBOX, (job) => this.inboxProcessorService.process(job), { this.inboxQueueWorker = new Bull.Worker(QUEUE.INBOX, (job) => this.inboxProcessorService.process(job), {
...baseQueueOptions(this.config, QUEUE.INBOX), ...baseQueueOptions(this.config, QUEUE.INBOX, this.redisForJobQueue),
autorun: false, autorun: false,
concurrency: this.config.inboxJobConcurrency ?? 16, concurrency: this.config.inboxJobConcurrency ?? 16,
limiter: { limiter: {
@ -249,7 +253,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
//#region webhook deliver //#region webhook deliver
this.webhookDeliverQueueWorker = new Bull.Worker(QUEUE.WEBHOOK_DELIVER, (job) => this.webhookDeliverProcessorService.process(job), { this.webhookDeliverQueueWorker = new Bull.Worker(QUEUE.WEBHOOK_DELIVER, (job) => this.webhookDeliverProcessorService.process(job), {
...baseQueueOptions(this.config, QUEUE.WEBHOOK_DELIVER), ...baseQueueOptions(this.config, QUEUE.WEBHOOK_DELIVER, this.redisForJobQueue),
autorun: false, autorun: false,
concurrency: 64, concurrency: 64,
limiter: { limiter: {
@ -281,7 +285,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
default: throw new Error(`unrecognized job type ${job.name} for relationship`); default: throw new Error(`unrecognized job type ${job.name} for relationship`);
} }
}, { }, {
...baseQueueOptions(this.config, QUEUE.RELATIONSHIP), ...baseQueueOptions(this.config, QUEUE.RELATIONSHIP, this.redisForJobQueue),
autorun: false, autorun: false,
concurrency: this.config.relashionshipJobConcurrency ?? 16, concurrency: this.config.relashionshipJobConcurrency ?? 16,
limiter: { limiter: {
@ -308,7 +312,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
default: throw new Error(`unrecognized job type ${job.name} for objectStorage`); default: throw new Error(`unrecognized job type ${job.name} for objectStorage`);
} }
}, { }, {
...baseQueueOptions(this.config, QUEUE.OBJECT_STORAGE), ...baseQueueOptions(this.config, QUEUE.OBJECT_STORAGE, this.redisForJobQueue),
autorun: false, autorun: false,
concurrency: 16, concurrency: 16,
}); });
@ -325,7 +329,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
//#region ended poll notification //#region ended poll notification
this.endedPollNotificationQueueWorker = new Bull.Worker(QUEUE.ENDED_POLL_NOTIFICATION, (job) => this.endedPollNotificationProcessorService.process(job), { this.endedPollNotificationQueueWorker = new Bull.Worker(QUEUE.ENDED_POLL_NOTIFICATION, (job) => this.endedPollNotificationProcessorService.process(job), {
...baseQueueOptions(this.config, QUEUE.ENDED_POLL_NOTIFICATION), ...baseQueueOptions(this.config, QUEUE.ENDED_POLL_NOTIFICATION, this.redisForJobQueue),
autorun: false, autorun: false,
}); });
//#endregion //#endregion

View file

@ -5,6 +5,7 @@
import { Config } from '@/config.js'; import { Config } from '@/config.js';
import type * as Bull from 'bullmq'; import type * as Bull from 'bullmq';
import type * as Redis from 'ioredis';
export const QUEUE = { export const QUEUE = {
DELIVER: 'deliver', DELIVER: 'deliver',
@ -17,12 +18,9 @@ export const QUEUE = {
WEBHOOK_DELIVER: 'webhookDeliver', WEBHOOK_DELIVER: 'webhookDeliver',
}; };
export function baseQueueOptions(config: Config, queueName: typeof QUEUE[keyof typeof QUEUE]): Bull.QueueOptions { export function baseQueueOptions(config: Config, queueName: typeof QUEUE[keyof typeof QUEUE], redisConnection: Redis.Redis): Bull.QueueOptions {
return { return {
connection: { connection: redisConnection,
...config.redisForJobQueue,
keyPrefix: undefined,
},
prefix: config.redisForJobQueue.prefix ? `${config.redisForJobQueue.prefix}:queue:${queueName}` : `queue:${queueName}`, prefix: config.redisForJobQueue.prefix ? `${config.redisForJobQueue.prefix}:queue:${queueName}` : `queue:${queueName}`,
}; };
} }