where(function ($q) use ($params) { $q->where('name', 'like', '%' . $params['keyword'] . '%') ->orWhere('command', 'like', '%' . $params['keyword'] . '%'); }); } if (isset($params['is_active']) && $params['is_active'] !== '') { $query->where('is_active', $params['is_active']); } if (!empty($params['type'])) { $query->where('type', $params['type']); } $query->orderBy('id'); $pageSize = $params['page_size'] ?? 20; $list = $query->paginate($pageSize); return [ 'list' => $list->items(), 'total' => $list->total(), 'page' => $list->currentPage(), 'page_size' => $list->perPage(), ]; } public function getAll(): array { return Task::all()->toArray(); } public function getById(int $id): ?Task { return Task::find($id); } public function create(array $data): Task { Validator::make($data, [ 'name' => 'required|string|max:100', 'command' => 'required|string|max:255', 'type' => 'required|string|in:command,job,closure', 'expression' => 'required|string', ])->validate(); return Task::create($data); } public function update(int $id, array $data): Task { $task = Task::findOrFail($id); Validator::make($data, [ 'name' => 'sometimes|required|string|max:100', 'command' => 'sometimes|required|string|max:255', 'type' => 'sometimes|required|string|in:command,job,closure', 'expression' => 'sometimes|required|string', ])->validate(); $task->update($data); return $task; } public function delete(int $id): bool { $task = Task::findOrFail($id); return $task->delete(); } public function batchDelete(array $ids): bool { Task::whereIn('id', $ids)->delete(); return true; } public function batchUpdateStatus(array $ids, bool $status): bool { Task::whereIn('id', $ids)->update(['is_active' => $status]); return true; } public function run(int $id): array { $task = Task::findOrFail($id); $startTime = microtime(true); $output = ''; $status = 'success'; $errorMessage = ''; try { switch ($task->type) { case 'command': $command = $task->command; if ($task->run_in_background) { $command .= ' > /dev/null 2>&1 &'; } exec($command, $output, $statusCode); $output = implode("\n", $output); if ($statusCode !== 0) { throw new \Exception('Command failed with status code: ' . $statusCode); } break; case 'job': $jobClass = $task->command; if (class_exists($jobClass)) { dispatch(new $jobClass()); } else { throw new \Exception('Job class not found: ' . $jobClass); } break; case 'closure': throw new \Exception('Closure type tasks cannot be run directly'); } $task->increment('run_count'); } catch (\Exception $e) { $status = 'error'; $errorMessage = $e->getMessage(); $task->increment('failed_count'); } $executionTime = round((microtime(true) - $startTime) * 1000); $task->update([ 'last_run_at' => now(), 'last_output' => substr($output, 0, 10000), ]); return [ 'status' => $status, 'output' => $output, 'error_message' => $errorMessage, 'execution_time' => $executionTime, ]; } public function getStatistics(): array { $total = Task::count(); $active = Task::where('is_active', true)->count(); $inactive = Task::where('is_active', false)->count(); return [ 'total' => $total, 'active' => $active, 'inactive' => $inactive, ]; } }