Запуск кода параллельно с ReactPhp

Проблема: мне нужно клонировать/загрузить несколько репозиториев git, к сожалению, последовательное выполнение этого занимает целую вечность. У меня возникла идея использовать цикл событий ReactPhp и делать это параллельно.

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

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

use Symfony\Component\Stopwatch\Stopwatch;

include 'vendor/autoload.php';

$toClone = [
    ['url' => 'http://github.com/symfony/symfony.git', 'dest' => 'C:\tmp\cloneR1'],
    ['url' => 'http://github.com/laravel/laravel.git', 'dest' => 'C:\tmp\cloneR2'],
    ['url' => 'http://github.com/rails/rails.git', 'dest' => 'C:\tmp\cloneR3'],
];
$end = count($toClone);
$i = 0;

$deferred = new React\Promise\Deferred();
$fClone = function (\React\EventLoop\Timer\Timer $timer) use (&$i, $deferred, &$toClone, $end) {
    $project = array_pop($toClone);
    $git = new \GitWrapper\GitWrapper();
    $git->setTimeout(3600);
    $git->cloneRepository($project['url'], $project['dest']);
    $deferred->notify([$i++, $project['url']]);
    if ($end <= $i) {
        $timer->cancel();
        $deferred->resolve();
    }
};

$stopwatch = new Stopwatch();
$stopwatch->start('run');

$loop = React\EventLoop\Factory::create();
$loop->addPeriodicTimer(1, $fClone);

$deferred->promise()->then(function () use ($stopwatch) {
    echo 'DONE' . PHP_EOL;
    $event = $stopwatch->stop('run');
    echo 'Run took ' . $event->getDuration() / 1000 . 'sec and ' . $event->getMemory() . ' bytes of memory';
}, null, function ($data) {
    echo 'RUN ' . $data[0] . ' - ' . $data[1] . PHP_EOL;
});


$loop->run();

мой композитор.json

{
    "require": {
        "react/promise": "2.2.0",
        "react/event-loop": "0.4.1",
        "cpliakas/git-wrapper": "1.4.1",
        "symfony/stopwatch": "2.7.0"
    }
}

ОС: Windows7 PHP: 5.4.8 и 5.5.20
ни одно из этих расширений не установлено

"suggest": {
    "ext-libevent": ">=0.1.0",
    "ext-event": "~1.0",
    "ext-libev": "*"
},

поэтому используется StreamSelectLoop


person mrok    schedule 04.06.2015    source источник
comment
Попробуйте pthreads, я скомпилировал его на Linux PHP, не уверен, что он хорошо работает в Windows.   -  person Daniel W.    schedule 05.06.2015


Ответы (1)


Основная проблема, с которой вы сталкиваетесь, заключается в том, что вызов $git->cloneRepository() блокируется; reactphp просто позволяет работать с циклами на уровне приложения. Если вы не сделаете свой код неблокирующим, ваш код все равно будет работать линейным образом. Вы должны выяснить, как заставить клон работать в фоновом режиме; это можно сделать, разветвив процесс или вызвав другой php-скрипт для запуска в фоновом режиме. Я не уверен в обертке git, которая работает так, но если вы можете найти библиотеку, которая выполняет вызовы git неблокирующим образом; тогда ваша проблема будет почти решена.

ReactPHP не превращает php в неблокирующий, он просто предоставляет структуру, позволяющую использовать неблокирующие методы. Если ваш код блокируется, цикл реагирования не будет запущен.

person Method    schedule 05.06.2015