Enhancing Your Laravel Job Handling with Middleware: Managing HttpClientException

Laravel devs, here's a gem for you: πŸ’Ž

If you're looking to improve the resilience and efficiency of your job handling in Laravel, leveraging middleware is a powerful approach. In this post, we'll explore how to use the ThrottlesExceptions middleware to handle failed HTTP requests gracefully and ensure your jobs stay robust even under intermittent failures.

Using Middleware in Laravel Jobs

Middleware in Laravel provides a way to filter HTTP requests entering your application. However, it can also be applied to queued jobs to control their execution flow. The ThrottlesExceptions middleware is particularly useful when dealing with external HTTP requests that may fail intermittently.

Example: The GetArticle Job

Let's dive into a practical example with the GetArticle job. This job fetches an article from a given URL, processes it, and stores it in the database. We'll add middleware to handle retries in case of failures.

Here's the complete code for the GetArticle job:

<?php

namespace App\Jobs;

use Http;
use App\Models\Article;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Http\Client\HttpClientException;

class GetArticle implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(public string $url){}

    public function middleware()
    {
        return [
            (new ThrottlesExceptions(
                maxAttempts: 3, 
                decayMinutes: 5
            ))->by('service_id_here')
            ->backoff(1)
            ->when(function (Throwable $e) {
                return $e instanceof HttpClientException;
            })
        ];
    }

    public function handle()
    {
        $response = Http::acceptJson()
            ->timeout(10)
            ->get($this->url);

        if ($response->serverError()) {
            return $this->release(600);
        }

        $transformedData = Article::transform($response->json());
        Article::create($transformedData);
    }
}

GetArticle.php

Controller to Dispatch the Job

To complete the example, we need a controller to dispatch the GetArticle job. Here is a simple controller that accepts a URL and dispatches the job:

<?php

namespace App\Http\Controllers;

use App\Jobs\GetArticle;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class ArticleController extends Controller
{
    public function fetchArticle(Request $request)
    {
        $url = $request->input('url');
        GetArticle::dispatch($url);

        return response()->json(['message' => 'Article fetch job has been dispatched.']);
    }
}

ArticleController.php

Route Definition

Next, define a route to handle the request and invoke the controller method:

use App\Http\Controllers\ArticleController;

Route::post('/fetch-article', [ArticleController::class, 'fetchArticle']);

routes/web.php

Breaking Down the Code

  1. Middleware Setup:
    The middleware method in the GetArticle job class sets up the ThrottlesExceptions middleware. This middleware is configured to retry a failed job up to 3 times, with a cooldown period of 5 minutes between attempts. The backoff(1) method ensures a delay of 1 minute before retrying. This setup is particularly useful for handling intermittent failures, such as temporary network issues or service unavailability.
  2. Exception Handling:
    The middleware checks for the specific HttpClientException to apply the throttle only when this type of exception occurs. This ensures that only relevant errors are throttled, making the job handling more efficient and targeted.
  3. Job Execution:
    In the handle method, the job attempts to fetch an article from a specified URL. If the server returns an error, the job is released back to the queue to be retried after 10 minutes. If successful, the response data is transformed and saved to the database.
  4. Controller and Route:
    The ArticleController includes a method to handle incoming requests and dispatch the GetArticle job. The route definition ensures that the controller method is accessible via a POST request.

Benefits of Using Middleware for HttpClientException

Using middleware specifically designed to handle HttpClientException in your jobs brings several targeted benefits:

  1. Targeted Error Handling:
    Middleware like ThrottlesExceptions can be configured to handle specific exceptions such as HttpClientException. This means that only relevant HTTP client errors will trigger the retry mechanism, ensuring that your application doesn't waste resources retrying for non-recoverable errors.
  2. Retry Mechanism:
    By leveraging middleware, you can implement a robust retry mechanism. This allows your job to automatically retry a few times (e.g., up to 3 attempts) if it encounters an HttpClientException. This is particularly useful for dealing with transient network issues or temporary unavailability of external services.
  3. Cooldown Periods:
    The middleware can introduce cooldown periods (e.g., 5 minutes) between retries. This helps prevent hammering the external service with continuous requests, giving it time to recover if it’s experiencing issues.
  4. Customizable Backoff Strategies:
    You can customize the backoff strategy to wait a specific amount of time (e.g., 1 minute) before attempting the job again. This ensures that retries are spaced out, reducing the likelihood of repeated failures in quick succession.
  5. Improved Resilience:
    By automatically handling retries and managing failures, your job processing becomes more resilient. This helps maintain the smooth operation of your application even when external dependencies are unstable.
  6. Resource Optimization:
    Efficiently handling specific exceptions with middleware helps optimize server resources by avoiding unnecessary retries for non-recoverable errors. This keeps your queue workers focused on tasks that have a higher chance of success.

Conclusion

Integrating middleware into your Laravel job handling can significantly enhance the robustness and efficiency of your applications. The ThrottlesExceptions middleware, in particular, is a powerful tool for managing retries and handling specific exceptions like HttpClientException gracefully. By implementing such strategies, you ensure that your jobs are resilient and capable of dealing with intermittent failures effectively.

Found this helpful?

If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!

Subscribe to Harris Raftopoulos

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe