0

I am trying to add +1 to a specific field in the realtime database. My function:

exports.dbWriteOnNewPost = functions.database.ref('/posts/{postid}').onWrite((change, context) => {
        const postUUID = context.params.postid;
        const postData = change.after.val();
        const communityUUID = postData.community;
        const authorUUID = postData.author;
        const postDate = postData.date;

        const promisePostByCommunity = admin.database().ref('/posts_by_community/' + communityUUID + '/' + postUUID).set(postDate);
        const promisePostByUser = admin.database().ref('/posts_by_user/' + authorUUID + '/' + postUUID).set(postDate);
        const promiseCommunityPostsCount = admin.database().ref('/communities/' + communityUUID + '/posts_count').transaction(
            (posts_value) => {
                return posts_value + 1;
            }
        );
        return Promise.all([promisePostByCommunity, promisePostByUser, promiseCommunityPostsCount]);
    });

I am simply asking if this transaction will prevent assigning wrong value, if for example 10 users are creating posts in the exact same time, which is going to happen if I use typical .once value => .set ?
EDIT: Finally managed to test it without breaking anything and the code above works perfectly fine.

A. Newbie
  • 187
  • 1
  • 3
  • 17
  • 1
    Transactions will retry the operation if another user is concurrently modifying the same data. See my answers on how they work [here](https://stackoverflow.com/questions/35818946/firebase-runtransaction-not-working-mutabledata-is-null/35819073#35819073) and [here](https://stackoverflow.com/questions/57130534/firebase-realtime-database-transaction-handler-gets-called-twice-most-of-the-tim/57134276#57134276). – Frank van Puffelen Aug 05 '19 at 14:37

1 Answers1

1

I'm not too familiar with Firebase, but it looks like Transactions will do exactly what you want out of the box. The description for this seems to directly answer your question

The update function takes the current state of the data as an argument and returns the new desired state you would like to write. If another client writes to the location before your new value is successfully written, your update function is called again with the new current value, and the write is retried.

documentation: https://firebase.google.com/docs/database/web/read-and-write#save_data_as_transactions

gar.stauffer
  • 137
  • 7
  • As far sa I can see this is the correct syntax, but do I return it as part of the promises array (the way it is now)? – A. Newbie Aug 05 '19 at 22:17
  • @A.Newbie ah I think I mis understood your original question. I do not think you want to return an array of promises, it seems that you should only return a single, non-null CloudFunction (https://firebase.google.com/docs/reference/functions/functions.database.RefBuilder#onWrite). In this case, it seems that you would actually want to return a batch from your db trigger. – gar.stauffer Aug 06 '19 at 01:05
  • Shouldn't I just call .then() after the transaction and inside call Promise.all() without this promiseCommunityPostsCount? – A. Newbie Aug 06 '19 at 09:17
  • Thanks mate, I finally managed to test everything without breaking my data xD The way I've done it is perfectly fine. I am going to mark your answer as the corrent answer because you were helful and update my question. – A. Newbie Aug 06 '19 at 10:12