12/08/2018, 12:59

Task Scheduling trong Laravel 5.1

Trong quá khứ, các developer đã phải tạo ra một mục Cron cho từng nhiệm vụ mà họ cần phải lên lịch. Tuy nhiên, đây là một công việc khá mệt mỏi bởi lịch trình công việc của bạn không phải trong source code, và bạn phải SSH vào máy chủ của bạn để thêm các mục Cron. Trong laravel 5.1, lệnh Laravel ...

Trong quá khứ, các developer đã phải tạo ra một mục Cron cho từng nhiệm vụ mà họ cần phải lên lịch. Tuy nhiên, đây là một công việc khá mệt mỏi bởi lịch trình công việc của bạn không phải trong source code, và bạn phải SSH vào máy chủ của bạn để thêm các mục Cron. Trong laravel 5.1, lệnh Laravel Scheduler cho phép bạn cấu hình xác định lịch trình lệnh của bạn trong chính source code, và chỉ cần một mục Cron trên máy chủ của bạn là đủ.

Lịch trình công việc của bạn được xác định trong file app/Console/Kernel.php. Bạn có thể để thêm nhiều nhiệm vụ theo lịch trình vào object Schedule.

Bắt đầu với Schedule:

Với server có hệ điều hành linux bạn chỉ cần gõ command:

crontab -e

và thêm vào 1 dòng cron duy nhất:

* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1

để schedule laravel có thể chạy mỗi phút 1 lần. Và laravel sẽ check và chạy các công việc đã được lên lịch trong schedule.

Định nghĩa Schedule:

Bạn có thể lên lịch cho tất cả các công việc của bạn trong hàm schedule của class AppConsoleKernel. Ví dụ:

<?php

namespace AppConsole;

use DB;
use IlluminateConsoleSchedulingSchedule;
use IlluminateFoundationConsoleKernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        AppConsoleCommandsInspire::class,
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  IlluminateConsoleSchedulingSchedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->call(function () {
            DB::table('users')->delete();
        })->daily();
    }
}

Với ví dụ trên ta có thể xóa bảng users vào lúc nửa đêm mỗi ngày. Ngoài việc gọi Closure ta có thể gọi Artisan commands bằng hàm command:

$schedule->command('emails:send --force')->daily();

Hoặc dùng hàm exec để chạy các lệnh của hệ điều hành:

$schedule->exec('node /home/forge/script.js')->daily();

Thiết lập thời gian

Method Description
->cron('* * * * *'); chạy công việc trong custom Cron schedule
->everyMinute(); chạy mỗi phút 1 lần
->everyFiveMinutes(); chạy mỗi 5 phút 1 lần
->everyTenMinutes(); chạy mỗi 10 phút 1 lần
->everyThirtyMinutes(); chạy mỗi 30 phút 1 lần
->hourly(); chạy mỗi giờ 1 lần
->daily(); chạy mỗi ngày vào 00:00
->dailyAt('13:00'); chạy mỗi ngày vào 13:00
->twiceDaily(1, 13); chạy 2 lần 1 ngày vào 1:00 & 13:00
->weekly(); chạy mỗi tuần 1 lần
->monthly(); chạy mỗi tháng 1 lần
->yearly(); chạy mỗi năm 1 lần

Những phương pháp này có thể được kết hợp với một số ràng buộc để tạo ra điều chỉnh nhỏ hơn cho lịch trình mà chỉ chạy vào những ngày nhất định trong tuần. Ví dụ, để sắp xếp một lệnh để chạy hàng tuần vào thứ hai:

$schedule->call(function () {
    // Runs once a week on Monday at 13:00...
})->weekly()->mondays()->at('13:00');

Dưới đây là một danh sách của những hạn chế lịch trình bổ sung:

Method Description
->weekdays(); giới hạn công việc các ngày trong tuần
->sundays(); giới hạn công việc trong chủ nhật
->mondays(); giới hạn công việc trong thứ hai
->tuesdays(); giới hạn công việc trong thứ ba
->wednesdays(); giới hạn công việc trong thứ tư
->thursdays(); giới hạn công việc trong thứ năm
->fridays(); giới hạn công việc trong thứ sáu
->saturdays(); giới hạn công việc trong thứ bảy
->when(Closure); giới hạn công việc khi thỏa điều kiện

Với method when() bạn có thể giới hạn chỉ chạy công việc khi thỏa mãn một hoặc nhiều điều kiện nào đó. Và chỉ khi tất cả các điều kiện thỏa mãn thì công việc mới chạy.Ví dụ:

$schedule->command('emails:send')->daily()->when(function () {
    return true;
});

**Ngăn chặn thực thi chồng chéo: **

Công việc của bạn có thể vẫn khởi chạy khi mà lần chạy trước của nó chưa hoàn thành. Và để ngăn điều này xảy ra bạn cần thêm câu lệnh:

$schedule->command('emails:send')->withoutOverlapping();

Task output

Laravel cung cấp 1 số phương thức rất thuận tiện để báo cáo nhiệm vụ hoàn thành của các task. Chúng ta có thể sử dụng phương thức sendOutputTo hoặc emailOutputTo

$schedule->command('emails:send')
 ->daily()
 ->sendOutputTo($filePath);

$schedule->command('emails:send')
 ->daily()
 ->sendOutputTo($filePath);

$schedule->command('foo')
 ->daily()
 ->sendOutputTo($filePath)
 ->emailOutputTo('foo@example.com');

$schedule->command('foo')
 ->daily()
 ->sendOutputTo($filePath)
 ->emailOutputTo('foo@example.com');

Lưu ý rằng 2 phương thức sendOutputTo và emailOutputTo chỉ hỗ trợ cho các task được gọi bằng lệnh command chứ không hỗ trợ phương thức call

Task Hooks

Bằng cách sử dụng phương thức before và after, ta có thể chỉ định các đoạn lệnh được chạy trước và sau của các task

$schedule->command('emails:send')
 ->daily()
 ->before(function () {
 // Task is about to start...
 })
 ->after(function () {
 // Task is complete...
 });

$schedule->command('emails:send')
 ->daily()
 ->before(function () {
 // Task is about to start...
 })
 ->after(function () {
 // Task is complete...
 });

Tham khảo : http://laravel.com/docs/5.1/scheduling#defining-schedules

0