Не удается прочитать в реальном времени из redis

У меня есть приложение с длительным временем работы сервера, которое хранит процесс следующим образом:

routes.php

Route::post('cloud/slice/{modelfileid}', '[email protected]');
Route::get('cloud/slice/sliceProgress', '[email protected]');

часть функции slice():

while($s = fgets($pipes[2]))
{
    if(strpos($s, "Progress:") !== FALSE)
    {
        Log::info(100 * substr($s, -10, 4) . '%');
        $this->redis->SET('sliceProgress' . $uid, 100 * substr($s, -10, 4) . '%');

    }
}

а мой клиент каждые 0,5 секунды запрашивает прогресс в redis с этим:

public function sliceProgress()
{
    if (!isset($_SESSION["uid"]))
        return Redirect::to('cloud');
    $uid = $_SESSION["uid"];
    return Response::json(array('status' => 'success', 'data' => array('progress' => $this->redis->GET('sliceProgress' . $uid))));
}

и

$interval(function()
{
    $scope.refreshProgress();
}, 500);

Но клиент получит запрос о проделанной работе до конца со 100%, без прогресса, который составляет менее 100%. То есть, я получаю ответ на ход, когда приложение среза сервера завершено. Я полагаю, что laravel не обрабатывает второй запрос при обработке среза.


Отредактировано: Я использую ниже код, чтобы получить redis в slice() после того, как redis- > SET работает хорошо, это выводит sliceProgress в реальном времени.

Log::info($this->redis->GET('sliceProgress' . $uid));

Ответ 1

Попробуйте запустить этот код в фоновом процессе, таком как асинхронные очереди или crons

while($s = fgets($pipes[2]))
{
if(strpos($s, "Progress:") !== FALSE)
{
    Log::info(100 * substr($s, -10, 4) . '%');
    $this->redis->SET('sliceProgress' . $uid, 100 * substr($s, -10, 4) . '%');

}
}

Ответ 2

Я считаю, что проблема может быть Session Lock. Подумайте, что вы уволили запрос POST после нескольких вызовов GET. Теперь, если существует блокировка сеанса, ни один из запросов на получение не будет обрабатываться PHP до тех пор, пока не будет выполнен первый.

Как работает Session Lock?
Ну php просто блокирует файл сеанса для чтения, поэтому все остальные процессы Apache должны ждать. Laravel также использует управление сеансом на основе файлов, поэтому.

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

Я не уверен на 100%, как laravel обрабатывает блокировку сеанса, поэтому просто перепроверьте, если это проблема.

Удаление блокировки сеанса:
Первый способ: использовать метод, как только вы закончили обработку сеанса session_write_close.
Во-вторых: Pass read_and_close будет истинным во время стартового сеанса с session_start

Не уверен, разрешает ли laravel это делать. Существуют и другие способы выполнения синхронизации в реальном времени.