findOrFail($planId); if (!$plan->is_enabled) { throw new \Exception('计划已禁用,无法创建任务'); } if ($plan->contents->isEmpty()) { throw new \Exception('计划没有配置内容,无法创建任务'); } // 验证任务选项 $validatedOptions = static::validateTaskOptions($taskOptions); // 统计任务信息 $enabledContents = $plan->contents->where('is_enabled', true); $totalTables = $enabledContents->count(); if ($totalTables === 0) { throw new \Exception('计划中没有启用的表配置,无法创建任务'); } // 创建任务 $task = CleanupTask::create([ 'task_name' => $validatedOptions['task_name'] ?? "清理任务 - {$plan->plan_name}", 'plan_id' => $planId, 'status' => TASK_STATUS::PENDING->value, 'progress' => 0, 'current_step' => '准备中', 'total_tables' => $totalTables, 'processed_tables' => 0, 'total_records' => 0, 'deleted_records' => 0, 'backup_size' => 0, 'execution_time' => 0, 'backup_time' => 0, 'created_by' => $validatedOptions['created_by'] ?? 0, ]); DB::commit(); return [ 'success' => true, 'message' => '清理任务创建成功', 'data' => [ 'task_id' => $task->id, 'task_name' => $task->task_name, 'plan_name' => $plan->plan_name, 'total_tables' => $totalTables, 'status' => TASK_STATUS::from($task->status)->getDescription(), ] ]; } catch (\Exception $e) { DB::rollBack(); Log::error('创建清理任务失败', [ 'plan_id' => $planId, 'task_options' => $taskOptions, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return [ 'success' => false, 'message' => '创建清理任务失败: ' . $e->getMessage(), 'data' => null ]; } } /** * 更新任务状态 * * @param int $taskId 任务ID * @param TASK_STATUS $status 新状态 * @param array $updateData 更新数据 * @return array 更新结果 */ public static function updateTaskStatus(int $taskId, TASK_STATUS $status, array $updateData = []): array { try { $task = CleanupTask::findOrFail($taskId); $data = array_merge($updateData, [ 'status' => $status->value, ]); // 根据状态设置时间戳 switch ($status) { case TASK_STATUS::RUNNING: $data['started_at'] = now(); break; case TASK_STATUS::BACKING_UP: $data['started_at'] = $data['started_at'] ?? now(); break; case TASK_STATUS::COMPLETED: $data['completed_at'] = now(); $data['progress'] = 100; break; case TASK_STATUS::FAILED: case TASK_STATUS::CANCELLED: $data['completed_at'] = now(); break; } $task->update($data); return [ 'success' => true, 'message' => '任务状态更新成功', 'data' => [ 'task_id' => $task->id, 'status' => $status->getDescription(), 'progress' => $task->progress, ] ]; } catch (\Exception $e) { Log::error('更新任务状态失败', [ 'task_id' => $taskId, 'status' => $status->value, 'update_data' => $updateData, 'error' => $e->getMessage() ]); return [ 'success' => false, 'message' => '更新任务状态失败: ' . $e->getMessage(), 'data' => null ]; } } /** * 更新任务进度 * * @param int $taskId 任务ID * @param int $processedTables 已处理表数 * @param int $deletedRecords 已删除记录数 * @param string $currentStep 当前步骤 * @return array 更新结果 */ public static function updateTaskProgress(int $taskId, int $processedTables, int $deletedRecords, string $currentStep): array { try { $task = CleanupTask::findOrFail($taskId); $progress = $task->total_tables > 0 ? round(($processedTables / $task->total_tables) * 100, 2) : 0; $task->update([ 'progress' => $progress, 'processed_tables' => $processedTables, 'deleted_records' => $deletedRecords, 'current_step' => $currentStep, ]); return [ 'success' => true, 'data' => [ 'task_id' => $task->id, 'progress' => $progress, 'processed_tables' => $processedTables, 'total_tables' => $task->total_tables, 'deleted_records' => $deletedRecords, 'current_step' => $currentStep, ] ]; } catch (\Exception $e) { Log::error('更新任务进度失败', [ 'task_id' => $taskId, 'processed_tables' => $processedTables, 'deleted_records' => $deletedRecords, 'current_step' => $currentStep, 'error' => $e->getMessage() ]); return [ 'success' => false, 'message' => '更新任务进度失败: ' . $e->getMessage(), 'data' => null ]; } } /** * 取消任务 * * @param int $taskId 任务ID * @param string $reason 取消原因 * @return array 取消结果 */ public static function cancelTask(int $taskId, string $reason = ''): array { try { $task = CleanupTask::findOrFail($taskId); // 检查任务状态 $currentStatus = TASK_STATUS::from($task->status); if (in_array($currentStatus, [TASK_STATUS::COMPLETED, TASK_STATUS::FAILED, TASK_STATUS::CANCELLED])) { throw new \Exception('任务已完成或已取消,无法再次取消'); } $task->update([ 'status' => TASK_STATUS::CANCELLED->value, 'completed_at' => now(), 'error_message' => $reason ?: '用户取消', ]); return [ 'success' => true, 'message' => '任务已取消', 'data' => [ 'task_id' => $task->id, 'status' => TASK_STATUS::CANCELLED->getDescription(), ] ]; } catch (\Exception $e) { Log::error('取消任务失败', [ 'task_id' => $taskId, 'reason' => $reason, 'error' => $e->getMessage() ]); return [ 'success' => false, 'message' => '取消任务失败: ' . $e->getMessage(), 'data' => null ]; } } /** * 获取任务详情 * * @param int $taskId 任务ID * @return array 任务详情 */ public static function getTaskDetails(int $taskId): array { try { $task = CleanupTask::with(['plan', 'backup'])->findOrFail($taskId); return [ 'success' => true, 'data' => [ 'task' => [ 'id' => $task->id, 'task_name' => $task->task_name, 'status' => $task->status, 'status_name' => TASK_STATUS::from($task->status)->getDescription(), 'progress' => $task->progress, 'current_step' => $task->current_step, 'total_tables' => $task->total_tables, 'processed_tables' => $task->processed_tables, 'total_records' => $task->total_records, 'deleted_records' => $task->deleted_records, 'backup_size' => $task->backup_size, 'execution_time' => $task->execution_time, 'backup_time' => $task->backup_time, 'started_at' => $task->started_at, 'backup_completed_at' => $task->backup_completed_at, 'completed_at' => $task->completed_at, 'error_message' => $task->error_message, 'created_at' => $task->created_at, ], 'plan' => $task->plan ? [ 'id' => $task->plan->id, 'plan_name' => $task->plan->plan_name, 'plan_type' => $task->plan->plan_type, 'description' => $task->plan->description, ] : null, 'backup' => $task->backup ? [ 'id' => $task->backup->id, 'backup_name' => $task->backup->backup_name, 'backup_size' => $task->backup->backup_size, 'file_count' => $task->backup->file_count, 'status' => $task->backup->status, ] : null, ] ]; } catch (\Exception $e) { Log::error('获取任务详情失败', [ 'task_id' => $taskId, 'error' => $e->getMessage() ]); return [ 'success' => false, 'message' => '获取任务详情失败: ' . $e->getMessage(), 'data' => null ]; } } /** * 验证任务选项 * * @param array $taskOptions 任务选项 * @return array 验证后的选项 */ private static function validateTaskOptions(array $taskOptions): array { return [ 'task_name' => $taskOptions['task_name'] ?? null, 'created_by' => $taskOptions['created_by'] ?? 0, ]; } /** * 启动任务执行 * * @param int $taskId 任务ID * @return array 启动结果 */ public static function startTask(int $taskId): array { try { $task = CleanupTask::findOrFail($taskId); // 检查任务状态 if ($task->status !== TASK_STATUS::PENDING->value) { return [ 'success' => false, 'message' => '只有待执行状态的任务可以启动' ]; } // 更新任务状态为执行中 $task->update([ 'status' => TASK_STATUS::RUNNING->value, 'started_at' => now(), 'current_step' => '任务启动中...' ]); return [ 'success' => true, 'message' => '任务启动成功', 'data' => $task->fresh() ]; } catch (\Exception $e) { return [ 'success' => false, 'message' => '启动任务失败:' . $e->getMessage() ]; } } /** * 暂停任务执行 * * @param int $taskId 任务ID * @return array 暂停结果 */ public static function pauseTask(int $taskId): array { try { $task = CleanupTask::findOrFail($taskId); // 检查任务状态 if (!in_array($task->status, [TASK_STATUS::BACKING_UP->value, TASK_STATUS::RUNNING->value])) { return [ 'success' => false, 'message' => '只有备份中或执行中的任务可以暂停' ]; } // 更新任务状态为已暂停 $task->update([ 'status' => TASK_STATUS::PAUSED->value, 'current_step' => '任务已暂停' ]); return [ 'success' => true, 'message' => '任务暂停成功', 'data' => $task->fresh() ]; } catch (\Exception $e) { return [ 'success' => false, 'message' => '暂停任务失败:' . $e->getMessage() ]; } } /** * 恢复任务执行 * * @param int $taskId 任务ID * @return array 恢复结果 */ public static function resumeTask(int $taskId): array { try { $task = CleanupTask::findOrFail($taskId); // 检查任务状态 if ($task->status !== TASK_STATUS::PAUSED->value) { return [ 'success' => false, 'message' => '只有已暂停的任务可以恢复' ]; } // 更新任务状态为执行中 $task->update([ 'status' => TASK_STATUS::RUNNING->value, 'current_step' => '任务恢复执行中...' ]); return [ 'success' => true, 'message' => '任务恢复成功', 'data' => $task->fresh() ]; } catch (\Exception $e) { return [ 'success' => false, 'message' => '恢复任务失败:' . $e->getMessage() ]; } } /** * 停止任务执行 * * @param int $taskId 任务ID * @return array 停止结果 */ public static function stopTask(int $taskId): array { try { $task = CleanupTask::findOrFail($taskId); // 检查任务状态 if (!in_array($task->status, [TASK_STATUS::BACKING_UP->value, TASK_STATUS::RUNNING->value, TASK_STATUS::PAUSED->value])) { return [ 'success' => false, 'message' => '只有备份中、执行中或已暂停的任务可以停止' ]; } // 更新任务状态为已取消 $task->update([ 'status' => TASK_STATUS::CANCELLED->value, 'finished_at' => now(), 'current_step' => '任务已停止', 'error_message' => '任务被手动停止' ]); return [ 'success' => true, 'message' => '任务停止成功', 'data' => $task->fresh() ]; } catch (\Exception $e) { return [ 'success' => false, 'message' => '停止任务失败:' . $e->getMessage() ]; } } /** * 获取任务进度 * * @param int $taskId 任务ID * @return array 进度信息 */ public static function getTaskProgress(int $taskId): array { try { $task = CleanupTask::findOrFail($taskId); return [ 'success' => true, 'data' => [ 'task_id' => $task->id, 'status' => $task->status, 'progress' => $task->progress, 'current_step' => $task->current_step, 'total_tables' => $task->total_tables, 'processed_tables' => $task->processed_tables, 'deleted_records' => $task->deleted_records, 'started_at' => $task->started_at, 'finished_at' => $task->finished_at, ] ]; } catch (\Exception $e) { return [ 'success' => false, 'message' => '获取任务进度失败:' . $e->getMessage() ]; } } }