Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save digitaltim-de/8bad4dd794561faa28f6f1e4a8b9c298 to your computer and use it in GitHub Desktop.
Save digitaltim-de/8bad4dd794561faa28f6f1e4a8b9c298 to your computer and use it in GitHub Desktop.
<?php
declare(strict_types=1);
namespace App\Service;
use Fiber;
class PHPAsyncRequests
{
private array $requests = [];
private array $handleMap = [];
private array $curlHandles = [];
private \CurlMultiHandle $mh;
private \CurlMultiHandle $mhFiber;
private bool $successful = false;
private Fiber $fiber;
public function __construct(array $requests)
{
$this->requests = $requests;
$this->mh = curl_multi_init();
$this->mhFiber = curl_multi_init();
}
public function execute()
{
$this->prepareHandles();
$this->startFiber();
$this->processMainHandles();
$this->processFiberHandles();
$this->closeHandles();
return $this->successful;
}
private function prepareHandles()
{
$halfOfList = floor(count($this->requests) / 2);
foreach ($this->requests as $index => $request) {
$ch = curl_init($request['url']);
$this->curlHandles[] = $ch;
if ($index > $halfOfList) {
curl_multi_add_handle($this->mhFiber, $ch);
$this->handleMap[(int)$ch] = $this->mhFiber;
} else {
curl_multi_add_handle($this->mh, $ch);
$this->handleMap[(int)$ch] = $this->mh;
}
}
}
private function startFiber()
{
$this->fiber = new Fiber(function () {
$still_running = null;
do {
curl_multi_exec($this->mhFiber, $still_running);
while ($info = curl_multi_info_read($this->mhFiber)) {
if ($info['msg'] == CURLMSG_DONE) {
$this->successful = true;
break;
}
}
Fiber::suspend();
} while ($still_running && !$this->successful);
});
$this->fiber->start();
}
private function processMainHandles(): void
{
$still_running = null;
do {
$status = curl_multi_exec($this->mh, $still_running);
while ($info = curl_multi_info_read($this->mh)) {
if ($info['msg'] == CURLMSG_DONE) {
$this->successful = true;
break;
}
}
if ($this->successful) {
break;
}
} while ($still_running);
}
private function processFiberHandles(): void
{
while (!$this->fiber->isTerminated()) {
$this->fiber->resume();
}
}
private function closeHandles()
{
foreach ($this->curlHandles as $ch) {
$multiHandle = $this->handleMap[(int)$ch];
curl_multi_remove_handle($multiHandle, $ch);
}
curl_multi_close($this->mh);
curl_multi_close($this->mhFiber);
}
}
$requests = [
[
'url' => 'https://webhook.site/fad1851c-62a5-4d6b-abf8-ef8fadca0fe6',
'options' => [CURLOPT_TIMEOUT => 10, /* Weitere Optionen */],
],
[
'url' => 'https://webhook.site/fad1851c-62a5-4d6b-abf8-ef8fadca0fe6',
'options' => [CURLOPT_RETURNTRANSFER => true, /* Weitere Optionen */],
],
[
'url' => 'https://testfile.org/files-5GB',
'options' => [CURLOPT_RETURNTRANSFER => true, /* Weitere Optionen */],
],
];
$parallelRequests = new PHPAsyncRequests($requests);
$status = $parallelRequests->execute();
@digitaltim-de
Copy link
Author

Anyone maybe want to update this ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment