Команда Laravel, которая теперь должна быть «доступна» через http - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть веб-приложение, созданное в Laravel, которое принимает платежи по кредитным картам.

Каждый день созданная мной запланированная команда запускает «сегодняшние» платежи (в основном она отправляет один http-запрос на каждый ожидающий платеж вплатежный шлюз).

Теперь мне нужно разрешить запуск этого процесса отправки платежа с помощью кнопки на панели инструментов.

Для выполнения команды требуется много времени (в зависимости от количестваплатежи для обработки), поэтому вызывать его из контроллера, я думаю, что это не вариант.

Я думаю просто реорганизовать его: переместить весь код команды в класс "middleman", чтобы я мог вызвать этот класскак на команду, так и на контроллер.

PaymentsSubmissionHelper::submit()

PaymentsSubmissionCommand: PaymentsSubmissionHelper::submit()
PaymentsSubmissionController: PaymentsSubmissionHelper::submit()

Тем не менее, команда отображает индикатор выполнения и приблизительное время обработки, и мне потребуется также отобразить индикатор выполнения в html-интерфейсе.В веб-интерфейсе мне нужно будет сделать ajax-запросы на сервер, чтобы получить текущий прогресс, но в команде этот прогресс отслеживается совершенно по-другому, используя:

$bar = $this->output->createProgressBar($totalPayments);
$bar->setFormat(' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %message%');

и для каждого обработанного платежа:

$bar->advance();

Как создать отслеживание прогресса как для команды, так и для контроллера?

Любая помощь будет оценена.

Заранее спасибо!

Ответы [ 3 ]

0 голосов
/ 13 февраля 2019

Поскольку вы используете индикатор прогресса и продвигаете его, вы будете делать то же самое в ajax, но логика прогресса будет отличаться от курса.

Общей частью в обоих случаях является обработка каждой платежной карты.Поэтому я скажу создать отдельный класс или службу, которая принимает экземпляр платежной карты, например, PaymentProcess, обрабатывает его и возвращает в случае успеха или неудачи.

Затем в команде вы можете выполнить (psuedocode):

public function handle () {$ pendingPayments = Payment :: where ('status', 'pending');

$bar = $this->output->createProgressBar($pendingPayments->count());

$pendingPayments->chunk(10, function($payments) use($bar){

    $payments->each(function($payment) use ($bar){

        $process = (new PaymentProcess($payment))->process();

        $bar->advance();

    });
});

$bar->finish();

}

Теперь, если вы запустите это из внешнего интерфейса,ответ ajax должен дать вам идентификатор текущего процесса, хранящегося где-то.Затем вы будете продолжать посылать другие ajx-запросы с интервалом, скажем, 1 секунду, и получать текущий прогресс, пока он не достигнет 100%.(Если вы используете XMLHttpRequest2, тогда логика будет отличаться)

Для этого вы можете создать еще одну таблицу для хранения результатов и затем обновлять ее.

Теперь аналогичным образом вы можете использовать PaymentProcess внутри контроллера.:

открытая функция processPendingPayments (Request $ request) {// Авторизовать запрос $ this-> authorize ('processPendingPayments', Payment :: class);

$pendingPayments = Payment::where('status', 'pending');

// Create a progress entry
$progress = PaymentProgress::create([
    'reference' => str_random('6')
    'total' => $pendingPayments->count(),
    'completed' => 0
]);

$pendingPayments->chunk(10, function($payments) use($bar){

    $payments->each(function($payment) use ($bar){

        $process = (new PaymentProcess($payment))->process();

        // Update a progress entry
        $progress->update([
            'completed' => $progress->completed + 1;
        ]);

    });
});

return response()->json([
    'progress_reference' => $progress->reference
], 200);

}

Теперь еще одна конечная точка для получения прогресса

открытая функция getProgress (Request $ request) {// Авторизовать запрос $ this-> authorize ('getProgress', Payment :: class);

$request->validate([
    'reference' => 'required|exists:payment_process,reference'
]);

$progress = PaymentProcess::where('reference', $request->reference)->first();

$percentage = $progress->completed / $progress->total * 100;

 return response()->json(compact('percentage'), 200);

}

0 голосов
/ 13 февраля 2019

Как уже указывалось в другом ответе, Прослушиватели событий Laravel в очереди - это способ обработки длительных процессов во внешнем интерфейсе.Вам вообще не нужно реорганизовывать консольную команду.

Что касается показа прогресса во внешнем интерфейсе, одним простым решением было бы установить некоторый опрос AJAX.Каждые несколько секунд AJAX запускает запрос к методу контроллера, который просто просматривает сегодняшние платежи, вычисляет, сколько обработано (возможно, у вас есть какое-то поле status, которое покажет вам, обрабатывалось ли уже запущенное задание или нет.) и вернуть число, представляющее процент выполненных работ.Затем обработчик AJAX success обновит ваш трекер прогресса на странице.

// Check status every 2s
var timer = setInterval(function() {
    pollStatus();
}, 2000);

pollStatus = function() {
    $.ajax({
        url: 'somewhere/jobStatus',
        success: function(resp) {
            $('#progress').html(resp . '%');

            if (resp === 100) {
                // We've reached 100%, no need to keep polling now
                clearInterval(timer);
            }
        }
    });
}

Возможно, было бы целесообразно каким-то образом убедиться, что опросы не будут перегружены, и, возможно, вы захотите настроить частотуопрос.

0 голосов
/ 13 февраля 2019

Я бы предложил использовать прослушивателей событий в очереди в этом случае использования.Вы отправили бы событие в свой контроллер и получили бы прослушиватель, который мог бы запустить команду.Ставя слушателя в очередь, вы избегаете длительного времени ответа.Не нужно реорганизовывать саму команду!

Что касается индикатора выполнения, у вас может быть статическая индикаторная строка, которая обновляется при загрузке страницы, где вы будете считывать статус из вашей БД и отображать его так же, как Amazon показывает, какВ любой момент ваш заказ может быть далеко.

Для обновленного индикатора выполнения в реальном времени я предлагаю использовать веб-сокеты. Socket.io кажется великолепным.

...