Strange numbers from multiple transactions with cloud features with Firebase

I'm new to Javascript, Promises, and fairly new to Firebase, so this might just be a misunderstanding about something basic. I appreciate any guidance!

Problem I'm running into: I keep 3 counters for specific events. So every time an "item" is added to a "user" I am updating the global item count, object count, and user count.

This works great when I use it and check it, however something is wrong when I sometimes log data after a few days and the global counts seem to have doubled. For example, I will look at the user's account which will be 200, however if I look at the actual data, that is, there are only 100 items, which makes me think that the account transactions are incremented by two instead of one (or called twice).

I cannot replicate it myself, and whenever I use this function all counts are incremented appropriately by one. But if I leave it on for a few days, the numbers start to increase by 2 or more.

My Firebase function, listening to DB:

"use strict";

// Firebase requirements
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const utils = require('./utils');
admin.initializeApp(functions.config().firebase);

exports.updatePatientCount = functions.database.ref('/projects/{projectId}/users/{userId}/itemList/{itemId}').onWrite(event => {
    // Extract the projectKey and userId
    var projectId = event.params.projectId
    var userId = event.params.userId

    return utils.saveGlobals(admin, event, "itemCount", projectId, userId);
});

      

saveGlobals:

"use strict";

const counter = function (up, count) {
    if (up) {
        return (count || 0) + 1;
    }

    return (count || 0) - 1;
};

exports.saveGlobals = function (admin, event, ref, projectId, userId) {
    const gloRef = admin.database().ref("global-stats/global");
    const gloProjRef = admin.database().ref("global-stats/projects");

    var up = false;
    // If data was created increment by 1
    if (event.data.exists() && !event.data.previous.exists()) {
        up = true;
    } else if (!event.data.exists() && event.data.previous.exists()) {
        // If the data was deleted deincrement by 1
        up = false;
    } else {
        // If the data was updated return
        return;
    }

    // Update the global count
    const setGlo = gloRef.child(ref).transaction(current => {
        return counter(up, current);
    }).then(() => {
        console.log('Global updated.');
    });

    // Update the project count + set the project ID 
    const setPro = gloProjRef.child(projectId).child("projectId").set(projectId);
    const setGloPro = gloProjRef.child(projectId).child(ref).transaction(current => {
        return counter(up, current);
    }).then(() => {
        console.log('Global project updated.');
    });

    // Update the user count + set the ID
    const setUse = gloProjRef.child(projectId).child("users").child("ID-" + userId).child("userId").set(userId);
    const setGloUse = gloProjRef.child(projectId).child("users").child("ID-" + userId).child(ref).transaction(current => {
        return counter(up, current);
    }, ).then(() => {
        console.log('Global user updated.');
    });

    // Return the promises
    return setGlo && setPro && setGloPro && setUse && setGloUse;
}

      

The example I used to combine: https://github.com/firebase/functions-samples/tree/master/child-count

I pulled out the saveGlobals () part because it is used by several cloud functions that increment different counters.

Can anyone see any reason why transactions should start incrementing counters by more than one when an item is added to the list?

+3


source to share





All Articles