PHPackages                             bagart/async-kernel - 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. bagart/async-kernel

ActiveLibrary

bagart/async-kernel
===================

Async kernel for PHP — Fibers, Promises, cooperative scheduling

00

Since Jul 21Compare

[ Source](https://github.com/bagart/php-async-kernel-lib)[ Packagist](https://packagist.org/packages/bagart/async-kernel)[ RSS](/packages/bagart-async-kernel/feed)WikiDiscussions Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

Async Kernel
============

[](#async-kernel)

A lightweight async runtime for PHP 8.1+ built on Fibers and Promises.

Overview
--------

[](#overview)

Async Kernel provides a single-threaded event loop that coordinates concurrent tasks using PHP Fibers, Guzzle promises, and a cooperative scheduling model. It is designed for long-running daemons that need to perform non-blocking I/O (HTTP requests, polling, scheduled tasks) without external dependencies like ReactPHP or Amp.

Architecture
------------

[](#architecture)

```
AsyncKernel
├── Drivers (AsyncTickableContract)    — drive async I/O (Guzzle queue, curl_multi)
├── Daemons (DaemonContract)           — long-running tasks polled each tick
│   └── FiberScheduler (SchedulerContract) — Fiber-based cooperative scheduler
└── Promises (PromiseContract)         — resolve/reject with then/otherwise chains

```

### Core Components

[](#core-components)

ClassPurpose`AsyncKernel`Main event loop — ticks drivers then daemons, manages idle/busy sleep`ASKPromise` / `ASKDeferred`Promise/A+ style primitives with `then`, `otherwise`, `wait`, `cancel``ASKPromiseResolver`Awaits a promise from within a Fiber or blocking context`ASKFiberScheduler`Enqueues and schedules Fibers with `sleep(delay)` support`GuzzlePromiseAdapter`Wraps `GuzzleHttp\Promise\PromiseInterface` into `ASKPromiseContract``GuzzleTickableDriver`Ticks `GuzzleHttp\Promise\Utils::queue()` each cycle`CurlMultiClient`Ticks a `CurlMultiHandler` each cycleRequirements
------------

[](#requirements)

- PHP 8.1+
- `guzzlehttp/guzzle` (for Guzzle drivers/adapters)

Quick Start
-----------

[](#quick-start)

```
use BAGArt\AsyncKernel\AsyncKernel;use BAGArt\AsyncKernel\Network\Drivers\GuzzleTickableDriver;use BAGArt\AsyncKernel\Promise\GuzzlePromiseAdapter;use BAGArt\AsyncKernel\Promise\ASKPromiseResolver;use GuzzleHttp\Client;use Monolog\Handler\StreamHandler;use Monolog\Logger;

$logger = new Logger('app');
$logger->pushHandler(new StreamHandler('php://stderr', Logger::INFO));

$kernel = new AsyncKernel($logger);
$kernel->addTickable(new GuzzleTickableDriver());

$client = new Client(['timeout' => 10]);
$resolver = new ASKPromiseResolver($kernel);

$promise = GuzzlePromiseAdapter::wrap(
    $client->requestAsync('GET', 'https://example.com/api')
);

$result = $resolver->await($promise);
```

Creating a Daemon
-----------------

[](#creating-a-daemon)

Implement `ASKDaemonContract` to define a long-running task:

```
use BAGArt\AsyncKernel\Contracts\Daemons\ASKDaemonContract;use BAGArt\AsyncKernel\Contracts\ASKPromiseContract;

final class MyDaemon implements ASKDaemonContract
{
    private ?ASKPromiseContract $pending = null;
    private int $nextRunAfter = 0;

    public function startup(): void
    {
    }

    public function onError(\Throwable $e): void
    {
    }

    public function name(): string
    {
        return substr(strrchr(static::class, '\\'), 1);
    }

    public function tick(): void
    {
        if ($this->pending !== null) {
            // process previous result
            if ($this->pending->getState() === ASKPromiseContract::FULFILLED) {
                $data = $this->pending->getValue();
                // ...
            }
            $this->pending = null;
            $this->nextRunAfter = time() + 30;
            return;
        }

        if (time() < $this->nextRunAfter) {
            return;
        }

        // start new async work
        $this->pending = $this->fetchData();
    }

    public function shutdown(): bool
    {
        return $this->pending === null;
    }

    public function isIdle(): bool
    {
        return $this->pending === null;
    }

    public function queueSize(): int
    {
        return $this->pending !== null ? 1 : 0;
    }
}
```

Register it with the kernel:

```
$kernel->addDaemon(new MyDaemon());
$kernel->run();
```

Fiber Scheduler
---------------

[](#fiber-scheduler)

Use `ASKFiberScheduler` to run concurrent Fiber-based tasks:

```
use BAGArt\AsyncKernel\Drivers\ASKFiberScheduler;

$scheduler = new ASKFiberScheduler();

$scheduler->enqueue(function (): void {
    echo "Task 1 started\n";
    Fiber::suspend(); // yield
    echo "Task 1 resumed\n";
});

$scheduler->enqueue(function (): void {
    echo "Task 2 started\n";
});

$kernel->addDaemon($scheduler);
$kernel->run();
```

### Delayed Execution

[](#delayed-execution)

```
$scheduler->sleep(function (): void {
    echo "Delayed task\n";
}, seconds: 5);
```

Promise States
--------------

[](#promise-states)

```
PENDING  →  FULFILLED (resolve)
       ↘  REJECTED  (reject)
       ↘  cancelled (cancel)

```

- `then($onFulfilled, $onRejected)` — chain handlers
- `otherwise($onRejected)` — catch rejection
- `wait($unwrap)` — block until settled (requires a wait function or strategy)
- `cancel()` — mark as cancelled

PromiseResolver
---------------

[](#promiseresolver)

`PromiseResolver::await($promise, $timeout)` works in two modes:

1. **Inside a Fiber** — suspends the Fiber, resumes on resolve/reject
2. **Outside a Fiber** — spins `kernel->tick()` until settled

Configuration
-------------

[](#configuration)

```
use BAGArt\AsyncKernel\ASKClock;use BAGArt\AsyncKernel\Enum\ExceptionPolicy;use BAGArt\AsyncKernel\KernelSleepStrategy\AdaptiveKernelSleepStrategy;

$kernel = new AsyncKernel(
    logger: $kernelLogger,
    clock: new ASKClock(),
    sleepStrategy: new AdaptiveKernelSleepStrategy(
        idleMicroseconds: 1_000,   // sleep when queue empty
        busyMicroseconds: 0,       // sleep between busy ticks
    ),
    exceptionPolicy: ExceptionPolicy::INTERRUPT, // throw on daemon/driver exceptions
);
```

### Sleep Strategies

[](#sleep-strategies)

StrategyDescription`AdaptiveKernelSleepStrategy`Linearly increases idle sleep up to 1ms; configurable idle/busy microseconds`ExponentialBackoffSleepStrategy`Doubles idle sleep each tick (capped)`NoSleepStrategy`No sleep between ticks (busy-wait)### Exception Policies

[](#exception-policies)

PolicyBehavior`ExceptionPolicy::IGNORE`Log and continue`ExceptionPolicy::STOP_KERNEL`Gracefully stop the kernel`ExceptionPolicy::RESTART_DAEMON`Log and continue (future: restart daemon)`ExceptionPolicy::INTERRUPT`Rethrow the exception (default)Graceful Shutdown
-----------------

[](#graceful-shutdown)

`$kernel->shutdown()` calls `shutdown()` on each daemon in a loop until all return `true`. Daemons should flush pending work and return `true` when fully stopped.

`$kernel->stop($reason)` requests a stop after the current tick completes.

Examples
--------

[](#examples)

Run the example daemon (fetches USD→EUR rate every 10s):

```
php commands/example-daemon.php
php commands/example-daemon.php --interval=5
```

Directory Structure
-------------------

[](#directory-structure)

```
src/
├── Contracts/
│   ├── AsyncKernelContract.php      — tick/run interface
│   ├── AsyncTickableContract.php    — tick/isIdle/queueSize
│   ├── DaemonContract.php           — daemon with shutdown
│   ├── PromiseContract.php          — promise states & chaining
│   └── SchedulerContract.php        — fiber scheduler interface
├── Exceptions/
│   └── AsyncKernelException.php
├── Runtime/
│   ├── ClientParts/
│   │   ├── AsyncSocketKernel.php
│   │   ├── CurlMultiDriver.php
│   │   ├── GuzzleDriver.php
│   │   ├── GuzzlePromiseAdapter.php
│   │   └── OutboundRequest.php
│   ├── AsyncKernel.php
│   ├── Deferred.php
│   ├── FiberScheduler.php
│   ├── Promise.php
│   ├── PromiseFactory.php
│   └── PromiseResolver.php

```

###  Health Score

9

—

LowBetter than 0% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity0

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/02a582356aa07935e42e622817f56810dce45be995af444215fabb072a39992b?d=identicon)[bagart](/maintainers/bagart)

### Embed Badge

![Health badge](/badges/bagart-async-kernel/health.svg)

```
[![Health](https://phpackages.com/badges/bagart-async-kernel/health.svg)](https://phpackages.com/packages/bagart-async-kernel)
```

PHPackages © 2026

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