Laravel планирует push-уведомление и при необходимости отмените его

В моем приложении с Laravel на сервере пользователи могут отправлять сообщения друг другу.

Я хочу отправить push-уведомление пользователям приложения о новом сообщении в почтовом ящике, но мне нужно отправлять сообщения только в том случае, если пользователь еще не прочитал это сообщение.

Так что я так вижу

  1. Для каждого отправленного сообщения мне нужно запланировать уведомление Laravel через 1 минуту
  2. если пользователь уже получил это сообщение, мне нужно отменить это уведомление

Как отклонить запланированное уведомление в Laravel? Насколько хорошо и актуален сейчас такой подход?

Класс расширяет уведомление

public function via($notifiable)
{
    if($this->dontSend($notifiable)) {
        return [];
    }
    return ['mail'];
}

public function dontSend($notifiable)
{
    return $this->appointment->status === 'cancelled';
} 

Может есть более удобный способ справиться с этим? Например, отправлять push каждый раз, но как-то убрать его отображение из приложения, если оно уже запущено?


person moonvader    schedule 28.06.2020    source источник
comment
Как узнать, получил ли пользователь уведомление? Вы за этим следите?   -  person Ersoy    schedule 30.06.2020
comment
Если приложение включило push-уведомления, я могу отслеживать их внутри приложения и при необходимости отправлять API-запросы на сервер.   -  person moonvader    schedule 30.06.2020


Ответы (1)


Один из способов сделать это - сделать что-то вроде этого;

  • Прежде чем запускать уведомление, создайте уникальный идентификатор (sha1 может быть опцией) с комбинацией user_id. Допустим, это SgiA7EfBQBFQK3pjRWtaxB1CkSf7gf4lSixvei3jU3ydHJ39ZGjhhdUUCnHRno3C. Отправьте это в уведомление. И уведомление, и сообщение будут отправлены одновременно, но уведомление будет иметь задержку в одну минуту.
$identifier = Str::random(64);
$delay = now()->addMinute();
$user->notify((new MyNotification($identifier))->delay($delay));
// send a request that contains identifier.
  • Вы устанавливаете это на Redis с TTL в 2 минуты. Он исчезнет, ​​если не будет предпринято никаких действий.
Redis::set('SgiA7EfBQBFQK3pjRWtaxB1CkSf7gf4lSixvei3jU3ydHJ39ZGjhhdUUCnHRno3C', 1, 120);
  • Отправляя сообщение пользователю, прикрепите этот идентификатор к сообщению. Когда пользователь читает это сообщение, вы делаете запрос к своей конечной точке / read со всеми параметрами + идентификатором.
  • При получении запроса удалите ключ из Redis. (пользователь получил сообщение)
Redis::del('SgiA7EfBQBFQK3pjRWtaxB1CkSf7gf4lSixvei3jU3ydHJ39ZGjhhdUUCnHRno3C');
  • В своем классе уведомлений реализуйте небольшой метод, чтобы проверить, существует ли ключ в Redis.
Redis::exists('SgiA7EfBQBFQK3pjRWtaxB1CkSf7gf4lSixvei3jU3ydHJ39ZGjhhdUUCnHRno3C');
class MyNotification extends BaseNotification
{
    use Queueable;

    private $identifier;

    public function __construct($identifier)
    {
        $this->identifier = $identifier;
    }

    public function via()
    {
        return $this->isValid() ? ['mail'] : [];
    }

    public function isValid()
    {
        return Redis::exists($this->identifier);
    }

    public function toMail()
    {
        // details..
    }
}

Это не обязательно должен быть Redis, но он идеально подходит для такой структуры ключ / значение.

person Ersoy    schedule 03.07.2020
comment
в этом случае мне нужно вызвать уведомление через 2 минуты? - person moonvader; 04.07.2020
comment
На самом деле вы активируете его, когда отправляете сообщение. Уведомление будет отправлено с задержкой в ​​1 минуту. - person Ersoy; 04.07.2020