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

Pokio Laravel Package

nunomaduro/pokio

Pokio is a simple async API for PHP: run closures concurrently via pcntl forks and await results. Uses FFI shared memory for fast parent/child communication. Built for internal tooling and performance work; not recommended for production use.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require nunomaduro/pokio
    

    Ensure your project uses PHP 8.3+ and has pcntl and ffi extensions enabled (though Pokio gracefully falls back to sequential execution if unavailable).

  2. First Use Case: Replace a blocking sleep() or sequential task with parallel execution:

    $promise1 = async(function () {
        // Simulate I/O-bound task (e.g., API call, DB query)
        sleep(2);
        return 'Task 1 result';
    });
    
    $promise2 = async(function () {
        sleep(1);
        return 'Task 2 result';
    });
    
    [$result1, $result2] = await([$promise1, $promise2]);
    // Outputs: ["Task 1 result", "Task 2 result"] in ~2 seconds (not 3)
    
  3. Key Entry Points:

    • async(Closure): Wrap a task to run asynchronously.
    • await(Promise|array): Block and resolve one or multiple promises.
    • Promise chaining: .then(), .catch(), .finally() for async workflows.
  4. Where to Look First:

    • README.md for syntax and examples.
    • Tests for edge cases (e.g., Xdebug compatibility, error handling).
    • Changelog for breaking changes (e.g., v1.0.1 Xdebug fix).

Implementation Patterns

Core Workflows

1. Parallelizing I/O-Bound Tasks

  • Pattern: Replace sequential foreach loops or sleep() delays with async/await.
  • Example: Parallelize API calls in a Laravel Artisan command:
    $urls = ['https://api.example.com/data1', 'https://api.example.com/data2'];
    $promises = array_map(fn ($url) => async(fn () => file_get_contents($url)), $urls);
    $results = await($promises);
    
  • Tip: Use array_map or collect()->map to batch tasks.

2. Error Handling

  • Pattern: Chain .catch() or use try/catch with await.
  • Example:
    $promise = async(fn () => 1/0)
        ->catch(fn (Throwable $e) => "Handled: {$e->getMessage()}");
    echo await($promise); // "Handled: Division by zero"
    
  • Tip: For multiple promises, use array_map + await with a loop to catch individual errors.

3. Chaining Promises

  • Pattern: Chain .then() for sequential async operations.
  • Example:
    $promise = async(fn () => fetchData())
        ->then(fn ($data) => processData($data))
        ->then(fn ($result) => saveToDB($result));
    await($promise);
    
  • Tip: Return promises from .then() closures to auto-await nested async calls.

4. Invokable Promises

  • Pattern: Use promises as callables (since v0.1.1).
  • Example:
    $promise = async(fn () => 42);
    $result = $promise(); // Equivalent to await($promise)
    

5. Laravel Integration

  • Pattern: Use in Artisan commands or console kernels.
  • Example Command:
    use Illuminate\Console\Command;
    use function Pokio\async, Pokio\await;
    
    class ParallelProcessCommand extends Command
    {
        protected $signature = 'process:parallel';
        public function handle()
        {
            $tasks = collect(range(1, 5))->map(fn ($i) =>
                async(fn () => $this->processTask($i))
            );
            await($tasks);
        }
    }
    

6. Fallback Behavior

  • Pattern: Pokio auto-falls back to sequential execution if:
    • pcntl or ffi are disabled.
    • Xdebug is in debug mode (since v1.0.1).
  • Tip: Test fallbacks with:
    if (!Pokio\supportsConcurrency()) {
        // Handle sequential execution
    }
    

7. Shared State

  • Pattern: Use shared memory (via FFI) for inter-process communication.
  • Example: Pass data between parent/child processes:
    $sharedData = async(fn () => [
        'key' => 'value',
    ]);
    $data = await($sharedData);
    

Integration Tips

  1. Testing:

    • Mock async/await in unit tests by replacing with synchronous calls or using Pokio\supportsConcurrency() to conditionally test fallbacks.
    • Example:
      if (Pokio\supportsConcurrency()) {
          $result = await(async(fn () => 'test'));
      } else {
          $result = 'test'; // Fallback
      }
      
  2. Debugging:

    • Use Xdebug with Pokio (since v1.0.1): No need to disable debugging for parallel tasks.
    • Tip: Set XDEBUG_TRIGGER=1 in your environment to ensure Xdebug doesn’t interfere.
  3. Performance:

    • Benchmark with pcntl/ffi vs. fallback to validate gains.
    • Tip: Avoid overloading with too many concurrent tasks (e.g., limit to CPU cores).
  4. Artisan Commands:

    • Extend Illuminate\Console\Command and use async/await in handle().
    • Tip: Use this->info() to log progress during parallel execution.
  5. Pest Testing:

    • Pokio is designed for Pest’s internal use. Leverage it for parallel test execution:
      test('parallel tests', function () {
          $promises = [
              async(fn () => expect(true)->toBeTrue()),
              async(fn () => expect(1+1)->toEqual(2)),
          ];
          await($promises);
      })->parallel();
      

Gotchas and Tips

Pitfalls

  1. No Production Support:

    • Gotcha: Pokio uses low-level process forking and FFI, which are not stable for production. Avoid for user-facing async APIs or long-running processes.
    • Workaround: Use Laravel Queues or Swoole for production-grade async.
  2. Xdebug Conflicts (Pre-v1.0.1):

    • Gotcha: Older versions would crash with Xdebug enabled. Since v1.0.1, Pokio auto-disables forking in debug mode.
    • Tip: Always use >=v1.0.1 if debugging parallel tasks.
  3. Stateful Processes:

    • Gotcha: Child processes are stateless. Avoid relying on global state (e.g., Laravel’s service container) in async closures.
    • Workaround: Pass all dependencies explicitly:
      $repo = new UserRepository();
      $promise = async(fn () use ($repo) => $repo->find(1));
      
  4. Memory Limits:

    • Gotcha: Forking creates new processes, which may hit memory limits (e.g., ulimit -v).
    • Tip: Limit concurrent tasks or increase memory limits in CI/local environments.
  5. FFI/PCNTL Dependencies:

    • Gotcha: Pokio falls back to sequential execution if pcntl or ffi are missing, but this may not be desired.
    • Tip: Check support at runtime:
      if (!Pokio\supportsConcurrency()) {
          throw new RuntimeException('Async not supported in this environment.');
      }
      
  6. Error Propagation:

    • Gotcha: Uncaught exceptions in async closures may not bubble up predictably.
    • Tip: Always use .catch() or try/catch with await:
      try {
          await(async(fn () => throw new Exception()));
      } catch (Throwable $e) {
          // Handle error
      }
      
  7. Shared Memory Leaks:

    • Gotcha: FFI shared memory isn’t automatically cleaned up. Long-running scripts may leak memory.
    • Tip: Avoid very long-lived processes with Pokio.

Debugging Tips

  1. Check Concurrency Support:

    var_dump(Pokio\supportsConcurrency()); // bool
    
    • Returns false if pcntl/ffi are missing or Xdebug is active.
  2. Log Process IDs:

    • Debug forking issues by logging posix_getpid() in parent/child:
      $
      
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.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony