PHPackages                             modstore/async - 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. [Queues &amp; Workers](/categories/queues)
4. /
5. modstore/async

ActiveLibrary[Queues &amp; Workers](/categories/queues)

modstore/async
==============

Forked from spatie/async

1.0.2(7y ago)09MITPHPPHP ^7.1

Since Dec 14Pushed 6y agoCompare

[ Source](https://github.com/modstore/async)[ Packagist](https://packagist.org/packages/modstore/async)[ Docs](https://github.com/spatie/async)[ RSS](/packages/modstore-async/feed)WikiDiscussions master Synced 4d ago

READMEChangelogDependencies (5)Versions (8)Used By (0)

Asynchronous and parallel PHP
=============================

[](#asynchronous-and-parallel-php)

[![Latest Version on Packagist](https://camo.githubusercontent.com/d5d3cf7f9b1f9c5765a2d3fac930cc41522be479320422cedaadf4578cb705a4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7370617469652f6173796e632e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/async)[![Build Status](https://camo.githubusercontent.com/21572e11da719123d3016e41d6a6c936f4fccdd094dee4bace5f5ed9cb265666/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f7370617469652f6173796e632f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.org/spatie/async)[![Quality Score](https://camo.githubusercontent.com/b88782b65303e4cebf7119a1890b895ced36e45fa63e5f61aaee5b7fa4fab30e/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f672f7370617469652f6173796e632e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/spatie/async)[![StyleCI](https://camo.githubusercontent.com/4c0d98beef1fbd36307b0c94dafc8d77cc057c799076039a8f829396329a5e43/68747470733a2f2f7374796c6563692e696f2f7265706f732f3131343232383730302f736869656c643f6272616e63683d6d6173746572)](https://styleci.io/repos/114228700)[![Total Downloads](https://camo.githubusercontent.com/82927eaa459f1b7f811dc7a070611a5996916302a2460362113d33494f594e3c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7370617469652f6173796e632e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/async)

This library provides a small and easy wrapper around PHP's PCNTL extension. It allows running of different processes in parallel, with an easy-to-use API.

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require spatie/async
```

Usage
-----

[](#usage)

```
use Spatie\Async\Pool;

$pool = Pool::create();

foreach ($things as $thing) {
    $pool->add(function () use ($thing) {
        // Do a thing
    })->then(function ($output) {
        // Handle success
    })->catch(function (Throwable $exception) {
        // Handle exception
    });
}

$pool->wait();
```

### Event listeners

[](#event-listeners)

When creating asynchronous processes, you'll get an instance of `ParallelProcess` returned. You can add the following event hooks on a process.

```
$pool
    ->add(function () {
        // ...
    })
    ->then(function ($output) {
        // On success, `$output` is returned by the process or callable you passed to the queue.
    })
    ->catch(function ($exception) {
        // When an exception is thrown from within a process, it's caught and passed here.
    })
    ->timeout(function () {
        // A process took too long to finish.
    })
;
```

### Functional API

[](#functional-api)

Instead of using methods on the `$pool` object, you may also use the `async` and `await` helper functions.

```
use Spatie\Async\Process;

$pool = Pool::create();

foreach (range(1, 5) as $i) {
    $pool[] = async(function () {
        usleep(random_int(10, 1000));

        return 2;
    })->then(function (int $output) {
        $this->counter += $output;
    });
}

await($pool);
```

### Error handling

[](#error-handling)

If an `Exception` or `Error` is thrown from within a child process, it can be caught per process by specifying a callback in the `->catch()` method.

```
$pool
    ->add(function () {
        // ...
    })
    ->catch(function ($exception) {
        // Handle the thrown exception for this child process.
    })
;
```

If there's no error handler added, the error will be thrown in the parent process when calling `await()` or `$pool->wait()`.

If the child process would unexpectedly stop without throwing an `Throwable`, the output written to `stderr` will be wrapped and thrown as `Spatie\Async\ParallelError` in the parent process.

### Catching exceptions by type

[](#catching-exceptions-by-type)

By type hinting the `catch` functions, you can provide multiple error handlers, each for individual types of errors.

```
$pool
    ->add(function () {
        throw new MyException('test');
    })
    ->catch(function (MyException $e) {
        // Handle `MyException`
    })
    ->catch(function (OtherException $e) {
        // Handle `OtherException`
    });
```

Note that as soon as an exception is handled, it won't trigger any other handlers

```
$pool
    ->add(function () {
        throw new MyException('test');
    })
    ->catch(function (MyException $e) {
        // This one is triggerd when `MyException` is thrown
    })
    ->catch(function (Exception $e) {
        // This one is not triggerd, even though `MyException` extends `Exception`
    });
```

### Working with tasks

[](#working-with-tasks)

Besides using closures, you can also work with a `Task`. A `Task` is useful in situations where you need more setup work in the child process. Because a child process is always bootstrapped from nothing, chances are you'll want to initialise eg. the dependency container before executing the task. The `Task` class makes this easier to do.

```
use Spatie\Async\Task;

class MyTask extends Task
{
    public function configure()
    {
        // Setup eg. dependency container, load config,...
    }

    public function run()
    {
        // Do the real work here.
    }
}

// Add the task to the pool
$pool->add(new MyTask());
```

#### Simple tasks

[](#simple-tasks)

If you want to encapsulate the logic of your task, but don't want to create a full blown `Task` object, you may also pass an invokable object to the `Pool`.

```
class InvokableClass
{
    // ...

    public function __invoke()
    {
        // ...
    }
}

$pool->add(new InvokableClass(/* ... */));
```

### Pool configuration

[](#pool-configuration)

You're free to create as many pools as you want, each pool has its own queue of processes it will handle.

A pool is configurable by the developer:

```
use Spatie\Async\Pool;

$pool = Pool::create()

// The maximum amount of processes which can run simultaneously.
    ->concurrency(20)

// The maximum amount of time a process may take to finish in seconds.
    ->timeout(15)

// Configure which autoloader sub processes should use.
    ->autoload(__DIR__ . '/../../vendor/autoload.php')

// Configure how long the loop should sleep before re-checking the process statuses in milliseconds.
    ->sleepTime(50000)
;
```

### Synchronous fallback

[](#synchronous-fallback)

If the required extensions (`pcntl` and `posix`) are not installed in your current PHP runtime, the `Pool` will automatically fallback to synchronous execution of tasks.

The `Pool` class has a static method `isSupported` you can call to check whether your platform is able to run asynchronous processes.

If you're using a `Task` to run processes, only the `run` method of those tasks will be called when running in synchronous mode.

Behind the curtains
-------------------

[](#behind-the-curtains)

When using this package, you're probably wondering what's happening underneath the surface.

We're using the `symfony/process` component to create and manage child processes in PHP. By creating child processes on the fly, we're able to execute PHP scripts in parallel. This parallelism can improve performance significantly when dealing with multiple synchronous tasks, which don't really need to wait for each other. By giving these tasks a separate process to run on, the underlying operating system can take care of running them in parallel.

There's a caveat when dynamically spawning processes: you need to make sure that there won't be too many processes at once, or the application might crash. The `Pool` class provided by this package takes care of handling as many processes as you want by scheduling and running them when it's possible.

That's the part that `async()` or `$pool->add()` does. Now let's look at what `await()` or `$pool->wait()` does.

When multiple processes are spawned, each can have a separate time to completion. One process might eg. have to wait for a HTTP call, while the other has to process large amounts of data. Sometimes you also have points in your code which have to wait until the result of a process is returned.

This is why we have to wait at a certain point in time: for all processes on a pool to finish, so we can be sure it's safe to continue without accidentally killing the child processes which aren't done yet.

Waiting for all processes is done by using a `while` loop, which will wait until all processes are finished. Determining when a process is finished is done by using a listener on the `SIGCHLD` signal. This signal is emitted when a child process is finished by the OS kernel. As of PHP 7.1, there's much better support for listening and handling signals, making this approach more performant than eg. using process forks or sockets for communication. You can read more about it [here](https://wiki.php.net/rfc/async_signals).

When a process is finished, its success event is triggered, which you can hook into with the `->then()` function. Likewise, when a process fails or times out, the loop will update that process' status and move on. When all processes are finished, the while loop will see that there's nothing more to wait for, and stop. This is the moment your parent process can continue to execute.

### Comparison to other libraries

[](#comparison-to-other-libraries)

We've written a blog post containing more information about use cases for this package, as well as making comparisons to other asynchronous PHP libraries like ReactPHP and Amp: .

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

### Security

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Postcardware
------------

[](#postcardware)

You're free to use this package, but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using.

Our address is: Spatie, Samberstraat 69D, 2060 Antwerp, Belgium.

We publish all received postcards [on our company website](https://spatie.be/en/opensource/postcards).

Credits
-------

[](#credits)

- [Brent Roose](https://github.com/brendt)
- [All Contributors](../../contributors)

Support us
----------

[](#support-us)

Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects [on our website](https://spatie.be/opensource).

Does your business depend on our contributions? Reach out and support us on [Patreon](https://www.patreon.com/spatie). All pledges will be dedicated to allocating workforce on maintenance and new awesome stuff.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

27

—

LowBetter than 49% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity4

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity63

Established project with proven stability

 Bus Factor1

Top contributor holds 82% 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

Every ~86 days

Recently: every ~118 days

Total

7

Last Release

2556d ago

Major Versions

0.0.4 → 1.0.02019-03-22

### Community

Maintainers

![](https://www.gravatar.com/avatar/6cf970f6fb0f66aed0a1ef7ad2f5f964c8bae2b5ac239f35c6a0c8c4591bbc8d?d=identicon)[modstore](/maintainers/modstore)

---

Top Contributors

[![brendt](https://avatars.githubusercontent.com/u/6905297?v=4)](https://github.com/brendt "brendt (141 commits)")[![freekmurze](https://avatars.githubusercontent.com/u/483853?v=4)](https://github.com/freekmurze "freekmurze (20 commits)")[![modstore](https://avatars.githubusercontent.com/u/7380420?v=4)](https://github.com/modstore "modstore (2 commits)")[![vuongxuongminh](https://avatars.githubusercontent.com/u/38932626?v=4)](https://github.com/vuongxuongminh "vuongxuongminh (2 commits)")[![Kanti](https://avatars.githubusercontent.com/u/471387?v=4)](https://github.com/Kanti "Kanti (1 commits)")[![mintunitish](https://avatars.githubusercontent.com/u/12434080?v=4)](https://github.com/mintunitish "mintunitish (1 commits)")[![svenluijten](https://avatars.githubusercontent.com/u/11269635?v=4)](https://github.com/svenluijten "svenluijten (1 commits)")[![jeromegamez](https://avatars.githubusercontent.com/u/67554?v=4)](https://github.com/jeromegamez "jeromegamez (1 commits)")[![carusogabriel](https://avatars.githubusercontent.com/u/16328050?v=4)](https://github.com/carusogabriel "carusogabriel (1 commits)")[![Gummibeer](https://avatars.githubusercontent.com/u/6187884?v=4)](https://github.com/Gummibeer "Gummibeer (1 commits)")[![assertchris](https://avatars.githubusercontent.com/u/200609?v=4)](https://github.com/assertchris "assertchris (1 commits)")

---

Tags

asyncspatie

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[spatie/async

Asynchronous and parallel PHP with the PCNTL extension

2.8k4.5M37](/packages/spatie-async)[jolicode/castor

A lightweight and modern task runner. Automate everything. In PHP.

53541.0k3](/packages/jolicode-castor)[badfarm/zanzara

Asynchronous PHP Telegram Bot Framework

2042.5k](/packages/badfarm-zanzara)[orisai/scheduler

Cron job scheduler - with locks, parallelism and more

4037.1k4](/packages/orisai-scheduler)[ufo-tech/json-rpc-bundle

The bundle for easy using json-rpc api on your project

224.6k3](/packages/ufo-tech-json-rpc-bundle)[fghazaleh/multi-thread-manager

Multi-thread manager using Symfony process component

172.6k](/packages/fghazaleh-multi-thread-manager)

PHPackages © 2026

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