1

I'm trying to send email notifications to my app users, limiting the number of emails to only 2 per minute, so as not to breach my email provider's allowed sending rate. So in MailingController.php I have:

<?php
namespace App\Http\Controllers;

use App\Jobs\SendMessages;
use Illuminate\Http\Request;

class MailingController extends Controller
{
    public function send(Request $request) {
        SendMessages::dispatch();
        return redirect()->back()->withSuccess('Successful operation.');
    }
}

SendMessages.php content is:

<?php
namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\Jobs\Middleware\RateLimited;
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Redis;

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

    public $timeout = 7200;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct()
    {
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $users = User::all();
        foreach ($users as $user) {
            Log::debug('SendMessages@handle() ' . $user->email);
             $user->notify(new VerifyEmail);
        }
    }

    public function middleware()
    {
        return [new RateLimited];
    }
}

And finally, RateLimited.php content is:

<?php
namespace App\Jobs\Middleware;

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class RateLimited
{
    /**
     * Process the queued job.
     *
     * @param  mixed  $job
     * @param  callable  $next
     * @return mixed
     */
    public function handle($job, $next)
    {
        Redis::throttle('key')
            ->block(0)->allow(1)->every(30)
            ->then(function () use ($job, $next) {
                // Lock obtained...
                Log::debug('RateLimited');
                $next($job);
            }, function () use ($job) {
                // Could not obtain lock...
                $job->release(16);
            });
    }
}

All these are copied and pasted from a Laravel 8 application that works perfectly fine, sending one email every 30 seconds as expected, but in my brand new Laravel 9 application the same code no longer works, and all email notifications are sent at once. I know I must be missing something, but have ran out of ideas. Any help would be greatly appreciated. Thank you.

E. Barney
  • 373
  • 4
  • 19

0 Answers0