Issue
Используя Laravel 5.7 с Redis, я получил уведомления о подтверждении электронной почты и сбросе пароля в очередь, используя метод, описанный в ответе Стивена Мудере в Как отправить ссылку для сброса пароля по электронной почте, используяочередь в laravel 5 , но я не могу понять, как ограничить скорость этих конкретных уведомлений в очереди.Поскольку мое приложение будет отправлять электронные письма по разным причинам (не только для этих двух целей), а мой почтовый сервер ограничен скоростью до 30 электронных писем в минуту, мне нужно ограничить скорость всего в очереди «электронной почты».
Справочная информация
В соответствии с очередью Laravel Документация кажется довольно простым сделать это в классе задания в методе handle, используя
Redis::throttle('key')->allow(10)->every(60)->then(function () {
// Job logic...
}, function () {
// Could not obtain lock...
return $this->release(10);
});
Проблема в том, что я использую не класс работы, а уведомление.Например, для сброса пароля я создал следующий
ResetPassword Class
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Auth\Notifications\ResetPassword as ResetPasswordNotification;
class ResetPassword extends ResetPasswordNotification implements ShouldQueue
{
use Queueable;
}
, который вызывается из модели пользователя с использованием:
public function sendPasswordResetNotification($token)
{
$this->notify(new ResetPasswordNotification($token));
}
Подход
У меня естьпопытался решить эту проблему, изменив функцию sendPasswordResetNotification в модели User:
public function sendPasswordResetNotification($token)
{
Redis::throttle('email')->allow(2)->every(60)->then(function () use($token) {
$this->notify(new ResetPasswordNotification($token));
}, function () {
// Could not obtain lock...
return $this->release(10);
});
}
Обратите внимание, что значения для дросселя искусственно занижены для целей тестирования.Кажется, это работает частично.В приведенном выше примере, если я попытаюсь выполнить две последовательные перезагрузки пароля, электронные письма будут помещены в очередь и отправлены.Когда я пытаюсь отправить третье письмо (превышающее установленное ограничение 2 в минуту), я получаю исключение BadMethodCallException, "Call to undefined method App\User::release()"
.Я понимаю, что это связано с тем, что в модели User нет метода выпуска, но возникает проблема, заключающаяся в том, что я точно не знаю, где и как использовать логику регулирования.Есть ли способ изменить это, чтобы работать, или мне нужно использовать совершенно другой подход к отправке этих сообщений?
Обновление: альтернативный подход, который не удается по другой причине
Я переключился сиспользуя уведомление об использовании Job, чтобы я мог использовать Redis :: throttle в соответствии с документацией.Чтобы настроить задание для очереди сообщений, я использовал подход из Как поставить в очередь Laravel 5.7 «проверка электронной почты» отправка электронной почты .Это отлично работало для отправки писем в очереди.Затем я попытался ограничить работу, идущую в очередь.Вот мой полный подход:
use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Support\Facades\Redis;
class QueuedVerifyEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function handle()
{
Redis::throttle('email')->allow(2)->every(60)->then(function () {
$this->user->notify(new VerifyEmail);
}, function() {
return $this->release(10);
});
}
}
Они идут в очередь, но затем терпят неудачу.В трассировке стека есть следующее: Symfony\Component\Debug\Exception\FatalThrowableError: Class 'App\Jobs\Redis' not found in /home/vagrant/code/myapp/app/Jobs/QueuedVerifyEmail.php:27
Я не могу понять, почему он ищет фасад Redis в App \ Jobs, когда у меня есть оператор использования для определения правильного местоположения.