一键导入
add-queue-job
Add a new BullMQ job queue to the project — processor, producer injection, module registration, Bull Board integration, and unit tests.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Add a new BullMQ job queue to the project — processor, producer injection, module registration, Bull Board integration, and unit tests.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Create an End-to-End (E2E) test for a REST controller or GraphQL resolver using Fastify injection.
Write unit tests for an existing NestJS service, resolver, or controller in the project following its Vitest + NestJS Testing conventions.
Run the full code quality pipeline (TypeScript + Biome + Knip), fix all issues, and clean up comments in changed code.
Create a git commit with all unstaged changes. Use this skill whenever the user asks to commit, make a commit, save changes to git, or says something like "commit this", "commit all changes". Always runs npm run check before committing and fixes any errors found.
Use this workflow to implement ANY new feature following Test-Driven Development strictly.
Guide through a full Prisma schema change workflow — edit schema, create migration, regenerate client, update affected services.
| name | add-queue-job |
| description | Add a new BullMQ job queue to the project — processor, producer injection, module registration, Bull Board integration, and unit tests. |
The user wants to add a new BullMQ job queue to the project. They will provide the queue name and describe what the job should do.
@nestjs/bullmq (NestJS wrapper) + bullmqBullModule.forRootAsync in app.module.ts@bull-board/nestjs — each queue must register itself theresrc/infrastructure/test-queue/src/infrastructure/<queue-name>/
<queue-name>.module.ts
<queue-name>.processor.ts
<queue-name>.service.ts (producer — injectable into other modules)
<queue-name>.spec.ts
If the queue is tightly coupled to a business module, place it in src/modules/<module>/ instead.
<queue-name>.processor.tsimport { Processor, WorkerHost } from '@nestjs/bullmq';
import { Logger } from '@nestjs/common';
import { Job } from 'bullmq';
export interface <QueueName>JobData {
// define typed job payload here
}
@Processor('<queue-name>')
export class <QueueName>Processor extends WorkerHost {
private readonly logger = new Logger(<QueueName>Processor.name);
async process(job: Job<<QueueName>JobData>): Promise<unknown> {
this.logger.log(`Processing job ${job.id} (${job.name})`);
// job logic here
this.logger.log(`Finished job ${job.id}`);
return { result: 'Success' };
}
}
<queue-name>.service.ts (producer)import { InjectQueue } from '@nestjs/bullmq';
import { Injectable } from '@nestjs/common';
import { Queue } from 'bullmq';
import { <QueueName>JobData } from './<queue-name>.processor';
@Injectable()
export class <QueueName>Service {
constructor(
@InjectQueue('<queue-name>') private readonly queue: Queue,
) {}
async add<JobName>(data: <QueueName>JobData): Promise<void> {
await this.queue.add('<job-name>', data);
}
}
<queue-name>.module.tsimport { BullMQAdapter } from '@bull-board/api/bullMQAdapter';
import { BullBoardModule } from '@bull-board/nestjs';
import { BullModule } from '@nestjs/bullmq';
import { Module } from '@nestjs/common';
import { <QueueName>Processor } from './<queue-name>.processor';
import { <QueueName>Service } from './<queue-name>.service';
@Module({
imports: [
BullModule.registerQueue({
name: '<queue-name>',
}),
BullBoardModule.forFeature({
name: '<queue-name>',
adapter: BullMQAdapter,
}),
],
providers: [<QueueName>Processor, <QueueName>Service],
exports: [<QueueName>Service],
})
export class <QueueName>Module {}
<queue-name>.spec.tsimport { Logger } from '@nestjs/common';
import { Job } from 'bullmq';
import { Test } from '@nestjs/testing';
import { getQueueToken } from '@nestjs/bullmq';
// Globals (describe, it, expect, vi, beforeEach, afterEach) are available without import (vitest globals: true)
// Import path to mocks is relative — adjust depth based on file location:
// src/infrastructure/<queue-name>/ → '../../../test/utils/mocks'
// src/modules/<module>/ → '../../../test/utils/mocks'
import { createJobMock } from '../../../test/utils/mocks';
import { <QueueName>Processor } from './<queue-name>.processor';
import { <QueueName>Service } from './<queue-name>.service';
describe('<QueueName>Processor', () => {
let processor: <QueueName>Processor;
const buildJob = (data?: Partial<Job>): Job => {
const job = createJobMock();
job.id = data?.id ?? '1';
job.name = data?.name ?? '<job-name>';
job.data = data?.data ?? { /* default test data */ };
return job;
};
beforeEach(() => {
processor = new <QueueName>Processor();
});
afterEach(() => {
vi.clearAllMocks();
});
it('should process job and return success', async () => {
const result = await processor.process(buildJob());
expect(result).toEqual({ result: 'Success' });
});
it('should log start and finish', async () => {
const logSpy = vi.spyOn(Logger.prototype, 'log');
const job = buildJob();
await processor.process(job);
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(String(job.id)));
});
});
describe('<QueueName>Service', () => {
let service: <QueueName>Service;
const mockQueue = {
add: vi.fn().mockResolvedValue(undefined),
};
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [
<QueueName>Service,
{
provide: getQueueToken('<queue-name>'),
useValue: mockQueue,
},
],
}).compile();
service = module.get(<QueueName>Service);
});
afterEach(() => {
vi.clearAllMocks();
});
it('should add job to queue', async () => {
// Replace add<JobName> with the actual method name, e.g. addEmail, addReport
await service.add<JobName>({ /* test data matching <QueueName>JobData */ } as <QueueName>JobData);
expect(mockQueue.add).toHaveBeenCalledWith('<job-name>', expect.any(Object));
});
});
Add the new module to src/app.module.ts imports array:
import { <QueueName>Module } from '@/infrastructure/<queue-name>/<queue-name>.module';
// in @Module imports:
<QueueName>Module,
app.module.tsnpm run check to verify everything compiles