2

I've made CRON Job using Laravel's task scheduling. But what I need is to store somewhere when that task was last ran,

Does anyone have any methods of how they store that and also, If Laravel outputs anything that can tell you when it was last ran?

Thanks

StuBlackett
  • 3,789
  • 15
  • 68
  • 113

3 Answers3

4

Not possible directly, however it is possible if you cache a date-time string on each run (either at the beginning or end of your script).

Cache::rememberForever('name_of_artisan_task', function () {
    return now()->toDateTimeString();
});

The example shows using the Cache facade's ::rememberForever method to create a key/value of the last time the task was ran. As the name suggests, this is saved forever.

You can easily retrieve this date and time using the cache() helper:

cache('name_of_artisan_task');

The con with this method is that if your cache is cleared, you will not longer have this stored.

thisiskelvin
  • 4,136
  • 1
  • 10
  • 17
2

Using a cache is not a safe way to do this, as @thisiskelvin hinted, clearing the cache will remove the data (which should happen on each deployment) but he didn't provide an alternative

So here is one if you need this date reliably (if you use it to know the interval to run an export for instance)

In which case I recommend creating a model php artisan make:model ScheduleRuns -m

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

/**
 * @property string $task
 */
class ScheduleRuns extends Model
{
    public const UPDATED_AT = false;

    public $timestamps = true;

    protected $attributes = [
        'task' => '',
    ];

    protected $fillable = [
        'task',
        'created_at',
    ];
}
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('schedule_runs', function (Blueprint $table) {
            $table->id();
            $table->string('task');
            $table->timestamp('created_at')->nullable();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('schedule_runs');
    }
};

Then use schedule hooks to create it (or do it within the task if you want to avoid possible seconds differences)

$schedule->command('export:users')
     ->weekly()->onSuccess(fn () => ScheduleRuns::create(['task' => 'export:users']))

And to retrieve the latest run

ScheduleRuns::query()->where('task', 'export:users')->latest();
Tofandel
  • 3,006
  • 1
  • 29
  • 48
  • Thanks for this, Tofandel. I put together a little package to make it reusable. I also added a HasScheduleRuns trait with some convenience methods, and added a JSON column for storing misc data with the task. https://packagist.org/packages/rushing/laravel-schedule-runs – stephenr85 Mar 30 '23 at 15:56
0

Just write log each time the task was run, or you can push it into database.

<?php

namespace App\Console\Commands\Tasks;

use Illuminate\Console\Command;

class ScheduledTask extends Command
{
    public function handle()
    {
        //
        // ...handle you task
        //
        $file = 'logs/jobs/' . __CLASS__ . '.log';
        $message = 'Executed at: ' . date('Y-m-d H:i:s', time());
        file_put_contents(storage_path($file), $message, FILE_APPEND);
    }
}
Hung Nguyen
  • 1,026
  • 11
  • 18
  • You might just want to use `->storeOutput()` on the schedule instead if you want logs, no need to reinvent the wheel – Tofandel Aug 31 '22 at 10:09