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 { AdminAuthModule } from './modules/admin-auth/admin-auth.module';
|
||||||
import { AdminDashboardModule } from './modules/admin-dashboard/admin-dashboard.module';
|
import { AdminDashboardModule } from './modules/admin-dashboard/admin-dashboard.module';
|
||||||
import { AdminUsersModule } from './modules/admin-users/admin-users.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 { AdminKnowledgeModule } from './modules/admin-knowledge/admin-knowledge.module';
|
||||||
import { AdminCostsModule } from './modules/admin-costs/admin-costs.module';
|
import { AdminCostsModule } from './modules/admin-costs/admin-costs.module';
|
||||||
import { AdminBillingModule } from './modules/admin-billing/admin-billing.module';
|
import { AdminBillingModule } from './modules/admin-billing/admin-billing.module';
|
||||||
@ -96,6 +97,7 @@ import appleConfig from './config/apple.config';
|
|||||||
AdminAuthModule,
|
AdminAuthModule,
|
||||||
AdminDashboardModule,
|
AdminDashboardModule,
|
||||||
AdminUsersModule,
|
AdminUsersModule,
|
||||||
|
AdminEventsModule,
|
||||||
AdminKnowledgeModule,
|
AdminKnowledgeModule,
|
||||||
AdminCostsModule,
|
AdminCostsModule,
|
||||||
AdminBillingModule,
|
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