初始化

This commit is contained in:
乘风
2026-01-05 10:11:01 +08:00
parent 3c4851b9ca
commit f1056bab01
99 changed files with 28576 additions and 36 deletions

View File

@@ -0,0 +1,283 @@
<?php
namespace app\service;
use app\repository\TagTaskRepository;
use app\repository\TagTaskExecutionRepository;
use app\repository\UserProfileRepository;
use app\service\TagService;
use app\utils\LoggerHelper;
use app\utils\RedisHelper;
use Ramsey\Uuid\Uuid as UuidGenerator;
/**
* 标签任务管理服务
*
* 职责:
* - 创建、更新、删除标签任务
* - 管理任务状态(启动、暂停、停止)
* - 执行标签计算任务
* - 追踪任务进度和统计信息
*/
class TagTaskService
{
public function __construct(
protected TagTaskRepository $taskRepository,
protected TagTaskExecutionRepository $executionRepository,
protected UserProfileRepository $userProfileRepository,
protected TagService $tagService
) {
}
/**
* 创建标签任务
*
* @param array<string, mixed> $taskData 任务数据
* @return array<string, mixed> 创建的任务信息
*/
public function createTask(array $taskData): array
{
$taskId = UuidGenerator::uuid4()->toString();
$task = [
'task_id' => $taskId,
'name' => $taskData['name'] ?? '未命名标签任务',
'description' => $taskData['description'] ?? '',
'task_type' => $taskData['task_type'] ?? 'full',
'target_tag_ids' => $taskData['target_tag_ids'] ?? [],
'user_scope' => $taskData['user_scope'] ?? ['type' => 'all'],
'schedule' => $taskData['schedule'] ?? [
'enabled' => false,
'cron' => null,
],
'config' => $taskData['config'] ?? [
'concurrency' => 10,
'batch_size' => 100,
'error_handling' => 'skip',
],
'status' => 'pending',
'progress' => [
'total_users' => 0,
'processed_users' => 0,
'success_count' => 0,
'error_count' => 0,
'percentage' => 0,
],
'statistics' => [
'total_executions' => 0,
'success_executions' => 0,
'failed_executions' => 0,
'last_run_time' => null,
],
'created_by' => $taskData['created_by'] ?? 'system',
'created_at' => new \MongoDB\BSON\UTCDateTime(time() * 1000),
'updated_at' => new \MongoDB\BSON\UTCDateTime(time() * 1000),
];
$this->taskRepository->create($task);
LoggerHelper::logBusiness('tag_task_created', [
'task_id' => $taskId,
'task_name' => $task['name'],
]);
return $task;
}
/**
* 更新任务
*/
public function updateTask(string $taskId, array $taskData): bool
{
$task = $this->taskRepository->find($taskId);
if (!$task) {
throw new \InvalidArgumentException("任务不存在: {$taskId}");
}
if ($task->status === 'running') {
$allowedFields = ['name', 'description', 'schedule'];
$taskData = array_intersect_key($taskData, array_flip($allowedFields));
}
$taskData['updated_at'] = new \MongoDB\BSON\UTCDateTime(time() * 1000);
return $this->taskRepository->where('task_id', $taskId)->update($taskData) > 0;
}
/**
* 删除任务
*/
public function deleteTask(string $taskId): bool
{
$task = $this->taskRepository->find($taskId);
if (!$task) {
throw new \InvalidArgumentException("任务不存在: {$taskId}");
}
if ($task->status === 'running') {
$this->stopTask($taskId);
}
return $this->taskRepository->where('task_id', $taskId)->delete() > 0;
}
/**
* 启动任务
*/
public function startTask(string $taskId): bool
{
$task = $this->taskRepository->find($taskId);
if (!$task) {
throw new \InvalidArgumentException("任务不存在: {$taskId}");
}
if ($task->status === 'running') {
throw new \RuntimeException("任务已在运行中: {$taskId}");
}
$this->taskRepository->where('task_id', $taskId)->update([
'status' => 'running',
'updated_at' => new \MongoDB\BSON\UTCDateTime(time() * 1000),
]);
// 设置Redis标志通知调度器启动任务
RedisHelper::set("tag_task:{$taskId}:start", '1', 3600);
LoggerHelper::logBusiness('tag_task_started', [
'task_id' => $taskId,
]);
return true;
}
/**
* 暂停任务
*/
public function pauseTask(string $taskId): bool
{
$task = $this->taskRepository->find($taskId);
if (!$task) {
throw new \InvalidArgumentException("任务不存在: {$taskId}");
}
if ($task->status !== 'running') {
throw new \RuntimeException("任务未在运行中: {$taskId}");
}
$this->taskRepository->where('task_id', $taskId)->update([
'status' => 'paused',
'updated_at' => new \MongoDB\BSON\UTCDateTime(time() * 1000),
]);
RedisHelper::set("tag_task:{$taskId}:pause", '1', 3600);
return true;
}
/**
* 停止任务
*/
public function stopTask(string $taskId): bool
{
$task = $this->taskRepository->find($taskId);
if (!$task) {
throw new \InvalidArgumentException("任务不存在: {$taskId}");
}
$this->taskRepository->where('task_id', $taskId)->update([
'status' => 'stopped',
'updated_at' => new \MongoDB\BSON\UTCDateTime(time() * 1000),
]);
RedisHelper::set("tag_task:{$taskId}:stop", '1', 3600);
return true;
}
/**
* 获取任务列表
*/
public function getTaskList(array $filters = [], int $page = 1, int $pageSize = 20): array
{
$query = $this->taskRepository->query();
if (isset($filters['status'])) {
$query->where('status', $filters['status']);
}
if (isset($filters['task_type'])) {
$query->where('task_type', $filters['task_type']);
}
if (isset($filters['name'])) {
$query->where('name', 'like', '%' . $filters['name'] . '%');
}
$total = $query->count();
$tasks = $query->orderBy('created_at', 'desc')
->skip(($page - 1) * $pageSize)
->take($pageSize)
->get()
->toArray();
return [
'tasks' => $tasks,
'total' => $total,
'page' => $page,
'page_size' => $pageSize,
'total_pages' => ceil($total / $pageSize),
];
}
/**
* 获取任务详情
*/
public function getTask(string $taskId): ?array
{
$task = $this->taskRepository->find($taskId);
return $task ? $task->toArray() : null;
}
/**
* 获取任务执行记录
*/
public function getExecutions(string $taskId, int $page = 1, int $pageSize = 20): array
{
$query = $this->executionRepository->query()->where('task_id', $taskId);
$total = $query->count();
$executions = $query->orderBy('started_at', 'desc')
->skip(($page - 1) * $pageSize)
->take($pageSize)
->get()
->toArray();
return [
'executions' => $executions,
'total' => $total,
'page' => $page,
'page_size' => $pageSize,
'total_pages' => ceil($total / $pageSize),
];
}
/**
* 执行任务(供调度器调用)
*/
public function executeTask(string $taskId): void
{
$executor = new \app\service\TagTaskExecutor(
$this->taskRepository,
$this->executionRepository,
$this->userProfileRepository,
new \app\repository\TagDefinitionRepository(),
$this->tagService
);
$executor->execute($taskId);
}
}