Node.js - FCM отправляет запланированное уведомление о теме - PullRequest
1 голос
/ 24 июня 2019

Я использую приложение Angular и сервер Node.js для отправки тематических уведомлений на устройства Android с помощью FCM.Я использую bull для планирования уведомлений.

Существует два способа отправки уведомления: отправить уведомление сейчас и отправить уведомление в определенную дату и время.

Для отправки уведомлений я использую приложение Angular и этот метод:

  sendTopicNotification(notification: Notification): Observable<any> {
    console.log("send topic");
    return this.http.post(endpoint + `notifications/send/topic/topic${notification.target}`, JSON.stringify(notification), httpOptions).pipe(
      map(result => { return true; })
    );
  }

Это мой код Node.js:

const express = require('express');
const router = express.Router();
const fb = require('../firebase/fb');
const db = fb.firestore();
const fcm = fb.messaging();
const moment = require('moment');

var Queue = require('bull');
var notificationsQueue = new Queue('topic notifications', { redis: { port: 6379, host: '127.0.0.1' } }); // Specify Redis connection using object

const notificationsCollection = 'notifications';
const donationsCollection = 'donations';


router.post('/send/topic/:topic', (req, res) => {
    var topic = `/topics/${req.params.topic.toString()}`;

    var payload = {
        notification: {
            title: req.body.title,
            body: req.body.body
        }
    };

    var options = {
        priority: "high",
        timeToLive: 60 * 60 * 24
    };

    if (req.body.sendDate && req.body.sendHour) {
        var date = req.body.sendDate;
        var hour = req.body.sendHour;
        scheduleMessage(date, hour, topic, payload, options);
    } else {
        sendTopicNotification(topic, payload, options);
    }


    res.send(200);
});

//Schedule the job
async function scheduleMessage(date, hour, topic, payload, options, res) {
    var date = date.toString().split("/");
    var hour = hour.toString().split(":");
    console.log(date[2], date[1], date[0], hour[0], hour[1], 0);
    var jobDate = new Date(date[2], date[1] - 1, date[0], hour[0], hour[1]);

    console.log(jobDate);
    console.log(new Date());
    var jobDelay = ((jobDate.getTime() / 1000) - (Math.floor(new Date().getTime() / 1000)));

    console.log(jobDate.getTime() / 1000);
    console.log(Math.abs(jobDelay));
    console.log(Math.floor(new Date().getTime() / 1000));

    const job = await notificationsQueue.add({
        topic: topic,
        payload: payload,
        options: options
    }, { delay: Math.abs(jobDelay) });
    console.log(date + " " + hour);
}

//Process qued job
notificationsQueue.process(async (job, done) => {
    console.log(job.data);
    sendTopicNotification(job.data.topic, job.data.payload, job.data.options);
});

//Send notificaiton
function sendTopicNotification(topic, payload, options) {
    var currentTime = new Date().getTime();

    var target;
    switch (topic) {
        case "/topics/topicA":
            target = 'Donatorii cu grupa sanguină A'
            break;
        case "/topics/topicB":
            target = 'Donatorii cu grupa sanguină B'
            break;
        case "/topics/topicAB":
            target = 'Donatorii cu grupa sanguină AB'
            break;
        case "/topics/topic0":
            target = 'Donatorii cu grupa sanguină 0'
            break;
        case "/topics/topicAll":
            target = 'Toți donatorii'
            break;
        default:
            break;
    }
    fcm.sendToTopic(topic, payload, options)
        .then((response) => {
            db.collection(notificationsCollection).doc(currentTime.toString()).set({
                title: payload.notification.title,
                body: payload.notification.body,
                date: currentTime,
                target: target,
                status: "Notificarea a fost trimisă!"
            }).then((res) => {
                console.log('Create new notification ');
            });
            // Response is a message ID string.
            console.log('Successfully sent message:', response);
        })
        .catch((error) => {
            db.collection(notificationsCollection).doc(currentTime.toString()).set({
                title: payload.notification.title,
                body: payload.notification.body,
                date: currentTime,
                target: topic,
                status: "Notificarea nu a fost trimisă!"
            }).then(() => {
                console.log('Create new notification');
            });
            console.log('Error sending message:', error);
        });
}
module.exports = router;

1)."Теперь "уведомление

Тело уведомления (отправлено из Angular):

{
    body: "test",
    date: undefined,
    status: "Notificarea nu a fost trimisă!",
    target: "A",
    title: "test",
}

Это результат и журналы:

express deprecated res.send(status): Use res.sendStatus(status) instead routes/notifications.js:41:9
Successfully sent message: { messageId: 9203836031271870000 }
Create new notification

Уведомление достигает приложения Android ивсе работает нормально, как и ожидалось.

2)."Запланированное уведомление"

Тело уведомления (отправлено из Angular):

{
    body: "test",
    date: undefined,
    sendDate: "29/06/2019",
    sendHour: "07:27",
    status: "Notificarea nu a fost programată!",
    target: "A",
    title: "test",
}

Эторезультат и логи:

2019-06-29T04:27:00.000Z
2019-06-29T04:25:35.070Z
{ topic: '/topics/topicA',
  payload: { notification: { title: 'test', body: 'test' } },
  options: { priority: 'high', timeToLive: 86400 } }
Successfully sent message: { messageId: 5284791767401410000 }
Create new notification 

Теперь что-то не так с поведением.Уведомление не достигнет приложения Android, пока я не перезапущу серверКак вы можете видеть, он запрограммирован на отправку в 2019-06-29T04:27:00.000Z, но ничего не было отправлено даже после более длительного периода.Когда я перезагружаю сервер, приложение Android получит последнее отправленное уведомление.

Итак, мои проблемы во втором сценарии:

  • уведомления не отправляются после задержки;
  • уведомления не сохраняются в очереди, поэтому после перезапуска сервера будет отправляться только последнее;
  • после перезапуска сервера ранее запланированные уведомления, похоже, отправляются и включаются.Например: первое уведомление отправлено, перезапущено, второе отправлено, перезапущено, первое отправлено и т. Д.

Чего мне не хватает?

1 Ответ

3 голосов
/ 29 июня 2019

Я вижу две небольшие проблемы с вашим кодом.

  1. Задержка задания отправляется в секундах, а не в миллисекундах.

Заменить { delay: Math.abs(jobDelay) }); на { delay: Math.abs(jobDelay) * 1e3 });

  1. Вам нужно вызвать done () после того, как задание было обработано.

Добавить done(); после sendTopicNotification(job.data.topic, job.data.payload, job.data.options);.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...