21

Is it acceptable to increment a counter with a realtime database trigger using transaction?

exports.incPostCount = functions.database.ref('/threadsMeta/{threadId}/posts')
.onWrite(event => {
    admin.database().ref('/analytics/postCount')
    .transaction(count => {
        if (count === null) {
            return count = 1
        } else {
            return count + 1
        }
    })
});
AL.
  • 36,815
  • 10
  • 142
  • 281
J. Adam Connor
  • 1,694
  • 3
  • 18
  • 35

1 Answers1

41

Definitely! In fact, that's exactly how it's done in this code sample, although with a few small differences:

exports.countlikechange = functions.database.ref("/posts/{postid}/likes/{likeid}").onWrite((event) => {
  var collectionRef = event.data.ref.parent;
  var countRef = collectionRef.parent.child('likes_count');

  return countRef.transaction(function(current) {
    if (event.data.exists() && !event.data.previous.exists()) {
      return (current || 0) + 1;
    }
    else if (!event.data.exists() && event.data.previous.exists()) {
      return (current || 0) - 1;
    }
  });
});

Notably, this sample handles both an increment and a decrement case depending on whether the child node is being created or deleted.

Michael Bleigh
  • 25,334
  • 2
  • 79
  • 85
  • 1
    Excellent. Thank you. – J. Adam Connor Mar 21 '17 at 00:27
  • I recall reading somwhere that firebase might call some functions more than once. The same page strongly suggested writing idempotent functions. Is this safe? – natario May 28 '18 at 21:22
  • If you depend on the number being 100% right 100% of the time, then yes you'll need to write the function idempotently. Sometimes off by a few isn't a problem, in which case this will be fine. You can also have a hybrid solution where you periodically run a script that will go through and "fix" any counts that are incorrect by reading the canonical data. – Michael Bleigh Jun 01 '18 at 23:12
  • @MichaelBleigh For example when a posts gets deleted. The countlikechange get executed. How are you going to prevent that the countRef gets executed? – da1lbi3 Jul 23 '18 at 12:21