Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Потеря данных в фоновых процессах. #10

Closed
nepster-web opened this issue Apr 16, 2016 · 17 comments
Closed

Потеря данных в фоновых процессах. #10

nepster-web opened this issue Apr 16, 2016 · 17 comments
Labels

Comments

@nepster-web
Copy link

nepster-web commented Apr 16, 2016

Здравствуйте. Решил попробовать использовать ваше расширение и получилось так, что оно не запускает команды в фоне.

Конфигурация:

    'controllerMap' => [
       ...
        'background-bus' => [
            'class' => 'trntv\bus\console\BackgroundBusController',
        ]
    ],

    'components' => [
     ...
        'commandBus' => [
            'class' => 'trntv\bus\CommandBus',
            'middlewares' => [
                [
                    'class' => '\trntv\bus\middlewares\BackgroundCommandMiddleware',
                    'backgroundHandlerBinary' => '/usr/bin/php',
                    'backgroundHandlerPath' => '@app/../yii',
                    'backgroundHandlerRoute' => 'background-bus/handle',
                ],
                [
                    'class' => '\trntv\bus\middlewares\LoggingMiddleware',
                    'level' => 1,
                ],
            ],
        ],
],

Команда:

<?php

namespace app\commands\handles;

use trntv\bus\middlewares\BackgroundCommandTrait;
use trntv\bus\interfaces\BackgroundCommand;
use trntv\bus\interfaces\SelfHandlingCommand;
use yii\base\Object;
use Yii;

class TestCommand extends Object implements BackgroundCommand, SelfHandlingCommand
{
    use BackgroundCommandTrait;

    public $setTo;

    public $subject;

    public $view;

    public $data;

    /**
     * @param $command
     */
    public function handle($command)
    {
        for($i = 0; $i <= 100000000; $i++) {

        }

        // sleep(5);

        echo 'test';

        /*$mail = Yii::$app->getMailer();

        $mail->compose($this->view, [])
            ->setTo($this->setTo)
            ->setSubject($this->subject)
            ->send();*/
    }
}

Запуск

        Yii::$app->commandBus->handle(new \app\commands\handles\TestCommand([
            'setTo' => 'example@mail.ru',
            'subject' => 'Тест',
            'view' => 'test',
            'data' => []
        ]));

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

С текущей конфигурацией и кодом ошибок не возникает, все отрабатывает корректно, за исключением того, что сама команда выполняется не в фоне. Тоесть идет загрузка на протяжении нескольких секунд пока не отработает цикл или sleep.

@nepster-web
Copy link
Author

Походу тут ошибка в документации: https://github.com/trntv/yii2-command-bus#2-background-commands-support-optional

Если использовать

    public $async = true;

Будет вот такая ошибка:

 PHP Compile Error – yii\base\ErrorException
app\commands\handles\TestCommand and trntv\bus\middlewares\BackgroundCommandTrait define the same property ($async) in the composition of app\commands\handles\TestCommand. However, the definition differs and is considered incompatible. Class was composed

Для корректной работы необходимо полностью переопределить метод:

    public function isAsync()
    {
        return true;
    }

@nepster-web
Copy link
Author

Остается только проблема с потерей данных, подробнее: http://yiiframework.ru/forum/viewtopic.php?f=19&p=186572#p186572

@trntv
Copy link
Owner

trntv commented Apr 20, 2016

Спасибо за информацию, сегодня проверю поведение async и попробую зарепродюсить потерю.

@nepster-web
Copy link
Author

Если не получится, я смогу вам продемонстрировать пример.

@nepster-web
Copy link
Author

Получилось проверить ?

trntv pushed a commit that referenced this issue Apr 23, 2016
@trntv
Copy link
Owner

trntv commented Apr 23, 2016

Документацию немного подправил, дописал тесты, но воспроизвести не удалось.

Попробуйте склонировать проект в какую-то папку, заинстались зависимости и запустить в корне проекта

docker-compose up -d
./vendor/bin/phpunit

@nepster-web
Copy link
Author

К сожалению буду только вечером. Но на первый взгляд мне кажется проблема в том, что я целенаправленно ставил sleep или цикл который делает команду более сложной. Тоесть она выполняется несколько секунд. Возможно проблема именно в этом.

@nepster-web nepster-web changed the title Не работают фоновые процессы. Потеря данных в фоновых процессах. Apr 23, 2016
@nepster-web
Copy link
Author

Например если команда выполняется секунд десять, а мы в первую секунду запускаем сразу 10 команд.

