Last active
January 29, 2024 05:14
-
-
Save digitaltim-de/8bad4dd794561faa28f6f1e4a8b9c298 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Anyone maybe want to update this ;)