Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Async Laravel Package

spatie/async

Run PHP tasks in parallel with a simple Pool API built on PCNTL. Add closures, handle results via then/catch, and wait for completion. Ideal for speeding up batch jobs, CPU-heavy work, and IO-bound processing with multiple processes.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/async
    

    Ensure your server has pcntl extension enabled (check php -m | grep pcntl).

  2. First Use Case: Run a simple parallel task:

    use Spatie\Async\Async;
    
    Async::run(function () {
        // Long-running task (e.g., processing a large file)
        file_put_contents('output.txt', 'Hello from async!');
    });
    
    • Output: The task executes in a separate process without blocking the main script.
  3. Where to Look First:

    • README for core concepts.
    • Async::run() and Async::parallel() methods in the API docs.
    • config/async.php for customization (e.g., process limits, timeouts).

Implementation Patterns

Core Workflows

  1. Basic Parallel Execution:

    Async::parallel([
        fn() => processUserData($users[0]),
        fn() => processUserData($users[1]),
        fn() => processUserData($users[2]),
    ]);
    
    • Use Case: Speed up batch operations (e.g., image resizing, API calls).
  2. Chaining Async Tasks:

    $result = Async::run(function () {
        $data = fetchRemoteData();
        return Async::run(fn() => transformData($data));
    })->wait();
    
    • Use Case: Sequential async steps (e.g., fetch → process → store).
  3. Error Handling:

    Async::run(function () {
        try {
            riskyOperation();
        } catch (\Throwable $e) {
            reportError($e);
        }
    })->catch(fn($e) => logger()->error($e->getMessage()));
    
    • Tip: Use wait() or catch() to handle failures gracefully.
  4. Integration with Laravel Jobs:

    Async::run(function () {
        dispatch(new ProcessLargeFileJob($file));
    });
    
    • Use Case: Offload Laravel jobs to parallel processes.

Advanced Patterns

  • Process Limits:

    config(['async.max_processes' => 4]); // Limit concurrent processes.
    
    • Use Case: Prevent server overload.
  • Timeouts:

    Async::run(fn() => slowTask(), timeout: 30)->wait();
    
    • Use Case: Abort hanging tasks (e.g., API timeouts).
  • Shared Memory:

    Async::run(function () {
        $shared = new \Spatie\Async\SharedMemory\SharedMemory('key');
        $shared->set('value');
    });
    
    • Use Case: Inter-process communication (e.g., counters, flags).

Gotchas and Tips

Pitfalls

  1. PCNTL Dependency:

    • Issue: pcntl is not enabled by default on shared hosting (e.g., Heroku, shared Linux).
    • Fix: Use Async::fallback() for non-pcntl environments:
      Async::fallback(function () {
          // Fallback to synchronous execution.
      });
      
  2. Memory Leaks:

    • Issue: Long-running processes may consume excessive memory.
    • Fix: Use Async::run(fn() => ..., memory_limit: '128M') to enforce limits.
  3. Race Conditions:

    • Issue: Shared resources (e.g., files, DB) can cause conflicts.
    • Fix: Use locks or SharedMemory for synchronization.
  4. Debugging:

    • Tip: Log process IDs (getmypid()) to track async tasks:
      Async::run(function () {
          logger()->info("Running PID: " . getmypid());
      });
      

Tips

  • Laravel Artisan Commands:

    Async::run(function () {
        Artisan::call('queue:work');
    });
    
    • Use Case: Run queue workers in parallel.
  • Dynamic Process Count:

    $processes = ceil(count($items) / config('async.max_processes'));
    Async::parallel(array_chunk($items, $processes), fn($chunk) => processChunk($chunk));
    
  • Extension Points:

    • Override Spatie\Async\Async to add custom logging or metrics.
    • Extend SharedMemory for complex IPC (e.g., Redis-backed shared state).
  • Testing:

    • Mock Async in tests using Async::shouldReceive('run')->once().
    • Test timeouts with Async::run(fn() => sleep(10), timeout: 1) to verify failure paths.
  • Performance:

    • Benchmark: Compare Async::parallel() vs. Laravel’s dispatchSync() for CPU-bound tasks.
    • Tradeoff: Async adds overhead (~500ms per process); use for tasks >1s.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4
php-http/client-implementation
phpcr/phpcr-implementation
cucumber/gherkin-monorepo
haydenpierce/class-finder
psr/simple-cache-implementation