@trntv
Copy link
Owner

trntv commented Apr 23, 2016

Вообщем попробуйте как будет возможность, плюс поиграйтесь с вот этим вот тестом, с параметром sleep команды, возможно удастся понять закономерность:
https://github.com/trntv/yii2-command-bus/blob/master/tests/BackgroundMiddlewareTest.php#L24

@nepster-web
Copy link
Author

nepster-web commented Apr 23, 2016

К сожалению не успел поработать с тестами, особо дел с ними не имел, как и с докером, вот только поставил докер, но нужно будет чуть больше времени поразбираться. А пока есть пример с помощью старого дедовского способа:

Обычный экшин в приложении:

    public function actionTest()
    {
        $cr = new \vova07\console\ConsoleRunner(['file' => '@app/../yii']);
        $cr->run('test/test');

        Yii::$app->commandBus->handle(new \app\commands\handles\TestCommand([
            'async' => true,
        ]));

    }

Тут я пытаюсь сравнить ранее используемый ConsoleRunner с Вашей командной шиной.

Код для ConsoleRunner:

    public function actionTest()
    {
        for($i = 0; $i <= 100000000; $i++) {

        }
        Yii::error('+++++');
    }

Код для шины:

    public function handle($command)
    {
        for($i = 0; $i <= 100000000; $i++) {

        }
        Yii::error('----');
    }

Далее, просто запускаю 10 раз экшин, который все это дело вызывает. Так как у меня логи записываются в базу данных, мы легко видим результат:
_2016-04-23_22-41-12

ConsoleRunner честно отрабатывает 10 раз.
А вот командная шина всего 3 раза при одинаковых условиях.

К сожалению по загруженности поработать с тестами и выдать результат смогу возможно к следующим выходным. Хотя пока честно говоря не представляю как можно затестировать запуск в фоновом решиме.

@nepster-web
Copy link
Author

@trntv итак ситуация следующая. В вашем тесте вы тестируете непосредственно работу команды. Тест будет всегда выполнятся, так как ошибок в самой команде нет.

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

Однако старый дедовский метод всегда под рукой. Поэтому я еще раз сравнил, но на этот раз уже 3 расширения:

        // Console Runner
        $cr = new \vova07\console\ConsoleRunner(['file' => '@app/../yii']);
        $cr->run('test/test');

        // Command Bus
        Yii::$app->commandBus->handle(new \app\commands\handles\TestCommand([
            'async' => true,
            'setTo' => 'nepsterxxx@mail.ru',
            'subject' => 'Тест',
            'view' => 'test',
            'data' => []
        ]));

        // Symfony
        $process = new Process(Yii::getAlias('@app/../yii') . ' test/test2');
        $process->start();

Опять таки условия все одинаковые и команды тоже. Запускаем выполнение 10 раз и результаты примерно такие:
ConsoleRunner - 10 / 10
commandBus - 7 / 10
Process - 6 / 10

Я понятия не имею в чем прикол, и скорее всего есть какае-то особенность так как Process сериализует объект и кидает в фон, а ConsoleRunner просто запускает экшин через консольную утилиту yii.

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

@trntv
Copy link
Owner

trntv commented May 5, 2016

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

Issues о Process надо отправлять в репозиторий самой symfony

@nepster-web
Copy link
Author

@trntv ну она отрабатывает, но не всегда. Тоесть я делаю 10 запусков, а команда отрабатывает от 4 до 7 раз.

Я еще не проверял, решил ли эту проблему например redis.

К сожалению я только учу англ однако он достаточно слабенький, но попробую что-то накалякать, возможной поймут.

Спасибо.

@trntv trntv added the invalid label Aug 17, 2016
@trntv trntv closed this as completed Aug 17, 2016
@sanchezzzhak
Copy link

sanchezzzhak commented Feb 10, 2017

Добрый день проблему решили?

Я тут на днях все способы перепробовал на win7-10
с флагом 'async' => true,

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

пока решил это костыльным путем через curl + дополнительный экшин в контроллере

@nepster-web
Copy link
Author

Здравствуйте. За себя отвечу, что нет. Пропала необходимость работать с данным расширением.

@TheElk2
Copy link

TheElk2 commented Apr 22, 2017

У меня лично приходил signal 9 от symfony/process. Ему памяти не хватало, хотя на сервере было на тот момент 2Gb. То бишь какие-то задания прогонял, на каких-то выпадал.

@nepster-web
Copy link
Author

Я тогда еще тестировал на локальном сервере, с 8Gb оперативы.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants