Проблема: мне нужно клонировать / скачать несколько репозиториев 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
ни один из этих enxtensiosn не установлен
"suggest": {
"ext-libevent": ">=0.1.0",
"ext-event": "~1.0",
"ext-libev": "*"},
поэтому StreamSelectLoop используется
Основная проблема, с которой вы имеете дело, заключается в том, что $git->cloneRepository()
звонок блокируется; Reactphp просто позволяет работать с циклами уровня приложения. Если вы не делаете свой код неблокирующим, тогда ваш код все равно будет работать линейно. Вы должны выяснить, как заставить клон происходить на заднем плане; это может быть сделано путем разветвления процесса или вызова другого php-скрипта для запуска в фоновом режиме. Я не уверен, что git-оболочка работает так, но если вы можете найти библиотеку, которая выполняет git-вызовы неблокирующим образом; тогда ваша проблема будет в основном решена.
ReactPHP не превращает php в неблокирующую, он просто обеспечивает среду, позволяющую использовать неблокирующую технику. Если ваш код блокируется, цикл реакции не будет запущен.
Других решений пока нет …