Firebase functions being called twice while running on Google App Engine

淺唱寂寞╮ 提交于 2019-12-08 06:32:08

问题


I am running firebase in a Google App Engine Flexible environment. I have a child added listener set up at a node and it gets called twice every single time I add one child. This only happens when I'm running this code on Google App Engine. If I run it locally, it operates as expected. Here is the code

// [START app]
'use strict';

var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var firebase = require('firebase-admin');

var app = express();

firebase.initializeApp({
    credential: firebase.credential.applicationDefault(),
    databaseURL: "https://myurl.firebaseio.com/"
});

var db = firebase.database();
var globalNotifications = db.ref("/globalNotifications");

var API_KEY = "myKey"; // Your Firebase Cloud Server API key
var now = new Date();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

globalNotifications.orderByChild('processed').equalTo(0).on("child_added", function(snapshot) {

    var key = snapshot.key;
    var incomingNotification = snapshot.val();
    var userID = incomingNotification.userID;
    var notifyID = incomingNotification.notifyID;

    request({
        url: 'https://fcm.googleapis.com/fcm/send',
        method: 'POST',
        headers: {
            'Content-Type' :'application/json',
            'Authorization': 'key='+API_KEY
        },
        body: JSON.stringify({
            "to" : incomingNotification.notificationID,
            "priority" : "high",
            "notification" : {
                "body" : "someone is following you",
                "title" : "You have a new follower"
            }
        })
    }, function(error, response, body) {
        if (error) { console.error(error); }
        else if (response.statusCode >= 400) {
            console.error('HTTP Error: '+response.statusCode+' - '+response.statusMessage);
        }
        else {
            console.log(response.statusCode);
            console.log(body);
            globalNotifications.child(key).update({"processed": 1, "response": body});
        }
    });

});

// Start the server
var server = app.listen(process.env.PORT || '8080', function () {
    console.log('App listening on port %s', server.address().port);
    console.log('Press Ctrl+C to quit.');
});
// [END app]

Thanks for any help in advance.


回答1:


After testing for a while I figured it out. This issue is caused by running Firebase-Admin on Google App Engine. Essentially, every underlying VM that your AppEngine sits on is running its own instance of Firebase-Admin. AppEngine, by default, maintains at least two VMs for every service. So in testing (under minimal load) the firebase functions are being called once by each of the two VM instances.

Apparently, there is no documentation on this issue but there is a library from Google/Firebase that does solve this problem. It is called Firebase-Queue and it can be found on NPM. I solved my issue with this code:

// [START notificationsservice app]
'use strict';

var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var rp = require('request-promise');
var admin = require('firebase-admin');
var Queue = require('firebase-queue');

var app = express();

admin.initializeApp({
    credential: admin.credential.cert("serviceAccountCredentials.json"),
    databaseURL: "https://<YOUR PROJECT ID HERE>.firebaseio.com/"
});

var db = admin.database();
var notifications = db.ref('/notifications');

var API_KEY = "<YOUR API KEY HERE>"

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

var queue = new Queue(notifications, function(data, progress, resolve, reject) {

    var incomingNotification = data;
    var userID = incomingNotification.userID;
    var username = incomingNotification.username;

    rp({
        url: 'https://fcm.googleapis.com/fcm/send',
        method: 'POST',
        headers: {
            'Content-Type' :'application/json',
            'Authorization': 'key='+API_KEY
        },
        body: JSON.stringify({
            "to" : "/topics/follower-"+userID,
            "priority": "high",
            "notification" : {
                "body" : username+" you have a notification",
            },
            "data" : {
                "type" : "follower"
            }
        })
    }).then(function(body) {
        progress(100);
        console.log("Notification sent."+body);
        resolve();
    }).catch(function(error) {
        progress(21);
        console.log(error);
        reject(); 
    });

  setTimeout(function() {
    resolve();
  }, 1000);
});

// Start the server
var server = app.listen(process.env.PORT || '8080', function () {
    console.log('App listening on port %s', server.address().port);
    console.log('Press Ctrl+C to quit.');
});
// [END app]


来源:https://stackoverflow.com/questions/40981572/firebase-functions-being-called-twice-while-running-on-google-app-engine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!