2016-12-05 71 views
1

我在Google App Engine靈活環境中運行Firebase。我有一個孩子添加了在節點上設置的監聽器,每次添加一個孩子時它會被調用兩次。只有在Google App Engine上運行此代碼時纔會發生這種情況。如果我在本地運行它,它按預期運行。這裏是代碼在Google App Engine上運行時調用兩次Firebase函數

// [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] 

感謝您提前的任何幫助。

回答

3

經過一段時間的測試,我找到了答案。此問題是由於在Google App Engine上運行Firebase-Admin導致的。實質上,您的AppEngine所在的每個底層虛擬機都運行其自己的Firebase-Admin實例。 AppEngine默認爲每項服務維護至少兩臺虛擬機。因此,在測試中(在最小負載下),兩個VM實例中的每一個都會調用一次firebase函數。

顯然,這個問題上沒有文檔,但是有一個來自Google/Firebase的庫可以解決這個問題。它被稱爲Firebase-Queue,它可以在NPM上找到。我用這段代碼解決了我的問題:

// [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] 
+1

謝謝你找到這個,比谷歌應用程序引擎API更可靠! –

相關問題