nunomaduro/pokio
Pokio is a simple async API for PHP 8.3+ using pcntl forks and FFI shared memory to run closures concurrently and await results. Falls back to sequential execution if extensions aren’t available. Experimental/unsafe; intended for internal use, not production.
Pokio’s process-forking concurrency model is a strong fit for Laravel’s CLI ecosystem, particularly in:
Key Synergies:
async/await), easing adoption in Laravel’s CLI layer.PCNTL/FFI are unavailable, ensuring portability across environments (e.g., shared hosting).Anti-Patterns:
Pokio integrates seamlessly with Laravel’s CLI layer via:
use Pokio\Async;
class ProcessUserData extends Command {
protected $signature = 'users:process';
public function handle() {
$users = User::all();
$results = await(array_map(
fn ($user) => async(fn () => $this->processUser($user)),
$users->chunk(10)
));
// ...
}
}
require __DIR__.'/vendor/autoload.php';
[$data1, $data2] = await([
async(fn () => file_get_contents('https://api.example.com/1')),
async(fn () => file_get_contents('https://api.example.com/2')),
]);
async/await globally for CLI-only use cases:
if ($this->app->runningInConsole()) {
$this->app->singleton('async', fn () => new Async());
}
Compatibility Notes:
SIGTERM). Use pcntl_signal_dispatch() or wrap in a try/catch for robustness.| Risk | Impact | Mitigation |
|---|---|---|
| Process Leaks | Zombie processes if child tasks fail. | Use pcntl_wait() or declare(ticks=1) to reap children. |
| Shared Memory Corruption | FFI misuse could corrupt data. | Validate all shared data; prefer serialization for complex objects. |
| State Inconsistency | Child processes lack Laravel context. | Initialize dependencies (e.g., DB, cache) inside closures or use stateless logic. |
| Blocking Fallback | Sequential execution on unsupported PHP. | Benchmark fallback performance; avoid in CPU-bound tasks. |
| Signal Interference | CLI signals (e.g., Ctrl+C) may not propagate. |
Implement custom signal handlers or wrap await() in a try/catch. |
| Windows Limitation | No PCNTL support; always sequential. | Document Windows-specific behavior; consider alternative async libraries. |
| Error Isolation | Child process errors may not bubble up predictably. | Use catch() or try/catch with await() to handle exceptions centrally. |
Critical Questions for TPM:
ext-threads) be preferable (if available)?Pokio is optimized for Laravel’s CLI stack and integrates with:
exec()/popen() hacks with a Promise-based API.Non-Fit Areas:
Pilot Phase (Low Risk):
async/await.
Example: Convert a sequential foreach into parallel chunks:
// Before
foreach ($users as $user) {
$this->processUser($user);
}
// After
$users = User::all()->chunk(5);
await(array_map(fn ($chunk) => async(fn () => array_map([$this, 'processUser'], $chunk)), $users));
composer.json as a dev dependency (avoid require for CLI-only use).PCNTL/FFI.Core Integration (Medium Risk):
// app/Providers/AppServiceProvider.php
public function register() {
if ($this->app->runningInConsole()) {
$this->app->singleton('async', fn () => new \Pokio\Async());
}
}
// app/Facades/Pokio.php
facade_root();
// Usage: Pokio::async(fn () => ...);
Advanced Use Cases (High Risk):
Schema::table() operations concurrently (caution: race conditions on DB locks).QuestionHelper for non-blocking prompts:
$name = await(async(fn () => $this->ask('Enter name')));
How can I help you explore Laravel packages today?