Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 24.10.2019 15:13:12

Job работает не так, как ожидается

Добрый день. Возникла такая проблема. Вывел загрузку данных в модальное окно, заполняется textarea данными, нажимается кнопка загрузки, методом ajax идёт запрос на AjaxController:

public function ajax_stats_upload(Request $request)
    {
        if(!$request->ajax()) return response('Unsupported method.', 405);

        $user = $request->user();
        if($user->block_upload)
            return response('Вам не разрешена загрузка своих данных.', 400);

        if(!$request->data)
            return response('Пожалуйста, добавьте данные в специальное поле', 400);

        $content = explode(PHP_EOL, $request->data);

        if(count($content) < 1)
            return response('Пожалуйста, добавьте данные в специальное поле', 400);

        if(count($content) > 1000)
            return response('Превышен допустимый размер загрузки (Макс. 1000 за 1 раз)', 400);
        
        $date = date("Y-m-d");
        $now = now();
        $stat = $user->stats()->where('created_at', '>=', $date)->first(); 
        if (!$stat)
            $stat = $user->stats()->create();

        LoadData::dispatch($content, $user, $stat)->onQueue('load-data');

        return response('Успешно. Ожидайте', 200);
    }

Через ивенты данные передаются для обновления. App/Jobs/LoadData.php:

class LoadData implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $data = [];
    protected $user;
    protected $stat;

    public $tries = 1;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($data, User $user, Stats $stat)
    {
        $this->data = $data;
        $this->user = $user;
        $this->stat = $stat;  
    }

    public function createEvent($iteration, $data, $loaded = 0, $replays = 0)
    {
        $events = [
            'user' => $this->user->id,
            'data' => [
                'replays' => $replays,
                'loaded' => $loaded,
                'all' => $data,
                'completed' => $iteration,
                'percent' => $iteration>0?round(($iteration/$data)*100):0
            ]
        ];
        event(new LoadDataEvent(json_encode($events)));
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        if(count($this->data) < 1) return false;

        $logins = [];
        $data_records = [];

        $added = 0;
        $notadded = 0;
        $replays = 0;

        $now = now();

        $it = 0;
        $this->createEvent($it, count($this->data));

        foreach($this->data as $line)
        {
            $matches = explode(':', $line);
            
            if (count($matches) < 3)
            {
                $notadded++;
                $it++;
                if($it % 10 == 0)
                    $this->createEvent($it, count($this->data));
                continue;
            }

            $login = $matches[0];
            $pass = trim($matches[1]);
            $token = trim($matches[2]);

            if(in_array($login, $logins))
            {
                $replays++;
                $it++;
                if($it % 10 == 0)
                    $this->createEvent($it, count($this->data));
                continue;   
            }

            if(!empty($line))
            {
                $added++;
                $data_records[] = [
                    'user_id' => $this->user->id,
                    'stats_id' => $this->stat->id,
                    'updated_at' => $now,
                    'created_at' => $now
                ];

                $logins[] = $login;
            } else {
                $notadded++;
                $it++;
                if($it % 10 == 0)
                    $this->createEvent($it, count($this->data));
                continue;
            }

            $it++;

            if($it % 10 == 0)
                $this->createEvent($it, count($this->data));
        }

        $time = now()->subMonth();
        $replays_array = Data::whereIn('login', $logins)->where('created_at', '>=', $time)->get();
    
        if(count($replays_array) > 0)
        {
            for($i=count($data_records)-1;$i>=0;$i--)
            {
                foreach($replays_array as $replay)
                {
                    if($replay->login == $data_records[$i]['login'])
                    {
                        $replays++;
                        $added--;
                        unset($data_records[$i]);
                        break;
                    }
                }
            }
        }

        Data::insert($data_records);

        $this->createEvent($it, count($this->data), $added, $replays);

        return true;
    }

После этого, в окне должны отображатся данные. Иногда Job запускается 2 раза и данные создаются 2 раза или ajax выводит сообщение: "Произошла ошибка: undefined". В чем может быть причина?
View stats.php:

var showing = false;

	var pusher = new Pusher('<?=env('PUSHER_APP_KEY') ?>', {
	  cluster: 'ap1',
	  forceTLS: true
	});

  @php
    $user = Auth::user();
  @endphp

	var channel_f = pusher.subscribe('main-channel');
    channel_f.bind('load-accounts-event', function(data) {
      var button = $('#uploadBtn');
      var json = JSON.parse(data.message);
      var item = $('#uploadModal');
      var bar = $('div.bar-load');
      if(json.user == {{ $user->id }})
      {
        item.find('span.load-c').html(json.data.completed + '/' + json.data.all);
        bar.attr('style', 'width: '+json.data.percent+'%;').html(json.data.percent + '%');
        if(json.data.completed >= json.data.all && !showing)
        {
        	item.find('span.load-c').html(json.data.completed + '/' + json.data.all + ' (' + json.data.loaded + ' загружено / ' + json.data.replays + ' повторов)');
          button.html('Загрузить');
          $.growl.notice({ title: '', message: 'Загрузка успешно завершена', location: 'tc' });
          showing = true;
        }
      }
    });

$('#uploadBtn').on('click', function() {
        var data = $('#dataList').val();

        $(this).attr('disabled', true).html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span><span class="sr-only">Loading...</span>');
        
        $.ajax({
          type: "POST", 
          dataType: "json", 
          url: "{{ route('ajax.stats.upload') }}",
          data: {
            _token:window.Laravel.csrfToken,
            data:data
          },
          complete: function(response) {
	          if (response.status == 200) {
	            $.growl.notice({ title: '', message: response.responseText, location: 'tc' });
	          } else {
	          	$.growl.error({ title: '', message: 'Произошла ошибка: ' + response.responseText, location: 'tc' });
	            console.log('Ooops. Error: ' + response.responseText);
	          }
          }
        });
      });

Лог: worker-load-data.log.

[2019-10-24 15:32:00][13275] Processing: App\Jobs\LoadData
[2019-10-24 15:32:00][13275] Processing: App\Jobs\LoadData
[2019-10-24 15:32:00][] Processing: App\Events\LoadDataEvent
[2019-10-24 15:32:00][] Processing: App\Events\LoadDataEvent
[2019-10-24 15:32:01][] Processed:  App\Events\LoadDataEvent
[2019-10-24 15:32:01][] Processed:  App\Events\LoadDataEvent
[2019-10-24 15:32:05][] Processing: App\Events\LoadDataEvent
[2019-10-24 15:32:05][] Processing: App\Events\LoadDataEvent
[2019-10-24 15:32:05][] Processed:  App\Events\LoadDataEvent
[2019-10-24 15:32:05][] Processed:  App\Events\LoadDataEvent
[2019-10-24 15:32:06][13275] Processed:  App\Jobs\LoadData
[2019-10-24 15:32:06][13275] Processed:  App\Jobs\LoadData
[2019-10-24 15:32:45][13276] Processing: App\Jobs\LoadData
[2019-10-24 15:32:45][] Processing: App\Events\LoadDataEvent
[2019-10-24 15:32:45][] Processed:  App\Events\LoadDataEvent
[2019-10-24 15:32:45][] Processing: App\Events\LoadDataEvent
[2019-10-24 15:32:46][] Processed:  App\Events\LoadDataEvent
[2019-10-24 15:32:46][13276] Processed:  App\Jobs\LoadData

13276 отработал как надо, а вот 13275 запустилась 2 раза

Изменено pahanjkee (24.10.2019 15:38:18)

Не в сети

Подвал раздела