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

Coroutine Laravel Package

workerman/coroutine

Workerman coroutine library providing lightweight concurrency tools for PHP: Coroutine, Channel, Barrier, Parallel, and Pool. Designed to simplify async workflows and coordinated task execution in Workerman-based applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require workerman/coroutine
    

    Requires workerman/workerman (≥5.1) and PHP 8.1+ (PHP 8.4+ recommended for full compatibility).

  2. First Use Case: Replace a blocking HTTP request with a coroutine:

    use Workerman\Coroutine;
    
    Coroutine::create(function () {
        $client = new \Workerman\Coroutine\Http\Request();
        $response = $client->get('https://api.example.com/data');
        $data = json_decode($response, true);
        // Process $data asynchronously
    });
    
  3. Where to Look First:

    • Core Classes: Coroutine, Channel, Pool, Parallel.
    • Key Methods:
      • Coroutine::create(): Spawn a coroutine.
      • Channel::push()/pop(): Blocking-safe message passing.
      • Pool::get()/release(): Connection pooling.
    • Example: Tests directory for practical patterns.

Implementation Patterns

1. Coroutine Workflows

  • Fire-and-Forget:
    Coroutine::create(function () {
        // Async task (e.g., WebSocket handler, background job)
        $result = processData();
        logResult($result);
    });
    
  • Synchronous Execution:
    Coroutine::run(); // Blocks until all coroutines complete (use cautiously in Laravel).
    
  • Laravel Integration: Use coroutines in queues/jobs or artisan commands (avoid HTTP middleware):
    // In a Laravel job
    public function handle() {
        Coroutine::create([$this, 'process']);
    }
    
    private function process() {
        // Coroutine logic
    }
    

2. Channel-Based Communication

  • Producer/Consumer:
    $channel = new \Workerman\Coroutine\Channel(100);
    
    // Producer (e.g., API consumer)
    Coroutine::create(function () use ($channel) {
        $channel->push(fetchData());
    });
    
    // Consumer (e.g., database writer)
    Coroutine::create(function () use ($channel) {
        while (true) {
            $data = $channel->pop(); // Blocks until data is available
            saveToDatabase($data);
        }
    });
    
  • Check Availability:
    if ($channel->hasConsumers()) {
        $channel->push($data); // Safe to push
    }
    

3. Connection Pooling

  • Database Connections:
    $pool = new \Workerman\Coroutine\Pool(5, function () {
        return new \Workerman\Coroutine\Mysql\Connection('mysql:host=...');
    });
    
    Coroutine::create(function () use ($pool) {
        $conn = $pool->get(); // Acquires a connection
        $result = $conn->query('SELECT * FROM users');
        $pool->release($conn); // Releases back to pool
    });
    
  • HTTP Clients:
    $httpPool = new \Workerman\Coroutine\Pool(10, function () {
        return new \Workerman\Coroutine\Http\Request();
    });
    

4. Parallel Execution

  • Batch Processing:
    $parallel = new \Workerman\Coroutine\Parallel();
    $parallel->add(function () { /* Task 1 */ });
    $parallel->add(function () { /* Task 2 */ });
    $results = $parallel->wait(); // Array of results
    

5. Laravel-Specific Patterns

  • Async Queues: Replace Illuminate\Queue with a Pool-based worker:
    $jobPool = new \Workerman\Coroutine\Pool(20, function () {
        return new AsyncJobHandler();
    });
    
    Coroutine::create(function () use ($jobPool) {
        while (true) {
            $job = $jobPool->get()->handle();
            $jobPool->release($job);
        }
    });
    
  • WebSocket Servers: Use Workerman’s coroutine HTTP server (external to Laravel):
    // In a separate Workerman process
    $server = new \Workerman\Worker();
    $server->onWorkerStart = function () {
        \Workerman\Coroutine::runAll();
    };
    

Gotchas and Tips

Pitfalls

  1. Blocking the Event Loop:

    • Issue: Calling Coroutine::run() in Laravel’s HTTP middleware blocks the entire request pipeline.
    • Fix: Run coroutines outside HTTP requests (e.g., in queues, CLI, or dedicated workers).
  2. Memory Leaks:

    • Issue: Unbounded Channel/Pool sizes or leaked coroutines.
    • Fix:
      // Limit channel size
      $channel = new \Workerman\Coroutine\Channel(1000);
      
      // Close pools explicitly
      $pool->closeConnections();
      
  3. PHP 8.4+ Compatibility:

    • Issue: Deprecated object array usage in older versions.
    • Fix: Use v1.1.5+ and ensure workerman/workerman is updated.
  4. State Management:

    • Issue: Coroutines do not share Laravel’s request/session state.
    • Fix: Pass data explicitly or use shared storage (e.g., Redis).
  5. Debugging Complexity:

    • Issue: Non-deterministic execution makes debugging hard.
    • Fix:
      • Log coroutine IDs:
        Coroutine::create(function () {
            $id = Coroutine::getId();
            logger()->info("Coroutine $id started");
        });
        
      • Use Coroutine::get() to inspect active coroutines.

Debugging Tips

  • Inspect Active Coroutines:
    $coroutines = Coroutine::get();
    foreach ($coroutines as $id => $coroutine) {
        logger()->debug("Coroutine $id: " . $coroutine->getStatus());
    }
    
  • Timeout Handling:
    if (!Coroutine::wait(1.0, function () use ($channel) {
        return $channel->pop();
    })) {
        logger()->error("Timeout waiting for data");
    }
    
  • Error Handling:
    try {
        Coroutine::create(function () {
            try {
                // Risky operation
            } catch (\Throwable $e) {
                Coroutine::throwException($e); // Propagate to parent
            }
        });
    } catch (\Throwable $e) {
        logger()->error("Coroutine failed: " . $e->getMessage());
    }
    

Configuration Quirks

  1. Swoole vs. Workerman:

    • Swoole: Uses native coroutines (faster, but less portable).
    • Workerman: Abstracted layer (works with Swoole or event extension).
  2. Pool Sizing:

    • Rule of Thumb: Set Pool size to max concurrent connections (e.g., DB connections).
    • Dynamic Scaling: Use Pool::getConnectionCount() to monitor usage.
  3. Channel Backpressure:

    • Issue: Producers may overwhelm consumers.
    • Fix: Use Channel::hasConsumers() before pushing:
      if ($channel->hasConsumers()) {
          $channel->push($data);
      }
      

Extension Points

  1. Custom Coroutine Classes:
    class AsyncJob extends \Workerman\Coroutine\Coroutine {
        public function run() {
            // Override coroutine logic
        }
    }
    
  2. Channel Middleware:
    $channel = new \Workerman\Coroutine\Channel();
    $channel->onPush = function ($data) {
        // Pre-process data
        return $data;
    };
    
  3. Pool Initialization:
    $pool = new \Workerman\Coroutine\Pool(5, function () {
        return new CustomConnection();
    });
    

Laravel-Specific Gotchas

  1. Service Container:

    • Coroutines cannot use Laravel’s IoC directly. Manually instantiate dependencies:
      Coroutine::create(function () {
          $repo = new \App\Repositories\UserRepository(); // No `app()->make()`
      });
      
  2. Eloquent ORM:

    • Issue: Eloquent’s synchronous queries block coroutines.
    • Fix: Use async drivers (e.g., swoole-mysql) or raw PDO:
      $pdo = new \PDO('mysql:host=...', 'user', 'pass');
      $pdo->setAttribute(\PDO::ATTR_PERSISTENT, false);
      
  3. Middleware:

    • Issue: Coroutines bypass Laravel middleware.
    • Fix: Create async-compatible middleware:
      class AsyncAuthMiddleware
      
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor