Skip to content

Execute async concurrent requests

Choosing the right software package to enable a new feature in your code can be hard task. You’re adding a dependency which always comes with risks and trade-offs.

PHP was very late to the party offering an out-of-the-box solution for handling async requests in parallel (also called concurrency). PHP 8.1 was released in november 2021 and offers a new feature called Fibers.

Fibers are primitives for implementing lightweight cooperative concurrency. They are a means of creating code blocks that can be paused and resumed like Generators, but from anywhere in the stack. Fibers themselves don't magically provide concurrency, there still needs to be an event loop. However, they allow blocking and non-blocking implementations to share the same API.

Fibers allow getting rid of the boilerplate code previously seen with Promise::then() or Generator based coroutines. Libraries will generally build further abstractions around Fibers, so there's no need to interact with them directly.
Source: https://www.php.net/releases/8.1/en.php#fibers

Solutions found:

URLProsConsWebsockets
GuzzleUses Guzzle! The most used PHP HTTP client. Only three files for using a middleware solution for handling websocket requests. Relative new and not used by manyNeeds 8.2 and does not work with 8.1.
RevoltCollaboration initiative between AMPHP and ReactPHPLow-level, Lean, It uses PHP fibers which is new since 8.1 Fast
ReactPHPLow-level, Feels outdated
AMPHPHuge adoption for v2Lack of documentation for v3, v3 is relative new
Open SwooleAbsolutely fastThere is a PECL available, Relative new
spatie/asyncEasy to use
PPMOutdated
FrankenPHPNo async support (yet)
php-wssIncludes a client and server implementation

Considerations while choosing an solution for supporting concurrency requests in Nostr-PHP

  • Using a low-level package (Revolt, ReactPHP) is better than a framework (Open Swoole, AMPHP)
  • Fewer dependencies is better, so the codebase stays as small as possible
  • Writing native PHP async concurrent requests with fibers is something to consider in the future if we’re struggling with the choosen package.
  • The chosen package should support websockets, so we handle the requests relay requests through a websocket client in Nostr-PHP.
PackageReleaseFirst commit# contributors# open issues# stars# installs# dependenciesDate noted
revolt/event-loop1.0.625-07-20211257866.699.3831019-08-2024
amphp/amp3.0.204-08-201344154.18669.818.4751319-08-2024
react/event-loop1.0.529-04-2012352123159.180.077420-08-2024
openswoole/core22.1.1519-12-20211041344334.4417119-08-2024
valtzu/guzzle-websocket-middleware0.2.009-05-202451029104-10-2024
php-wss2.0.522-11-201547209720.885504-10-2024

Some insights

  • AMPHP v3 uses Revolt as a dependency for event loops - source: https://github.com/amphp/amp/issues/428
  • ReactPHP and AMPHP are similar and both async framework
  • Revolt seems to be up-to-date and is easier in use
  • Open Swoole is relative new and also had some drama in the past
  • For a solid, low-level integration ReactPHP seems to be the right dependency
  • My expectation the adoption Revolt will increase and is the best option for the future. It’s also much leaner compared to ReactPHP as it’s using the new fibers feature since PHP 8.1. As far as I researched and found, there is no support in the package for websockets (yet). Here we could use https://github.com/ratchetphp/Pawl which is a websocket client supporting concurrency.

Other resources

Released under the MIT License. Supported by OpenSats.
Source Code