Search code examples
laravel-novalaravel-horizon

Nova Queued Actions triggering multiple jobs


I've created an action as such:

use Illuminate\Bus\Queueable;
use Laravel\Nova\Actions\Action;
use Illuminate\Support\Collection;
use Laravel\Nova\Fields\ActionFields;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Laravel\Nova\Fields\BelongsTo;
use Illuminate\Support\Facades\Queue;

class ExportToCsv extends Action implements ShouldQueue
{
    use InteractsWithQueue, Queueable;

    public function handle(ActionFields $fields, Collection $models)
    {
        var_dump(time(), collect($models)->map(function($item){
            return $item->id;
        })->first());

        sleep(3);
    }
}

I'm then triggering it for 1128 items (twice) and observing this as a result:

[2020-05-02 20:45:05][181] Processing: App\Nova\Actions\ExportToCsv
int(1588452305)
int(621525)
[2020-05-02 20:45:05][180] Processing: App\Nova\Actions\ExportToCsv
int(1588452305)
int(412186)
[2020-05-02 20:45:05][179] Processing: App\Nova\Actions\ExportToCsv
int(1588452305)
int(621282)
[2020-05-02 20:45:08][181] Processed:  App\Nova\Actions\ExportToCsv
[2020-05-02 20:45:08][184] Processing: App\Nova\Actions\ExportToCsv
int(1588452308)
int(623886)
[2020-05-02 20:45:08][180] Processed:  App\Nova\Actions\ExportToCsv
[2020-05-02 20:45:08][182] Processing: App\Nova\Actions\ExportToCsv
int(1588452308)
int(622950)
[2020-05-02 20:45:08][179] Processed:  App\Nova\Actions\ExportToCsv
[2020-05-02 20:45:08][183] Processing: App\Nova\Actions\ExportToCsv
int(1588452308)
int(623252)
[2020-05-02 20:45:11][184] Processed:  App\Nova\Actions\ExportToCsv
[2020-05-02 20:45:11][182] Processed:  App\Nova\Actions\ExportToCsv
[2020-05-02 20:45:11][183] Processed:  App\Nova\Actions\ExportToCsv
[2020-05-02 20:45:35][185] Processing: App\Nova\Actions\ExportToCsv
int(1588452335)
int(621282)
[2020-05-02 20:45:35][187] Processing: App\Nova\Actions\ExportToCsv
int(1588452335)
int(621525)
[2020-05-02 20:45:35][186] Processing: App\Nova\Actions\ExportToCsv
int(1588452335)
int(412186)
[2020-05-02 20:45:38][185] Processed:  App\Nova\Actions\ExportToCsv
[2020-05-02 20:45:38][188] Processing: App\Nova\Actions\ExportToCsv
int(1588452338)
int(622950)
[2020-05-02 20:45:38][187] Processed:  App\Nova\Actions\ExportToCsv
[2020-05-02 20:45:38][190] Processing: App\Nova\Actions\ExportToCsv
int(1588452338)
int(623886)
[2020-05-02 20:45:38][186] Processed:  App\Nova\Actions\ExportToCsv
[2020-05-02 20:45:38][189] Processing: App\Nova\Actions\ExportToCsv
int(1588452338)
int(623252)
[2020-05-02 20:45:41][188] Processed:  App\Nova\Actions\ExportToCsv
[2020-05-02 20:45:41][190] Processed:  App\Nova\Actions\ExportToCsv
[2020-05-02 20:45:41][189] Processed:  App\Nova\Actions\ExportToCsv

By default the batches are grouped by 200 items and from what I'm seeing there are simultaneously 3 jobs being spawned at the same time. Unfortunately there's no way of knowing which job will be processed first, so models displayed in log for each batch change, as seen in output: 621525, 412186, 621282 for when action is called the first time and 621282, 621525, 412186 when it's called second time (the models are split between jobs the same way, but the order of jobs processed changes). The problem here is, that if I'm saving the view to a CSV file, the order matters.

I'd like only one job to be spawned at given time for given action, which would solve my problem. Is this possible?

Using horizon as queue worker


Solution

  • The way to accomplish this is to change processes value in horizon configuration:

        'environments' => [
            'local' => [
                'supervisor-1' => [
                    'connection' => 'redis',
                    'queue' => ['default'],
                    'balance' => 'simple',
                    'processes' => 1,
                    'tries' => 3,
                ],
            ],