kt-template-online-api/src/modules/qqbot/plugin-platform/application/task/qqbot-plugin-task.service.ts

148 lines
4.7 KiB
TypeScript

import { Injectable, Optional } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import {
Between,
FindOptionsWhere,
LessThanOrEqual,
MoreThanOrEqual,
Repository,
} from 'typeorm';
import { throwVbenError, ToolsService } from '@/common';
import {
QqbotPlugin,
QqbotPluginTask,
QqbotPluginTaskRun,
} from '../../infrastructure/persistence';
import { requireQqbotPluginTaskCron } from './qqbot-plugin-task-cron.validator';
import type {
QqbotPluginTaskPageQuery,
QqbotPluginTaskRunPageQuery,
} from './qqbot-plugin-task.types';
import { QqbotPluginTaskSchedulerService } from './qqbot-plugin-task-scheduler.service';
@Injectable()
export class QqbotPluginTaskService {
constructor(
@InjectRepository(QqbotPluginTask)
private readonly taskRepository: Repository<QqbotPluginTask>,
@InjectRepository(QqbotPluginTaskRun)
private readonly runRepository: Repository<QqbotPluginTaskRun>,
@InjectRepository(QqbotPlugin)
private readonly pluginRepository: Repository<QqbotPlugin>,
private readonly toolsService: ToolsService,
@Optional()
private readonly scheduler?: QqbotPluginTaskSchedulerService,
) {}
async pageTasks(query: QqbotPluginTaskPageQuery) {
const { pageNo, pageSize, skip } = this.toolsService.getPageParams(query);
const where: FindOptionsWhere<QqbotPluginTask> = {};
const pluginId = await this.resolvePluginIdFilter(query);
if (pluginId) where.pluginId = pluginId;
if (query.taskKey) where.taskKey = query.taskKey;
if (query.status) where.runtimeStatus = query.status;
if (query.enabled !== undefined) {
where.enabled = this.toolsService.normalizeBoolean(query.enabled);
}
const [list, total] = await this.taskRepository.findAndCount({
order: { createTime: 'DESC' },
skip,
take: pageSize,
where,
});
return { list, pageNo, pageSize, total };
}
async getTaskDetail(id: string) {
const task = await this.taskRepository.findOne({ where: { id } });
if (!task) throwVbenError('插件定时任务不存在');
return task;
}
async enableTask(id: string) {
const task = await this.getTaskDetail(id);
task.enabled = true;
task.runtimeStatus = 'scheduled';
const saved = await this.taskRepository.save(task);
await this.requireScheduler().syncTaskScheduler(saved);
return saved;
}
async disableTask(id: string) {
const task = await this.getTaskDetail(id);
task.enabled = false;
task.runtimeStatus = 'disabled';
const saved = await this.taskRepository.save(task);
await this.requireScheduler().removeTaskScheduler(id);
return saved;
}
async updateTaskCron(id: string, body: { cronExpression?: string }) {
const task = await this.getTaskDetail(id);
task.cronExpression = requireQqbotPluginTaskCron(body.cronExpression);
const saved = await this.taskRepository.save(task);
await this.requireScheduler().syncTaskScheduler(saved);
return saved;
}
async runTaskOnce(id: string, body: { input?: Record<string, unknown> }) {
await this.getTaskDetail(id);
const job = await this.requireScheduler().enqueueManualRun(
id,
body.input || {},
);
return { jobId: `${job.id || ''}`, taskId: id };
}
async pageTaskRuns(id: string, query: QqbotPluginTaskRunPageQuery) {
const { pageNo, pageSize, skip } = this.toolsService.getPageParams(query);
const where: FindOptionsWhere<QqbotPluginTaskRun> = { taskId: id };
if (query.status) where.status = query.status;
if (query.triggerType) where.triggerType = query.triggerType;
Object.assign(where, this.buildRunTimeFilter(query));
const [list, total] = await this.runRepository.findAndCount({
order: { createTime: 'DESC' },
skip,
take: pageSize,
where,
});
return { list, pageNo, pageSize, total };
}
private async resolvePluginIdFilter(query: QqbotPluginTaskPageQuery) {
if (query.pluginId) return query.pluginId;
if (!query.pluginKey) return undefined;
const plugin = await this.pluginRepository.findOne({
where: { pluginKey: query.pluginKey },
});
return plugin?.id || '__missing_plugin__';
}
private buildRunTimeFilter(query: QqbotPluginTaskRunPageQuery) {
if (query.startTime && query.endTime) {
return {
createTime: Between(query.startTime, query.endTime),
};
}
if (query.startTime) {
return {
createTime: MoreThanOrEqual(query.startTime),
};
}
if (query.endTime) {
return {
createTime: LessThanOrEqual(query.endTime),
};
}
return {};
}
private requireScheduler() {
if (!this.scheduler) {
throwVbenError('插件定时任务调度器未初始化');
}
return this.scheduler;
}
}