У сучасних веб-додатках автоматизація рутинних завдань є критично важливою для підтримки здорового стану системи. Laravel надає потужний інструмент для цього – Task Scheduler. У цій статті ми розглянемо як ефективно використовувати планувальник Laravel для автоматизації завдань обслуговування, зокрема для керування сесіями та логами.
Планувальник завдань у Laravel
Базова структура
Планувальник завдань у Laravel сконфігурований в файлі app/Console/Kernel.php. Це серце всієї автоматизації в Laravel.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * Define the application's command schedule. */ protected function schedule(Schedule $schedule): void { // Тут визначаються заплановані завдання } /** * Register the commands for the application. */ protected function commands(): void { $this->load(__DIR__.'/Commands'); } } |
Створення команди обслуговування
Перш ніж планувати завдання, створимо команду для обслуговування:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Log; class MaintenanceCommand extends Command { protected $signature = 'maintenance:cleanup'; protected $description = 'Clean up old sessions and logs'; public function handle(): int { try { $this->cleanupSessions(); $this->rotateLogs(); $this->info('Maintenance completed successfully'); return 0; } catch (\Exception $e) { $this->error("Error during maintenance: " . $e->getMessage()); Log::error("Maintenance error", ['exception' => $e]); return 1; } } private function cleanupSessions(): void { $sessionsPath = storage_path('sessions'); $this->info("Cleaning up sessions in: {$sessionsPath}"); // Видаляємо файли старші 24 годин $this->cleanDirectory($sessionsPath, 60 * 24); } private function rotateLogs(): void { $logsPath = storage_path('logs'); $this->info("Rotating logs in: {$logsPath}"); // Видаляємо логи старші 7 днів $this->cleanDirectory($logsPath, 60 * 24 * 7); } private function cleanDirectory(string $path, int $maxAgeMinutes): void { if (!File::exists($path)) { $this->warn("Directory doesn't exist: {$path}"); return; } $files = File::files($path); $now = time(); $deleted = 0; foreach ($files as $file) { if ($now - File::lastModified($file) > $maxAgeMinutes * 60) { File::delete($file); $deleted++; } } $this->info("Deleted {$deleted} files from {$path}"); } } |
Планування завдань
Тепер налаштуємо виконання наших завдань у планувальнику:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
protected function schedule(Schedule $schedule): void { // Щогодинне очищення сесій $schedule->command('maintenance:cleanup') ->hourly() ->withoutOverlapping() ->runInBackground() ->appendOutputTo(storage_path('logs/maintenance.log')); // Щоденне архівування логів $schedule->call(function () { $date = now()->subDay()->format('Y-m-d'); $logFile = storage_path("logs/laravel-{$date}.log"); if (File::exists($logFile)) { $archiveDir = storage_path('logs/archive'); File::makeDirectory($archiveDir, 0755, true, true); File::move($logFile, "{$archiveDir}/laravel-{$date}.log"); } })->daily(); } |
Налаштування Supervisor
Для забезпечення постійної роботи планувальника, потрібно налаштувати Supervisor:
|
1 2 3 4 5 6 7 8 9 10 |
[program:laravel-scheduler] process_name=%(program_name)s_%(process_num)02d command=/usr/bin/php /path/to/artisan schedule:run autostart=true autorestart=true user=www-data numprocs=1 redirect_stderr=true stdout_logfile=/var/log/laravel-scheduler.log stopwaitsecs=3600 |
Моніторинг виконання завдань
Логування результатів
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
class MaintenanceCommand extends Command { public function handle(): int { $startTime = microtime(true); try { // Виконання завдань $result = $this->performMaintenance(); // Логування успіху $duration = round(microtime(true) - $startTime, 2); Log::info('Maintenance completed', [ 'duration' => $duration, 'cleaned_files' => $result['cleaned'], 'memory_usage' => memory_get_peak_usage(true) ]); return 0; } catch (\Exception $e) { // Логування помилок Log::error('Maintenance failed', [ 'duration' => round(microtime(true) - $startTime, 2), 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return 1; } } } |
Сповіщення про помилки
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
use Illuminate\Support\Facades\Notification; use App\Notifications\MaintenanceFailedNotification; class MaintenanceCommand extends Command { protected function notifyOnFailure(\Exception $e): void { $admin = User::where('is_admin', true)->first(); Notification::send($admin, new MaintenanceFailedNotification([ 'command' => $this->signature, 'error' => $e->getMessage(), 'time' => now()->toDateTimeString() ])); } } |
Кращі практики
- Атомарність операцій
- Кожне завдання повинно бути атомарним
- Використовуйте транзакції де можливо
- Забезпечте можливість відкату змін
- Обробка помилок
- Завжди логуйте помилки
- Сповіщайте адміністраторів про критичні помилки
- Використовуйте try-catch для кожної важливої операції
- Продуктивність
- Обробляйте файли пакетами
- Використовуйте індекси при роботі з БД
- Уникайте важких операцій в пікові години
- Моніторинг
- Логуйте час виконання завдань
- Відслідковуйте використання пам’яті
- Зберігайте статистику виконання
Висновок
Правильно налаштований планувальник завдань – це ключ до здорового стану вашого додатку. Laravel надає всі необхідні інструменти для ефективної автоматизації рутинних завдань. Використовуйте їх мудро, слідкуйте за продуктивністю та не забувайте про моніторинг.