PHPackages                             php-aol/php-aol - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. php-aol/php-aol

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

php-aol/php-aol
===============

PHP 8.4+ attribute-driven async/concurrency library (Fibers + Revolt)

v0.0.1(1mo ago)14MITPHPPHP ^8.4CI passing

Since May 31Pushed 1mo agoCompare

[ Source](https://github.com/dot12x/php-aol)[ Packagist](https://packagist.org/packages/php-aol/php-aol)[ RSS](/packages/php-aol-php-aol/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (10)Versions (2)Used By (0)

php-aol
=======

[](#php-aol)

PHP 8.4+ attribute-driven async/concurrency library on Fibers + Revolt.

What it is
----------

[](#what-it-is)

A PHP async/concurrency library. The defining quality is attribute-driven declarative API: users do not write `await`, `yield`, `then()`, `go()`, `spawn`, or `task`. They write ordinary PHP classes annotated with attributes; AOL animates them at `Aol::wrap()` time and lets them live inside `Aol::scope()`. Process monitoring and concurrency share one mental model — wrap a class, let it live in a scope, let attributes describe its lifecycle and concurrency.

Requirements
------------

[](#requirements)

- PHP 8.4+
- Revolt event loop (`revolt/event-loop ^1.0`)

Install
-------

[](#install)

```
composer require php-aol/php-aol
```

Five-minute tour
----------------

[](#five-minute-tour)

### 1. Wrap, scope, async, auto-graph

[](#1-wrap-scope-async-auto-graph)

```
use Aol\Aol;
use Aol\Attribute\Async;

class ImageProcessor
{
    #[Async]
    public function resize(string $path, int $width): Image { ... }

    #[Async]
    public function compress(Image $img): Image { ... }
}

$proc = Aol::wrap(ImageProcessor::class);

$result = Aol::scope(function () use ($proc) {
    $a = $proc->resize('a.jpg', 800);   // Pending
    $b = $proc->compress($a);           // depends on $a — runs after
    $c = $proc->resize('b.jpg', 800);   // parallel with $a
    return [$b, $c];                    // scope close → real Images
});
```

`Pending` values passed as arguments declare dependencies automatically. The scope resolves all pending work before returning.

### 2. Worker pool with lifecycle

[](#2-worker-pool-with-lifecycle)

```
use Aol\Aol;
use Aol\Attribute\{Async, Worker, Restart, OnAwake, OnSleep, Retry, Timeout};

#[Worker(pool: 4, queue: 1024)]
#[Restart(max: 5, within: 60)]
class JobProcessor
{
    private \PDO $db;

    #[OnAwake]
    public function connect(): void { $this->db = new \PDO(...); }

    #[OnSleep]
    public function disconnect(): void { $this->db = null; }

    #[Async]
    #[Retry(times: 3, backoff: 'exponential', delay: 0.1, maxDelay: 5)]
    #[Timeout(30)]
    public function process(Job $job): Result { ... }
}

$pool = Aol::wrap(JobProcessor::class);  // 4 instances, OnAwake runs eagerly

Aol::scope(function () use ($pool, $jobs) {
    foreach ($jobs as $job) {
        $pool->process($job);            // distributed across 4 workers
    }
});                                      // OnSleep runs on each instance
```

### 3. Server-Sent Events (SSE)

[](#3-server-sent-events-sse)

```
use Aol\Aol;
use Aol\Http;

Aol::scope(function () {
    foreach (Http::sse('https://api.example.com/events') as $event) {
        echo "[{$event->event}] {$event->data}\n";
    }
});
```

Or declaratively on a wrapped class:

```
use Aol\Attribute\Worker;
use Aol\Http\Attribute\OnSse;
use Aol\Http\Sse\SseEvent;

#[Worker]
class Ingestor
{
    #[OnSse('https://api.example.com/events')]
    public function rx(SseEvent $event): void { /* per-event handler */ }
}
```

### 4. WebSocket

[](#4-websocket)

```
use Aol\Aol;
use Aol\WebSocket\WebSocket;

Aol::scope(function () {
    $ws = WebSocket::connect('wss://example.com/socket');
    $ws->send('hello');
    foreach ($ws->messages() as $msg) {
        echo $msg->payload, "\n";
    }
    $ws->close();
});
```

Or declaratively — `#[OnOpen]`/`#[OnMessage]`/`#[OnClose]` on a wrapped class. See [docs/websocket.md](docs/websocket.md).

### 5. Declarative HTTP client

[](#5-declarative-http-client)

```
use Aol\Http;
use Aol\Http\Attribute\{BaseUrl, Headers, Get, Post, Delete};
use Aol\Http\Attribute\{Path, Query, Body, Header};
use Aol\Attribute\{Retry, Timeout};

#[BaseUrl('https://api.github.com')]
#[Headers(['Accept' => 'application/vnd.github+json'])]
interface GitHubApi
{
    #[Get('/users/{login}')]
    #[Retry(times: 3, on: [NetworkException::class])]
    #[Timeout(10)]
    public function getUser(#[Path] string $login): User;

    #[Get('/users/{login}/repos')]
    public function listRepos(
        #[Path] string $login,
        #[Query] string $type = 'all',
        #[Query] int $per_page = 30,
    ): array;

    #[Post('/user/repos')]
    public function createRepo(
        #[Body] CreateRepoRequest $req,
        #[Header('Authorization')] string $token,
    ): Repo;

    #[Delete('/repos/{owner}/{repo}')]
    public function deleteRepo(
        #[Path] string $owner,
        #[Path] string $repo,
    ): void;
}

$gh   = Http::fromInterface(GitHubApi::class);
$user = Aol::scope(fn() => $gh->getUser('sattorbek'));
```

Attribute index
---------------

[](#attribute-index)

AttributeTargetWhat it does`#[Async]`methodReturns `Pending` instead of blocking; scheduled inside scope`#[Timeout(seconds)]`methodCancels and throws `AolTimeoutException` after N seconds`#[Retry(times:, on:, backoff:, delay:, maxDelay:)]`methodRetries on exception with fixed / linear / exponential backoff`#[Worker(pool:, queue:)]`classAnimates class as a pool of N instances`#[Restart(max:, within:)]`classRestarts crashed instances (one-for-one)`#[OnAwake]`methodCalled once per instance at `Aol::wrap()` time`#[OnSleep]`methodCalled once per instance when scope closes`#[OnSignal(SIG*)]`methodCalled when a UNIX signal arrives`#[OnTick(every:)]`methodCalled every N seconds`#[OnFileChange(path)]`methodCalled when a watched path changes`#[BaseUrl]`, `#[Headers]`interfaceHTTP client base URL and default headers`#[Get]`, `#[Post]`, `#[Put]`, `#[Patch]`, `#[Delete]`methodHTTP verb + path template`#[Path]`, `#[Query]`, `#[Body]`, `#[Header]`parameterHTTP request parameter binding`#[Process(command)]`classSpawns a child process at wrap time; `restart: true` respawns on exit`#[OnStdout]`, `#[OnStderr]`methodCalled per line of child process output`#[OnExit]`methodCalled when the child process exits`#[SseStream]`method (HTTP interface)Method returns an `iterable` instead of decoded JSON`#[OnSse(url)]`method (wrapped class)Subscribes the method to an SSE stream (repeatable)`#[WebSocket(url)]`classAnimates class as a WebSocket client (one connection per pool instance)`#[WsConnection]`propertyWrapper hydrates the property with the live `Connection` before `#[OnOpen]``#[OnOpen]`, `#[OnMessage]`, `#[OnClose]`methodWebSocket lifecycle hooksFull reference: `.claude/skills/php-aol/attributes-reference.md`

Module map
----------

[](#module-map)

NamespaceWhat it does`Aol\Aol`Entry points: `wrap()`, `scope()`, `async()`, `asyncBackground()``Aol\Pending`In-flight value proxy with magic chaining`Aol\Http`Declarative HTTP client + static facade (incl. Server-Sent Events)`Aol\WebSocket`WebSocket client (imperative + declarative)`Aol\File`Async filesystem (read/write/stream/walk/watch/lock/temp)`Aol\Stream`TCP/UDP/Unix/TLS sockets + framing`Aol\Process`Child processes (one-shot + spawn + declarative `#[Process]`)`Aol\Time`Async sleep / deadline / interval`Aol\Sync`Async-aware Mutex, Semaphore, Barrier, WaitGroup`Aol\Queue`In-memory Queue and Topic (pub/sub)`Aol\Test``FakeClock`, `runScope`PHPStan extension
-----------------

[](#phpstan-extension)

The library ships a PHPStan extension at `ext/phpstan/`. If you have `phpstan/extension-installer` installed, it loads automatically. Otherwise, add this to your `phpstan.neon`:

```
includes:
    - vendor/php-aol/php-aol/ext/phpstan/extension.neon
```

Runnable examples
-----------------

[](#runnable-examples)

The `examples/` directory has self-contained demos you can run directly:

ExampleWhat it shows`examples/daemon.php`Long-running daemon with `#[OnTick]` and `#[OnSignal]``examples/process.php`Declarative `#[Process]` + `#[OnStdout]`/`#[OnExit]``examples/http-parallel.php`5 HTTP requests in parallel — typically 5× faster than sequential`examples/http-declarative.php`Retrofit-style HTTP client from a plain PHP interface`examples/sse-imperative.php``Http::sse()` consuming a Server-Sent Events feed`examples/sse-declarative.php``#[OnSse]` on a wrapped class — handler per event`examples/websocket-chat.php`WebSocket echo round-trip (imperative + declarative)Run with `php examples/.php`. The HTTP demos hit public APIs (jsonplaceholder, GitHub) and need network access.

Development
-----------

[](#development)

```
composer install
composer test      # PHPUnit
composer phpstan   # PHPStan level 9
composer check     # both
```

Status
------

[](#status)

v0.2.0. Server-Sent Events and WebSocket shipped on top of v0.1.0's core (Animate model + auto-graph scopes + HTTP/File/Stream/Process facades).

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance89

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

54d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/285760884?v=4)[dot12x](/maintainers/dot12x)[@dot12x](https://github.com/dot12x)

---

Top Contributors

[![dot12x](https://avatars.githubusercontent.com/u/285760884?v=4)](https://github.com/dot12x "dot12x (1 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/php-aol-php-aol/health.svg)

```
[![Health](https://phpackages.com/badges/php-aol-php-aol/health.svg)](https://phpackages.com/packages/php-aol-php-aol)
```

###  Alternatives

[danog/madelineproto

Async PHP client API for the telegram MTProto protocol.

3.5k902.0k24](/packages/danog-madelineproto)[symfony/symfony

The Symfony PHP framework

31.4k87.2M2.2k](/packages/symfony-symfony)[drupal/core-recommended

Locked core dependencies; require this project INSTEAD OF drupal/core.

6942.5M425](/packages/drupal-core-recommended)[ecotone/ecotone

Enterprise architecture layer for Laravel and Symfony — CQRS, Event Sourcing, Durable Workflows (Sagas, Orchestrators), Projections, and Outbox messaging via PHP attributes.

564576.7k54](/packages/ecotone-ecotone)[tempest/framework

The PHP framework that gets out of your way.

2.2k34.4k16](/packages/tempest-framework)[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

751291.4k46](/packages/civicrm-civicrm-core)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
