You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I tried to build a system with reactphp/http and reactphp/async to do http calls in parallel in cascade.
🚀 Locally in docker working perfectly.
🎁 When deploying on AWS Lambda (Lambda as a Docker Image) via serverless deploy, surprise:
RequestId: 5ad1b639-980b-4f3c-baf6-7ac7d40971ee Error: Runtime exited with error: exit status 141
Runtime.ExitError
I manage to fix it with:
// Try to handle SIGPIPE and other potential signals gracefully\pcntl_async_signals(true);
\pcntl_signal(SIGPIPE, function() {
echo'Caught SIGPIPE, closing socket.' . PHP_EOL; // Remove this line in prod
});
With \pcntl_async_signals(true);, you enable asynchronous signal handling for your program, allowing it to catch and handle signals.
With the \pcntl_signal(SIGPIPE, ...), you specify a handler function for SIGPIPE.
While it fixes my little PoC. It is not fixing the whole project.
But it feels like a hack. I like it could crash anytime since
AWS Lambda does not provide full support for handling Unix signals as it abstracts many of these lower-level system interactions, which might lead to unexpected behavior or inability to handle signals properly.
I saw you have implemented several EventLoop type of implementation. Did I miss something ?
The bref lambda layer has [pcntl](https://www.php.net/manual/en/book.pcntl.php) by default.
Thanks in advance
Have a great day
<?phpdeclare(strict_types=1);
namespaceApp\Model;
usePsr\Log\LoggerInterface;
useReact\EventLoop\Loop;
useReact\Http\Browser;
usefunctionReact\Async\await;
usefunctionReact\Promise\all;
class Test
{
publicfunction__construct(
privatereadonlyLoggerInterface$logger
) {
}
publicfunctionrun(): void
{
// Try to handle SIGPIPE and other potential signals gracefully\pcntl_async_signals(true);
\pcntl_signal(SIGPIPE, function() {
// echo 'Caught SIGPIPE, closing socket.' . PHP_EOL;
});
$loop = Loop::get();
$browser = newBrowser($loop);
$browser->withTimeout(60);
$url = 'https://httpbin.org/delay/';
$startAt = microtime(true);
$stats = newStats(
randomDelays: [],
sequentialTotal: 0,
realTime: 0,
percent: 0,
);
$promises = $this->fetchRequests($browser, $stats, $url);
$expectedTotal = max($stats->randomDelays);
// Wait for all promises to be resolved$promisesAll = all($promises)->then(function (array$numbers) use ($startAt, $expectedTotal, $stats) {
$numbersList = implode(', ', $numbers);
echo"All tasks completed: $numbersList\n";
echo"Sequential total: {$stats->sequentialTotal}s\n";
echo"Expected total: {$expectedTotal}s\n";
$realTime = round(microtime(true) - $startAt, 2);
echo"Real time: {$realTime}s\n";
$percent = round($realTime / $expectedTotal * 100, 2);
echo"Percent: $percent%\n";
});
$firstPasses = await($promisesAll);
var_dump($firstPasses);
// 2xecho"************************\n";
echo"2nd time\n";
$promises = $this->fetchRequests($browser, $stats, $url);
$expectedTotal = max($stats->randomDelays);
// Wait for all promises to be resolved$promisesAll = all($promises)->then(function (array$numbers) use ($startAt, $expectedTotal, $stats) {
$numbersList = implode(', ', $numbers);
echo"All tasks completed: $numbersList\n";
echo"Sequential total: {$stats->sequentialTotal}s\n";
echo"Expected total: {$expectedTotal}s\n";
$realTime = round(microtime(true) - $startAt, 2);
echo"Real time: {$realTime}s\n";
$percent = round($realTime / $expectedTotal * 100, 2);
echo"Percent: $percent%\n";
});
$secondPasses = await($promisesAll);
var_dump($secondPasses);
// Run the event loop$loop->run();
}
/** * @return \React\Promise\PromiseInterface[] */privatefunctionfetchRequests(Browser$browser, Stats$stats, string$url): array
{
$requests = [];
$time = microtime(true);
for ($i = 1; $i <= 10; ++$i) {
$randomDelay = rand(1, 10);
if (1 === $i) {
$randomDelay = 10;
}
$stats->randomDelays[] = $randomDelay;
$stats->sequentialTotal += $randomDelay;
$delayedUrl = $url.$randomDelay;
$receivedAt = date('H:i:s');
echo"$receivedAt: Init $i ({$randomDelay}s)\n";
echo"$receivedAt: Start $delayedUrl\n";
$timeHttp = microtime(true);
$logger = $this->logger;
// Yield the promise from the HTTP request$requests[] = $browser->request('GET', $delayedUrl)->then(
function ($response) use ($i, $time, $timeHttp) {
$body = (string) $response->getBody();
$receivedAt = date('H:i:s');
$timeHttp = round(microtime(true) - $timeHttp, 2);
$receivedAt = date('H:i:s');
$inSeconds = round(microtime(true) - $time, 2);
echo"$receivedAt: End $i in {$inSeconds}s (HTTP {$timeHttp}s)\n";
return$i; // Return the number for successful results
},
function ($error) use ($i, $logger) {
echo"End $i: Error: ".$error->getMessage()."\n";
error_log('Request error: '.$error->getMessage());
$logger->critical(
'Request error',
['error' => $error->getMessage()]
);
return$i; // Return the number even in case of error
}
);
}
return$requests;
}
}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Hi,
👏 Thanks for the incredible work.
I tried to build a system with reactphp/http and reactphp/async to do http calls in parallel in cascade.
🚀 Locally in docker working perfectly.
🎁 When deploying on AWS Lambda (Lambda as a Docker Image) via
serverless deploy
, surprise:I manage to fix it with:
While it fixes my little PoC. It is not fixing the whole project.
But it feels like a hack. I like it could crash anytime since
I saw you have implemented several EventLoop type of implementation. Did I miss something ?
The bref lambda layer has
[pcntl](https://www.php.net/manual/en/book.pcntl.php)
by default.Thanks in advance
Have a great day
Beta Was this translation helpful? Give feedback.
All reactions