在Google App Engine上运行时,Firebase函数被调用了两次 [英] Firebase functions being called twice while running on Google App Engine

查看:63
本文介绍了在Google App Engine上运行时,Firebase函数被调用了两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Google App Engine灵活环境中运行firebase.我在一个节点上设置了一个添加子项的侦听器,每次添加一个子项时,它都会被调用两次.仅当我在Google App Engine上运行此代码时,才会发生这种情况.如果我在本地运行,它将按预期运行.这是代码

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.

推荐答案

测试了一段时间后,我发现了.此问题是由在Google App Engine上运行Firebase-Admin引起的.本质上,您AppEngine所在的每个基础VM都在运行自己的Firebase-Admin实例.默认情况下,AppEngine会为每个服务维护至少两个VM.因此,在测试(在最小负载下)时,两个VM实例中的每一个实例都会调用firebase函数一次.

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.

显然,没有关于此问题的文档,但是Google/Firebase提供了一个确实可以解决此问题的库.它称为Firebase-Queue,可以在NPM上找到.我用以下代码解决了我的问题:

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]

这篇关于在Google App Engine上运行时,Firebase函数被调用了两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