feat: 添加用户任务限制检查功能
- 在 executeTemplateByCode 方法中添加用户当前任务数量限制检查,确保用户在执行新任务前不超过最大并发任务数。 - 新增 checkUserTaskLimit 方法,查询用户正在进行的任务并判断是否满足执行条件。 - 更新 Swagger API 文档,添加任务数量限制的响应示例。
This commit is contained in:
parent
1e31514f11
commit
6307b216d6
|
|
@ -34,7 +34,11 @@ import {
|
||||||
TemplateListDto,
|
TemplateListDto,
|
||||||
BatchExecuteDto,
|
BatchExecuteDto,
|
||||||
} from '../dto/template.dto';
|
} from '../dto/template.dto';
|
||||||
import { TemplateExecutionEntity, ExecutionStatus, ExecutionType } from '../entities/template-execution.entity';
|
import {
|
||||||
|
TemplateExecutionEntity,
|
||||||
|
ExecutionStatus,
|
||||||
|
ExecutionType,
|
||||||
|
} from '../entities/template-execution.entity';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { ApiCommonResponses } from '../decorators/api-common-responses.decorator';
|
import { ApiCommonResponses } from '../decorators/api-common-responses.decorator';
|
||||||
|
|
@ -51,7 +55,7 @@ export class TemplateController {
|
||||||
private readonly templateRepository: Repository<N8nTemplateEntity>,
|
private readonly templateRepository: Repository<N8nTemplateEntity>,
|
||||||
@InjectRepository(TemplateExecutionEntity)
|
@InjectRepository(TemplateExecutionEntity)
|
||||||
private readonly executionRepository: Repository<TemplateExecutionEntity>,
|
private readonly executionRepository: Repository<TemplateExecutionEntity>,
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
@Post(':templateId/execute')
|
@Post(':templateId/execute')
|
||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
|
|
@ -127,10 +131,22 @@ export class TemplateController {
|
||||||
description: '执行成功',
|
description: '执行成功',
|
||||||
type: TemplateExecuteResponseDto,
|
type: TemplateExecuteResponseDto,
|
||||||
})
|
})
|
||||||
|
@SwaggerApiResponse({
|
||||||
|
status: 429,
|
||||||
|
description: '任务数量限制',
|
||||||
|
schema: {
|
||||||
|
example: {
|
||||||
|
code: 429,
|
||||||
|
message:
|
||||||
|
'当前账号有3个任务正在进行中,且距开始时间不足5分钟,请稍后再试',
|
||||||
|
data: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
async executeTemplateByCode(
|
async executeTemplateByCode(
|
||||||
@Param('code') code: string,
|
@Param('code') code: string,
|
||||||
@Body() body: { imageUrl: string },
|
@Body() body: { imageUrl: string },
|
||||||
@Request() req
|
@Request() req,
|
||||||
): Promise<ApiResponse<number>> {
|
): Promise<ApiResponse<number>> {
|
||||||
try {
|
try {
|
||||||
const { imageUrl } = body;
|
const { imageUrl } = body;
|
||||||
|
|
@ -139,6 +155,11 @@ export class TemplateController {
|
||||||
throw new HttpException('imageUrl is required', HttpStatus.BAD_REQUEST);
|
throw new HttpException('imageUrl is required', HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const userId = req.user.userId;
|
||||||
|
|
||||||
|
// 检查用户当前的任务限制
|
||||||
|
await this.checkUserTaskLimit(userId);
|
||||||
|
|
||||||
// 首先获取模板配置以确定模板类型
|
// 首先获取模板配置以确定模板类型
|
||||||
const templateConfig = await this.templateFactory.getTemplateByCode(code);
|
const templateConfig = await this.templateFactory.getTemplateByCode(code);
|
||||||
if (!templateConfig) {
|
if (!templateConfig) {
|
||||||
|
|
@ -150,12 +171,14 @@ export class TemplateController {
|
||||||
const taskId = await template.execute(imageUrl);
|
const taskId = await template.execute(imageUrl);
|
||||||
|
|
||||||
// 将任务保存到 TemplateExecutionEntity
|
// 将任务保存到 TemplateExecutionEntity
|
||||||
const userId = req.user.userId;
|
|
||||||
const execution = this.executionRepository.create({
|
const execution = this.executionRepository.create({
|
||||||
templateId: templateConfig.id,
|
templateId: templateConfig.id,
|
||||||
userId,
|
userId,
|
||||||
platform: req.user.platform,
|
platform: req.user.platform,
|
||||||
type: templateConfig.templateType === TemplateType.VIDEO ? ExecutionType.VIDEO : ExecutionType.IMAGE,
|
type:
|
||||||
|
templateConfig.templateType === TemplateType.VIDEO
|
||||||
|
? ExecutionType.VIDEO
|
||||||
|
: ExecutionType.IMAGE,
|
||||||
prompt: '', // 可以从请求参数中获取,如果有的话
|
prompt: '', // 可以从请求参数中获取,如果有的话
|
||||||
inputImageUrl: imageUrl,
|
inputImageUrl: imageUrl,
|
||||||
taskId: taskId, // 保存外部系统返回的任务ID,用于回调匹配
|
taskId: taskId, // 保存外部系统返回的任务ID,用于回调匹配
|
||||||
|
|
@ -170,7 +193,7 @@ export class TemplateController {
|
||||||
// 返回任务id (执行记录的ID)
|
// 返回任务id (执行记录的ID)
|
||||||
return ResponseUtil.success(savedExecution.id, '模板执行已启动');
|
return ResponseUtil.success(savedExecution.id, '模板执行已启动');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error);
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Template execution failed',
|
error.message || 'Template execution failed',
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
|
@ -178,6 +201,47 @@ export class TemplateController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查用户当前任务限制
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @throws HttpException 如果超出任务限制
|
||||||
|
*/
|
||||||
|
private async checkUserTaskLimit(userId: string): Promise<void> {
|
||||||
|
// 查询用户当前进行中的任务
|
||||||
|
const processingTasks = await this.executionRepository.find({
|
||||||
|
where: {
|
||||||
|
userId,
|
||||||
|
status: ExecutionStatus.PROCESSING,
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
startedAt: 'ASC',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 如果当前没有进行中的任务,允许执行
|
||||||
|
if (processingTasks.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果当前进行中任务数量已达到3个,需要检查时间限制
|
||||||
|
if (processingTasks.length >= 3) {
|
||||||
|
const now = new Date();
|
||||||
|
const fiveMinutesAgo = new Date(now.getTime() - 5 * 60 * 1000);
|
||||||
|
|
||||||
|
// 检查是否有任务在5分钟内开始
|
||||||
|
const recentTasks = processingTasks.filter(
|
||||||
|
(task) => task.startedAt && task.startedAt > fiveMinutesAgo,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (recentTasks.length > 0) {
|
||||||
|
throw new HttpException(
|
||||||
|
`有${processingTasks.length}个任务正在进行中,请稍后再试`,
|
||||||
|
HttpStatus.TOO_MANY_REQUESTS,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Post(':templateId/batch-execute')
|
@Post(':templateId/batch-execute')
|
||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: '批量执行模板',
|
summary: '批量执行模板',
|
||||||
|
|
@ -432,7 +496,9 @@ export class TemplateController {
|
||||||
* @returns 执行进度信息
|
* @returns 执行进度信息
|
||||||
*/
|
*/
|
||||||
@Get('execution/:taskId/progress')
|
@Get('execution/:taskId/progress')
|
||||||
async getExecutionProgress(@Param('taskId', ParseIntPipe) taskId: number): Promise<ApiResponse<any>> {
|
async getExecutionProgress(
|
||||||
|
@Param('taskId', ParseIntPipe) taskId: number,
|
||||||
|
): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const execution = await this.executionRepository.findOne({
|
const execution = await this.executionRepository.findOne({
|
||||||
where: { id: taskId },
|
where: { id: taskId },
|
||||||
|
|
@ -446,7 +512,8 @@ export class TemplateController {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseUtil.success({
|
return ResponseUtil.success(
|
||||||
|
{
|
||||||
taskId: execution.id,
|
taskId: execution.id,
|
||||||
templateId: execution.templateId,
|
templateId: execution.templateId,
|
||||||
templateName: execution.template?.name,
|
templateName: execution.template?.name,
|
||||||
|
|
@ -465,8 +532,10 @@ export class TemplateController {
|
||||||
executionDuration: execution.executionDuration,
|
executionDuration: execution.executionDuration,
|
||||||
createdAt: execution.createdAt,
|
createdAt: execution.createdAt,
|
||||||
updatedAt: execution.updatedAt,
|
updatedAt: execution.updatedAt,
|
||||||
executionResult: execution.executionResult
|
executionResult: execution.executionResult,
|
||||||
}, '获取执行进度成功');
|
},
|
||||||
|
'获取执行进度成功',
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof HttpException) {
|
if (error instanceof HttpException) {
|
||||||
throw error;
|
throw error;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue