12/08/2018, 13:03

Task Scheduling trong Laravel

Nếu bạn là một game thủ game online thì chắc cũng đã từng trải nghiệm những ngày tháng khô máu leo top rồi sống chết bảo vệ vị trí của mình cho tới thời điểm kết thúc event. Càng gần tới thời điểm kết thúc thì bạn kiểm tra thứ hạng càng thường xuyên, chỉ một giây lơ là có khi bị đối thủ cướp mất ...

Nếu bạn là một game thủ game online thì chắc cũng đã từng trải nghiệm những ngày tháng khô máu leo top rồi sống chết bảo vệ vị trí của mình cho tới thời điểm kết thúc event. Càng gần tới thời điểm kết thúc thì bạn kiểm tra thứ hạng càng thường xuyên, chỉ một giây lơ là có khi bị đối thủ cướp mất đồ ngon hay thê thảm hơn là bị đá đít xuống vị trí 11 và chả có tí sơ múi nào cả.

Vậy làm sao mà server biết phải tổng hợp rank cho người vào một thời điểm chính xác nào đó, hay biết lúc nào tới giữa event để vinh danh mấy anh hùng tạm thời khiến cho những đối thủ khác sôi máu mà đổ tiền đổ sức vào cày cuốc vượt mặt?

Tất nhiên không phải là cắt cử một ông developer rồi trông, căn đúng nửa đêm rồi nhấn nút phát cho code tổng hợp rank chạy rồi @@. Nhỡ ổng ngủ quên chỉ 1, 2 phút thôi, kết quả rank thay đổi là nhà vận hành game có đủ gạch xây trụ sở mới ngay.

Vâng, đó phải là Task Scheduling. Vậy làm sao để cài đặt Task Scheduling trong Laravel. Hôm nay chúng ta sẽ cùng nhau tìm hiểu nhé!

1. Example

Bạn có thể định nghĩa tất cả các tác vụ cần thực hiện ở trong method schedule của class AppConsoleKernel trong file app/Console/Kernel.php. Ví dụ bạn muốn có tổng hợp rank giữa event vào mỗi 18:00 ngày thứ 4 và rank của cả event vào mỗi 18:00 chủ nhật.

<?php

namespace DemoAppConsole;

use IlluminateConsoleSchedulingSchedule;
use IlluminateFoundationConsoleKernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
...

    protected function schedule(Schedule $schedule)
    {
        $schedule->call(function () {
            //Code tổng hợp rank giữa event
        })->weekly()->wednesdays()->at('18:00');

        $schedule->call(function () {
            //Code tổng hợp rank toàn event
        })->weekly()->sundays()->at('18:00');
    }
}

2. Thiết lập thời điểm thực hiện tác vụ

Larvel cung cấp cho chúng ta rất nhiều cách để có thể xác định chính xác thời điểm bạn cần chạy tác vụ. Trong khuôn khổ bài viết mình sẽ chỉ giới thiệu sơ qua một vài ví dụ cơ bản nhất.

->dailyAt('18:00');    Chạy tác vụ mỗi ngày vào 18:00
->twiceDaily(6, 18);   Chạy tác vụ mỗi ngày 2 lần vào 6:0018:00
->everyMinute();       Chạy tác vụ mỗi phút
->everyFiveMinutes();  Chạy tác vụ mỗi 5 phút
->hourly();            Chạy tác vụ mỗi giờ
->yearly();;           Chạy tác vụ mỗi năm

Ta còn có thể chỉ định rất chi tiết những thời điểm chạy tác vụ cho server như ví dụ tổng hợp rank cả event vào mỗi 18:00 chủ nhật: ->weekly()->sundays()->at('18:00');

Giả sử bạn có tác vụ chạy mỗi phút một lần. Nhưng không may server đang nóng máy, nó chạy tác dụ mất hơn một phút, thế là ở phút tiếp theo tác vụ lại được khởi động trong khi nó vẫn chưa kết thúc. Để tránh vụ đó ta có thể sử dụng phương thức withoutOverlapping

->everyMinute()->withoutOverlapping();

3. Thiết lập cho các tác vụ phức tạp

Với các task vụ đơn giản, bạn hoàn toàn có thể viết tất cả trong file app/Console/Kernel.php được. Tuy nhiên giả sử app bạn đang phát triển có chức năng lấy các bài đăng trên 9Gag, dân trí, hay facebook của người dùng để tổng hợp vào đăng lên timeline của chính nó thì sao? Lúc đó file của bạn sẽ thành ra như thế này.

        $schedule->call(function () {
            //Code lấy bài đăng từ 9gag
            //... dài dài
            //...
        })->everyFiveMinutes();

         $schedule->call(function () {
            //Code lấy bài đăng từ dân trí
            //... dài dài
            //...
        })->everyFiveMinutes();

         $schedule->call(function () {
            //Code lấy bài đăng từ Facebook
            //... dài dài
            //...
        })->everyFiveMinutes();

Nói chung là khó nuốt và lúc maintain thì thôi rồi. @@ Nói chung là chúng ta cần cách viết cool hơn một chút.

Bước 1: Tách code lấy dữ liệu bài đăng từ các kênh trên vào các file tương ứng

app/Console/Commands/NineGag.php
app/Console/Commands/DanTri.php
app/Console/Commands/Facebook.php

Với file app/Console/Commands/NineGag.php

<?php

namespace DemoAppConsoleCommands;

use IlluminateConsoleCommand;

class NineGag extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'ninegag';

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //Code lấy bài đăng từ 9Gag
    }
}

Các bạn chú ý đặt $signature sao cho dễ phân biệt nhé!

Bước 2: Viết Kernel.php

<?php

namespace DemoAppConsoleCommands;

use IlluminateConsoleSchedulingSchedule;
use IlluminateFoundationConsoleKernel as ConsoleKernel;

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

    protected function schedule(Schedule $schedule)
    {

        $schedule->command('ninegag')
            ->everyFiveMinutes();

        $schedule->command('dantri')
            ->everyFiveMinutes();

        $schedule->command('facebook')
            ->everyFiveMinutes();
    }
}

Rất ngắn gọn và dễ hiểu phải không? ^^

Trên đây mình đã giới thiệu với các bạn cách tạo Task Scheduling với Laravel. Chúc các bạn vui vẻ và được tính rank nhầm có lợi trong event! ^=^

0