Skip to content

Phase 2: Queue webhook processing via a Laravel Job #9

@dkwiebe

Description

@dkwiebe

Summary

Webhook payloads are currently processed synchronously during the HTTP request. If the database is slow or under load, AWS SNS may not receive a 200 OK within its 15-second timeout and will retry — potentially causing duplicate processing pressure. Moving to a queued Job returns 200 immediately and decouples processing from the HTTP layer.

Implementation

1. Create app/Jobs/ProcessSesWebhook.php

Move the core logic from SesWebhookController into the Job:

  • Payload parsing (SNS-wrapped vs. direct SES format)
  • Email, EmailRecipient, RecipientEvent creation
  • Sentry error capture

2. Update SesWebhookController

The controller becomes thin:

public function __invoke(Request $request, string $token)
{
    $project = Project::where('token', $token)->firstOrFail();
    ProcessSesWebhook::dispatch($project, $request->all());
    return response()->json(['status' => 'queued'], 200);
}

3. Configure the queue

The app defaults to the database queue driver. No infrastructure changes needed for basic use. Document QUEUE_CONNECTION=database in .env.example and add a note about running php artisan queue:work.

4. Flush the per-project cache tag (from issue #5) at the end of the Job after all DB writes succeed.

Acceptance Criteria

  • Webhook controller returns 200 within milliseconds regardless of DB load
  • All existing webhook processing tests pass against the new Job
  • Failed jobs appear in failed_jobs table with payload context
  • .env.example documents QUEUE_CONNECTION

Metadata

Metadata

Assignees

No one assigned

    Labels

    performancePerformance improvementsphase-2Security hardeningsecuritySecurity improvements

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions