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

Engine Laravel Package

hyperf/engine

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require hyperf/engine
    

    Ensure your project uses PHP 8.0+ and Swoole 4.5+ (or later, as per compatibility notes).

  2. First Use Case: Launch a coroutine task in a Laravel command or route handler:

    use Hyperf\Engine\Coroutine;
    
    Coroutine::create(function () {
        // Non-blocking I/O operations (e.g., HTTP requests, DB queries)
        $response = file_get_contents('https://api.example.com/data');
        return $response;
    });
    
  3. Key Entry Points:

    • Coroutine::create(): Spawn a new coroutine.
    • Coroutine::run(): Run a coroutine immediately (blocks current thread).
    • Coroutine::sleep(): Non-blocking sleep (microseconds).
    • Coroutine::yield(): Pause/resume coroutines manually.
  4. Where to Look First:


Implementation Patterns

Core Workflows

  1. Non-Blocking HTTP Requests:

    Coroutine::create(function () {
        $client = new \GuzzleHttp\Client();
        $response = $client->request('GET', 'https://api.example.com');
        // Process response...
    });
    
    • Use Guzzle with Swoole’s coroutine client or curl_multi for async I/O.
  2. Database Queries:

    Coroutine::create(function () {
        $results = DB::select('SELECT * FROM large_table');
        // Process results...
    });
    
    • Pair with doctrine/dbal or illuminate/database (ensure PDO drivers support coroutines).
  3. Event Loop Integration:

    Coroutine::run(function () {
        while (true) {
            $data = Coroutine::yield(); // Pause until data is available
            // Handle $data...
        }
    });
    
  4. Worker Pooling:

    $tasks = [];
    foreach ($items as $item) {
        $tasks[] = Coroutine::create(function () use ($item) {
            return processItem($item);
        });
    }
    Coroutine::all($tasks); // Wait for all to complete
    

Laravel-Specific Patterns

  1. Middleware for Async Processing:

    public function handle($request, Closure $next) {
        Coroutine::create(function () use ($request) {
            $response = $next($request);
            // Async post-processing...
        });
        return $next($request); // Sync path
    }
    
  2. Queue Workers:

    // In a Laravel command
    Coroutine::create(function () {
        while ($job = $this->queue->pop()) {
            $job->handle();
        }
    });
    
  3. Real-Time Features:

    • Use with laravel-websockets or pusher-php-server for WebSocket coroutines:
      Coroutine::create(function () {
          $socket = new \Swoole\WebSocket\Server(...);
          while (true) {
              $socket->recv(); // Non-blocking
          }
      });
      

Integration Tips

  • Avoid Blocking Calls: Never use sleep(), file_get_contents() (sync), or synchronous DB calls inside coroutines.
  • Error Handling: Wrap coroutines in try-catch:
    try {
        Coroutine::create(fn() => riskyOperation());
    } catch (\Throwable $e) {
        Coroutine::sleep(1000); // Backoff
    }
    
  • Dependency Injection: Use Laravel’s container to resolve coroutine-aware services:
    $service = app()->make(CoroutineService::class);
    Coroutine::create(fn() => $service->execute());
    

Gotchas and Tips

Pitfalls

  1. Global State Corruption:

    • Coroutines share memory. Avoid static variables or global state that can cause race conditions.
    • Fix: Use dependency injection or coroutine-local storage (e.g., Coroutine::getContext()).
  2. Blocking the Event Loop:

    • Synchronous operations (e.g., str_replace with large strings) can stall coroutines.
    • Fix: Offload heavy work to workers or use Coroutine::yield() to release the event loop.
  3. Resource Leaks:

    • Unclosed database connections, sockets, or file handles in coroutines can exhaust resources.
    • Fix: Use finally blocks or context managers:
      Coroutine::create(function () {
          $db = DB::connection();
          try {
              $db->select(...);
          } finally {
              $db->disconnect();
          }
      });
      
  4. Laravel’s Sync Defaults:

    • Laravel’s DB, Cache, and Queue are synchronous by default. Use coroutine-compatible alternatives:
      • DB: doctrine/dbal with PDO_SQLSRV or hyperf/db-connection.
      • Cache: swoole/cache or predis/predis (Redis).
      • Queue: hyperf/queue or spatie/laravel-async.
  5. Timeouts:

    • Coroutines don’t have built-in timeouts. Use Coroutine::sleep() or Swoole\Timer:
      $timer = Coroutine::create(function () {
          Coroutine::sleep(5000); // 5s timeout
          throw new \RuntimeException("Operation timed out");
      });
      

Debugging

  1. Stack Traces:

    • Coroutine stack traces are less intuitive. Use Coroutine::getContext() to inspect state:
      error_log(Coroutine::getContext());
      
    • Enable Swoole’s trace mode:
      \Swoole\Coroutine::set(['trace_enable' => true]);
      
  2. Logging:

    • Coroutines may log out of order. Use structured logging (e.g., Monolog with coroutine IDs):
      \Log::debug('Coroutine ID: ' . Coroutine::id(), ['data' => $data]);
      
  3. Common Errors:

    • "Coroutine not found": Ensure go() or Coroutine::create() is used (not raw Swoole\Coroutine).
    • Segmentation faults: Likely due to mixing sync/async code. Isolate coroutines to async-only paths.

Configuration Quirks

  1. Swoole Version Mismatches:

    • hyperf/engine requires Swoole 4.5+. Check compatibility in composer.json:
      "require": {
          "ext-swoole": "^4.5 || ^5.0"
      }
      
    • For Swoole 6.0+, use hyperf/engine v2.12.1+.
  2. PHP Extensions:

    • Disable opcache.jit_buffer if coroutines behave erratically (JIT can interfere with coroutine context).
  3. Laravel Service Providers:

    • Register coroutine-aware bindings in AppServiceProvider:
      $this->app->bind(CoroutineService::class, function () {
          return new CoroutineService(\Swoole\Coroutine::getuid());
      });
      

Extension Points

  1. Custom Coroutine Classes:

    class AsyncTask extends \Hyperf\Engine\Coroutine
    {
        public function __construct() {
            parent::__construct();
            $this->set(['hook_flags' => SWOOLE_HOOK_ALL]);
        }
    }
    
  2. Hooks for Low-Level Control:

    • Use Swoole hooks to intercept coroutine events:
      \Swoole\Coroutine::addHook(SWOOLE_HOOK_ALL, function ($hookType) {
          \Log::debug("Coroutine hook triggered: {$hookType}");
      });
      
  3. Integration with Hyperf:

    • If migrating from Hyperf, leverage hyperf/engine directly for shared coroutine logic:
      use Hyperf\Engine\Coroutine as EngineCoroutine;
      // Replace Laravel's async calls with EngineCoroutine.
      
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