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

php-standard-library/async

Fiber-based async primitives for PHP: structured concurrency with cooperative multitasking. Run tasks concurrently, manage lifecycles, cancellations, and scopes predictably. Part of PHP Standard Library; docs and guides at php-standard-library.dev.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require php-standard-library/async
    

    No additional configuration is required—Leverage Laravel’s autoloader.

  2. First Use Case: Async Database Queries (Safe)

    use Async\Task;
    use Async\Promise;
    use Illuminate\Support\Facades\DB;
    
    // Wrap a synchronous DB query in an async task (offload to queue in production)
    $promise = Task::run(function () {
        return DB::table('users')->where('id', 1)->first();
    });
    
    // Await the result (blocking—use cautiously in Laravel routes)
    $user = $promise->await();
    return response()->json($user);
    
  3. Where to Look First

    • Task class: The entry point for creating async tasks.
      • Methods: Task::run(), Task::later() (for delayed execution).
    • Promise class: For composing and awaiting results.
      • Methods: Promise::all(), Promise::race(), then(), catch().
    • Async facade: Laravel-friendly wrapper (if provided).
      • Example: Async::task(fn() => ...)->await().

Implementation Patterns

Core Workflows

1. Parallel Execution (Fan-Out/Fan-In)

// Fetch multiple API endpoints concurrently
$urls = ['https://api1.example.com', 'https://api2.example.com'];
$promises = collect($urls)->map(fn($url) =>
    Task::run(fn() => file_get_contents($url))
);

$results = Promise::all($promises)->await();

2. Sequential Async Chains

// Async waterfall pattern (e.g., auth → fetch data → process)
$result = Task::run(fn() => auth()->user())
    ->then(fn($user) => Task::run(fn() => UserService::fetchProfile($user)))
    ->then(fn($profile) => Task::run(fn() => $profile->process()))
    ->catch(fn($e) => logger()->error($e))
    ->await();

3. Error Handling

// Retry mechanism with exponential backoff
$task = Task::run(fn() => externalApiCall());
$task->retry(3, fn($attempt) => $attempt * 100); // Retry 3x with delays
$result = $task->catch(fn($e) => fallbackData())->await();

4. Integration with Laravel Queues

// Offload async tasks to Laravel's queue system
Task::later(now()->addSeconds(10), fn() =>
    dispatch(new ProcessPaymentJob($userId))
);

Laravel-Specific Patterns

Async Middleware (Laravel 11+)

public function handle(Request $request, Closure $next) {
    return Async::run(fn() => $next($request))->await();
}
  • Warning: Only use in async-compatible Laravel versions (risk of deadlocks in sync routes).

Async Eloquent Models

// Defer heavy computations to async
User::find(1)->then(fn($user) =>
    Task::run(fn() => $user->generateReport())
);

Async Artisan Commands

protected function handle() {
    Async::parallel([
        fn() => $this->processUsers(),
        fn() => $this->generateStats(),
    ])->await();
}

Testing Patterns

Mocking Async Tasks

// In PHPUnit tests
Async::shouldReceive('task')
    ->once()
    ->andReturn(new MockPromise([$expectedResult]));

$result = Async::task(fn() => ...)->await();
$this->assertEquals($expectedResult, $result);

Async Test Helpers

// Custom test trait for async assertions
trait AsyncAssertions {
    public function assertAwaits(Promise $promise, $expected) {
        $result = $promise->await();
        $this->assertEquals($expected, $result);
    }
}

Gotchas and Tips

Pitfalls

  1. Blocking the Main Thread

    • Issue: Calling await() in Laravel routes/middleware can block the request.
    • Fix: Use Task::later() or offload to queues.
      // Anti-pattern (blocks!)
      $result = Task::run(fn() => heavyTask())->await();
      
      // Pattern (non-blocking)
      Task::later(now()->addSecond(), fn() => heavyTask());
      
  2. Connection Leaks (Databases)

    • Issue: Async DB queries may not release connections properly.
    • Fix: Use DB::connection()->getPdo() or wrap in a queue job.
      // Risky: Async DB query
      Task::run(fn() => DB::table('users')->get());
      
      // Safer: Queue job
      dispatch(new AsyncDbJob());
      
  3. Uncaught Promise Rejections

    • Issue: Errors in async tasks may go unlogged.
    • Fix: Always chain .catch() or use a global handler.
      Async::task($task)->catch(fn($e) => report($e));
      
  4. Memory Bloat

    • Issue: Unawaited tasks consume memory.
    • Fix: Use Task::run()->detach() for fire-and-forget tasks.
      Task::run(fn() => cleanupOldLogs())->detach();
      
  5. Laravel’s Promise Facade Conflict

    • Issue: Namespace collisions with illuminate/support/Promise.
    • Fix: Prefer Async\Promise explicitly or alias:
      use Async\Promise as AsyncPromise;
      

Debugging Tips

  1. Pause Async Execution

    // Simulate async delays for debugging
    Task::run(fn() => sleep(2))->await();
    
  2. Inspect Pending Tasks

    // Log all active tasks (if package supports it)
    logger()->debug(Async::getActiveTasks());
    
  3. Timeout Handling

    // Add timeouts to tasks
    $task = Task::run(fn() => slowOperation())
        ->timeout(5.0) // 5 seconds
        ->catch(fn($e) => throw new TimeoutException());
    

Extension Points

  1. Custom Task Schedulers

    • Override Async\Scheduler to integrate with Laravel’s queue system.
    class LaravelQueueScheduler implements Scheduler {
        public function schedule(Task $task, ?\DateTimeInterface $delay = null) {
            dispatch(new AsyncTaskJob($task));
        }
    }
    
  2. Async Event Listeners

    // Listen to events asynchronously
    event(new UserRegistered($user))
        ->then(fn() => Task::run(fn() => sendWelcomeEmail($user)));
    
  3. Async Service Providers

    public function boot() {
        Async::task(fn() => $this->initializeCache())->detach();
    }
    

Configuration Quirks

  1. Concurrency Limits

    • Set globally to avoid overwhelming the app:
      Async::setConcurrency(10); // Max 10 concurrent tasks
      
  2. Error Reporting

    • Configure how rejected Promises are handled:
      Async::setErrorHandler(fn($e) => logger()->critical($e));
      
  3. Fiber Compatibility

    • Ensure your PHP version supports Fibers (PHP 8.1+).
    • Test with --enable-fiber-support if using custom runtimes.

Laravel-Specific Gotchas

  1. Service Container Binding

    • Bind the Async instance to Laravel’s container for dependency injection:
      $this->app->singleton(Async::class, fn() => new Async());
      
  2. Queue vs. Async

    • Use queues for:
      • Long-running tasks (>1s).
      • Tasks requiring persistence (retries, failures).
    • Use async tasks for:
      • Short-lived I/O operations (API calls, DB reads).
      • Composable workflows (e.g., Promise::all).
  3. Async in Jobs

    • Avoid nesting async tasks inside queue jobs (risk of deadlocks).
    • Prefer sequential execution or separate async layers.
  4. Testing Async Code

    • Use Async::fake() (if supported) or mock Task/Promise:
      Async::shouldReceive('task')->andReturn(new MockPromise([$data]));
      
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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai