skip to Main Content

My application is hosted on a shared hosting platform that limits to 200 emails per hour.
My application is running database connection driver and I have 3000 jobs in the jobs table.
I would like to throttle this queue to only send 1 email every 30 secs or 1 minute to ensure I don’t run issues with my hosting.

Research:
I have tried delay from this tutorial, rate limiting from this question with no response, delayed jobs from this laravel documention but nothing works.

Question: Is there a way to throttle the queue in database queue connection like they do it in redis queue connection i.e

// Allow only 1 email every 30 seconds
Redis::throttle('any_key')->allow(1)->every(30)->then(function () {
    Mail::to($this->email)->send(new NotificationEmail($this->data) );
    Log::info('Emailed order ' . $this->email);
}, function () {
    // Could not obtain lock; this job will be re-queued
    return $this->release(2);
});

My implementation: Delays only for the first job then sends the others with no delay

public function sendEmailNotification($email,$data)
{
    //Send email to user and to admin
    $email_job = (new ProcessEmailNotificationJob($email,$data))->delay(now()->addSeconds(30));
    
    if($this->dispatch($email_job)){
        return true;
    }
    else{
        return false;
    }
}

**ENV File: **

BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=database
SESSION_DRIVER=file
SESSION_LIFETIME=120

MEMCACHED_HOST=127.0.0.1

2

Answers


  1. Chosen as BEST ANSWER

    I'm not sure if this is the best option but the only solution that worked for me was sleeping the queue for 30 seconds after dispatch i.e

    Dispatch Method

    public function sendEmailNotification($email,$data)
    {
        //Dispatch all 3000 with no delay
        if(ProcessEmailNotificationJob::dispatch($email,$data)){
            return true;
        }
        else{
            return false;
        }
    }
    

    Sleep Queue Sender

    class ProcessEmailNotificationJob implements ShouldQueue
    {
        use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    
        private $email;
        private $data;
    
        /**
         * Create a new job instance.
         *
         * @return void
         */
        public function __construct($email,$data)
        {
            //
            $this->email = $email;
            $this->data = $data;
        }
    
        /**
         * Execute the job.
         *
         * @return void
         */
        public function handle()
        {
            //Send the Mail and sleep for 30 Seconds before sending the next one
            sleep(30);
            Mail::to($this->email)->send(new NotificationEmail($this->data) );
    
        }
    }
    

  2. did you run php artisan queue:listen, if yes check my below code maybe it will help

    inside your controller:

    $mail = (
        [
           'data' => $EmailData,
           'userName' => $userData->first_name,
           'userMail' => $userData->email,
           'subject' => $subject
        ]);
                        
    SendMailJob::dispatch($mail)
        ->delay(now()->addSeconds($waitSec));
    $waitSec += 30; //seconds interval
    

    SendMailJob class

    namespace AppJobs;
    
    use IlluminateBusQueueable;
    use IlluminateContractsQueueShouldBeUnique;
    use IlluminateContractsQueueShouldQueue;
    use IlluminateFoundationBusDispatchable;
    use IlluminateQueueInteractsWithQueue;
    use IlluminateQueueSerializesModels;
    use AppMailClientRegistrationNotification;
    use Mail;
    class SendMailJob implements ShouldQueue
    {
        use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    
        public $bulkMail, $mail;
        public function __construct($Mail)
        {
            $this->mail=$Mail;
        }
    
        public function handle()
        {
            try  {
                    Mail::to($this->mail['userMail'])
                         ->queue(new ClientRegistrationNotification($this->mail['data'], $this->mail['userName'], $this->mail['userMail'], $this->mail['subject']));
    
                 } catch (Throwable $exception) {
                    $this->fail();
                 }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search