Cookbook

Async Concurrency Recipes

Practical patterns for parallelism, cancellation, and resilient HTTP.

This cookbook shows how to leverage Glueful's fiber-based async primitives in common scenarios.

Parallel Fetch (Controller)

use Symfony\Component\HttpFoundation\Request;
use Glueful\Controllers\BaseController;
use Glueful\Http\Response;

$router->get('/dashboard', [DashboardController::class, 'show'])
    ->middleware(['async']);

class DashboardController extends BaseController
{
    public function show(Request $request)
    {
        $users = async(fn() => $this->repo->recentUsers());
        $stats = async(fn() => $this->analytics->summary());
        $news  = async(fn() => $this->news->latest());

        [$u, $s, $n] = await_all([$users, $stats, $news]);
        return Response::success(compact('u', 's', 'n'));
    }
}

First-Responder (Race)

Prefer the fastest source and continue gracefully:

$result = await_race([
    async(fn() => $this->cache->getFallback()),
    async(fn() => $this->service->fetchFresh()),
]);

Cooperative Cancellation

$token = cancellation_token();

$task = async(function() use ($token) {
    while (!$token->isCancelled()) {
        // do incremental work
        async_sleep(0.05, $token);
    }

    // cleanup if needed
});

// cancel from another place (timeout/user action)
$token->cancel();

try {
    await($task);
} catch (\Throwable $e) {
    // handle cancellation or failure
}

Parallel HTTP With Retries

use Glueful\Async\Contracts\Http\HttpClient;
use Glueful\Controllers\BaseController;
use Glueful\Http\Response;

class FeedController extends BaseController
{
    public function __construct(private HttpClient $http) {}

    public function index()
    {
        $feeds = [
            'a' => 'https://api.example.com/a',
            'b' => 'https://api.example.com/b',
            'c' => 'https://api.example.com/c',
        ];

        $tasks = [];
        foreach ($feeds as $key => $url) {
            $tasks[$key] = async(fn() => $this->http->get($url));
        }

        $responses = await_all($tasks);
        $payload = [];
        foreach ($responses as $k => $resp) {
            $payload[$k] = $resp->json();
        }

        return Response::success($payload);
    }
}

Configuration knobs (via your config layer):

  • async.http.max_retries, async.http.retry_delay_seconds, async.http.retry_on_status
  • async.http.max_concurrent, async.http.poll_interval_seconds

Tips

  • Use ->middleware(['async']) only where concurrency is beneficial (I/O heavy).
  • Keep tasks small and side-effect aware; prefer idempotent operations.
  • Respect cancellation tokens inside loops and long operations.
  • Use metrics to observe task counts, latencies, and retries.