Files
laravel_swoole/app/Services/System/TaskService.php
2026-02-08 22:38:13 +08:00

168 lines
4.6 KiB
PHP

<?php
namespace App\Services\System;
use App\Models\System\Task;
use Illuminate\Support\Facades\Validator;
class TaskService
{
public function getList(array $params): array
{
$query = Task::query();
if (!empty($params['keyword'])) {
$query->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,
];
}
}