1

I'm using Laravel 9 with PHP 8.0.

I would like to launch several hundred jobs one after the other.

I initialized my jobs by storing them in "recognitionsBus". Then ran the batch.

I tried to reduce the job to the minimum to just log information, but each time a job is launched, it passes in the condition which says that the batch is canceled.

Also, not all jobs are executed. After a certain number, the batch stops. It may be an issue on my side but the batch doesn't pass through the then/catch or finally. Do you know why?

Controller

foreach ($recognitions as $recognition) {
    $test = Test::create([...]);

    $recognitionsBus->push(new TestJob($test);
}

Bus::batch($recognitionsBus->toArray())
    ->then(function (Batch $batch) use ($test) {
        Log::info("success");
    })->catch(function (Batch $batch, \Throwable $e) use ($test) {
        Log::error("error");

        throw $e;
    })->finally(function (Batch $batch) use ($test) {
        Log::info("finish");
    })
    ->dispatch();

Job

namespace App\Jobs;

use Illuminate\Bus\Batchable;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Throwable;

class TestJob implements ShouldQueue
{
    use Batchable, Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $test;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($test)
    {
        $this->test = $test;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        if ($this->batch()->cancelled()) {
            Log::info('canceled');

            return;
        }

        Log::info($this->test->id);
    }

    /**
     * Handle a job failure.
     */
    public function failed(Throwable $exception)
    {
        Log::info($exception->getMessage());
    }
}

Command

php artisan queue:work
miken32
  • 42,008
  • 16
  • 111
  • 154
Jo--
  • 11
  • 2

1 Answers1

0

In your case I'd do something like:

  1. Create scheduler which will run your job every lets say 5minutes
  2. In your job, get data in chunks - I'd recommend chunks of 50-100 items since you have only 1 worker (depends on the job you want to do)

This way you want flood your database queues and you will always have latest data :)

$posts = [];

        DB::table('posts')
            ->select('id', 'title', 'body')
            ->chunk(20, function ($results) use (&$posts) {
                $posts = array_merge($posts, $results->toArray());
            });

        foreach ($posts as $post) {
            $id = $post->id;
            $title = $post->title;
            $body = $post->body;

            // Do something with the post data
            // ...
        }
    $schedule->job(new FetchPostsJob)->everyFiveMinutes();
This is how scheduler would be ran in you cpanel (somehting like this)
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
devsead
  • 312
  • 7