1

I've read through the Firebase Cloud Functions reference, guides and sample code to try and determine why my function is triggered twice, but am yet to find a successful resolution. I've also trialed Firebase-Queue as a work-around, however its latest update suggests Cloud Functions is the way to go.

In short, I'm retrieving notices from an external API using request-promise, checking those notices against ones I already have in my database, and when a new notice is identified, posting it to said database. The corresponding venue is then updated with a reference to the new notice. Code is as follows:

'use strict';

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const request = require('request');
const rp = require('request-promise');

admin.initializeApp(functions.config().firebase);

const db = admin.database();
const venues = db.ref("/venues/");

exports.getNotices = functions.https.onRequest((req, res) => {
    var options = {
        uri: 'https://xxxxx.xxxxx',
        qs: {
            format: 'json',
            type: 'venue',
            ...
        },
        json: true
    };
    rp(options).then(data => {
            processNotices(data);
            console.log(`venues received: ${data.length}`);
            res.status(200).send('OK');
        })
        .catch(error => {
            console.log(`Caught Error: ${error}`);
            res.status(`${error.statusCode}`).send(`Error: ${error.statusCode}`);
    });
});

function processNotices(data) {
    venues.once("value").then(snapshot => {
        snapshot.forEach(childSnapshot => {
            var existingKey = childSnapshot.val().key;
            for (var i = 0; i < data.length; i++) {
                var notice = data[i];
                var noticeKey = notice.key;
                if (noticeKey !== existingKey) {
                    console.log(`New notice identified: ${noticeKey}`)
                    postNotice(notice);
                }
            }
            return true;
        });
    });
}

function postNotice(notice) {
    var ref = venues.push();
    var key = ref.key;
    var loc = notice.location;
    return ref.set(notice).then(() => {
        console.log('notice posted...');
        updateVenue(key, loc);
    });
}

function updateVenue(key, location) {
    var updates = {};
    updates[key] = "true";
    var venueNoticesRef = db.ref("/venues/" + location + "/notices/");
    return venueNoticesRef.update(updates).then(() => {
        console.log(`${location} successfully updated with ${key}`);
    });
}

Any suggestions as to how to rectify the double-triggering would be greatly appreciated. Thanks in advance!

Aravind A R
  • 2,674
  • 1
  • 15
  • 25
donovki
  • 101
  • 1
  • 6
  • How are you invoking it such that it should only execute once? What do the logs show? – Doug Stevenson Jun 26 '17 at 18:24
  • Also note that you're doing async database work without waiting for it to complete in processNotices(). It should be returning a promise so the caller can know when the database work is fully complete before sending a response to the client. – Doug Stevenson Jun 26 '17 at 18:26
  • Thanks for the prompts, @DougStevenson. I've found a solution (detailed below). – donovki Jul 05 '17 at 05:47

1 Answers1

0

Problem solved - some misinformation from the Firebase Console Logs (repeating entries), coupled with nested for loops in the wrong order were responsible for the apparent double triggering.

donovki
  • 101
  • 1
  • 6