feat: M0-02 Admin event management AAPI — queues overview + failed + retry
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 37s
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 37s
This commit is contained in:
parent
42e9e80f4c
commit
4c4d14724a
@ -16,6 +16,7 @@ import { AuthModule } from './modules/auth/auth.module';
|
||||
import { AdminAuthModule } from './modules/admin-auth/admin-auth.module';
|
||||
import { AdminDashboardModule } from './modules/admin-dashboard/admin-dashboard.module';
|
||||
import { AdminUsersModule } from './modules/admin-users/admin-users.module';
|
||||
import { AdminEventsModule } from './modules/admin-events/admin-events.module';
|
||||
import { AdminKnowledgeModule } from './modules/admin-knowledge/admin-knowledge.module';
|
||||
import { AdminCostsModule } from './modules/admin-costs/admin-costs.module';
|
||||
import { AdminBillingModule } from './modules/admin-billing/admin-billing.module';
|
||||
@ -96,6 +97,7 @@ import appleConfig from './config/apple.config';
|
||||
AdminAuthModule,
|
||||
AdminDashboardModule,
|
||||
AdminUsersModule,
|
||||
AdminEventsModule,
|
||||
AdminKnowledgeModule,
|
||||
AdminCostsModule,
|
||||
AdminBillingModule,
|
||||
|
||||
87
src/modules/admin-events/admin-events.controller.ts
Normal file
87
src/modules/admin-events/admin-events.controller.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import { Controller, Get, Post, Param, UseGuards } from '@nestjs/common';
|
||||
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
|
||||
import { InjectQueue, InjectFlowProducer } from '@nestjs/bullmq';
|
||||
import { Queue, FlowProducer, Job } from 'bullmq';
|
||||
import { AdminAuthGuard } from '../../common/guards/admin-auth.guard';
|
||||
import { AdminRolesGuard } from '../../common/guards/admin-roles.guard';
|
||||
import { AdminRoles } from '../../common/decorators/admin-roles.decorator';
|
||||
import type { AdminRole } from '../../common/types/admin-role.enum';
|
||||
|
||||
const QUEUES = ['ai-analysis', 'document-import', 'notification', 'domain-events'] as const;
|
||||
|
||||
@ApiTags('admin-events')
|
||||
@Controller('admin-api/events')
|
||||
@UseGuards(AdminAuthGuard, AdminRolesGuard)
|
||||
@ApiBearerAuth()
|
||||
export class AdminEventsController {
|
||||
constructor(
|
||||
@InjectQueue('ai-analysis') private aiQ: Queue,
|
||||
@InjectQueue('document-import') private importQ: Queue,
|
||||
@InjectQueue('notification') private notifyQ: Queue,
|
||||
@InjectQueue('domain-events') private eventQ: Queue,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
@AdminRoles('SUPER_ADMIN' as AdminRole)
|
||||
@ApiOperation({ summary: '队列概览' })
|
||||
async overview() {
|
||||
const queues = await Promise.all(
|
||||
QUEUES.map(async (name) => {
|
||||
const q = this.getQueue(name);
|
||||
const [waiting, active, completed, failed, delayed] = await Promise.all([
|
||||
q.getWaitingCount(), q.getActiveCount(), q.getCompletedCount(),
|
||||
q.getFailedCount(), q.getDelayedCount(),
|
||||
]);
|
||||
return { name, waiting, active, completed, failed, delayed, total: waiting + active + completed + failed + delayed };
|
||||
}),
|
||||
);
|
||||
return { queues };
|
||||
}
|
||||
|
||||
@Get(':queue/failed')
|
||||
@AdminRoles('SUPER_ADMIN' as AdminRole)
|
||||
@ApiOperation({ summary: '失败任务列表' })
|
||||
async failed(@Param('queue') queueName: string) {
|
||||
const q = this.getQueue(queueName);
|
||||
const jobs = await q.getFailed(0, 20);
|
||||
return { jobs: jobs.map(this.formatJob) };
|
||||
}
|
||||
|
||||
@Get(':queue/jobs/:jobId')
|
||||
@AdminRoles('SUPER_ADMIN' as AdminRole)
|
||||
@ApiOperation({ summary: '任务详情' })
|
||||
async jobDetail(@Param('queue') queueName: string, @Param('jobId') jobId: string) {
|
||||
const q = this.getQueue(queueName);
|
||||
const job = await q.getJob(jobId);
|
||||
if (!job) return { error: 'Job not found' };
|
||||
const state = await job.getState();
|
||||
return { ...this.formatJob(job), state, data: job.data, stacktrace: job.stacktrace };
|
||||
}
|
||||
|
||||
@Post(':queue/jobs/:jobId/retry')
|
||||
@AdminRoles('SUPER_ADMIN' as AdminRole)
|
||||
@ApiOperation({ summary: '重试失败任务' })
|
||||
async retry(@Param('queue') queueName: string, @Param('jobId') jobId: string) {
|
||||
const q = this.getQueue(queueName);
|
||||
const job = await q.getJob(jobId);
|
||||
if (!job) return { error: 'Job not found' };
|
||||
await job.retry();
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
private getQueue(name: string): Queue {
|
||||
const map: Record<string, Queue> = {
|
||||
'ai-analysis': this.aiQ, 'document-import': this.importQ,
|
||||
'notification': this.notifyQ, 'domain-events': this.eventQ,
|
||||
};
|
||||
return map[name] || this.eventQ;
|
||||
}
|
||||
|
||||
private formatJob(job: Job) {
|
||||
return {
|
||||
id: job.id, name: job.name, timestamp: job.timestamp,
|
||||
attemptsMade: job.attemptsMade, failedReason: job.failedReason?.slice(0, 200),
|
||||
finishedOn: job.finishedOn, processedOn: job.processedOn,
|
||||
};
|
||||
}
|
||||
}
|
||||
17
src/modules/admin-events/admin-events.module.ts
Normal file
17
src/modules/admin-events/admin-events.module.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { BullModule } from '@nestjs/bullmq';
|
||||
import { AdminEventsController } from './admin-events.controller';
|
||||
import { AdminAuthGuard } from '../../common/guards/admin-auth.guard';
|
||||
import { AdminRolesGuard } from '../../common/guards/admin-roles.guard';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
BullModule.registerQueue(
|
||||
{ name: 'ai-analysis' }, { name: 'document-import' },
|
||||
{ name: 'notification' }, { name: 'domain-events' },
|
||||
),
|
||||
],
|
||||
controllers: [AdminEventsController],
|
||||
providers: [AdminAuthGuard, AdminRolesGuard],
|
||||
})
|
||||
export class AdminEventsModule {}
|
||||
Loading…
x
Reference in New Issue
Block a user