0
votes

I'm using Parse cloud code to update some counters on a user in beforeSave/afterDelete on certain classes. A user has a counter that keeps track of the number of their subscriptions. The subscription class is a relation class between a user and another class. The user subscription count is updated in subscription beforeSave and afterDelete.

Parse.Cloud.beforeSave("Subscription", function(request, response) {
    var fromUserPointer = subscription.get("fromUser");

    fromUserPointer.fetch().then(function(user){

        var subscriptionCount = user.get("subscriptionCount");

        console.log( subscriptionCount + 1);
        user.set("subscriptionCount", subscriptionCount + 1);
        return user.save();
    });
});

On the client iPhone app a user is able to navigate through a tableView and rapidly create subscription objects. Unfortunately, it appears that the above code is not able to keep up. It seems that if the subscriptions are added too quickly, the line var subscriptionCount = user.get("subscriptionCount"); gets called before the previous before_save saves the user, and we end up with a stale subscription count.

Below is a sample of the console output that demonstrates this:

I2015-02-17T23:10:14.972Z] v268: before_save triggered for Subscription for user NHl80OFkKm
  Input: {...}
  Result: {...}
I2015-02-17T23:10:15.022Z] v268: before_save triggered for Subscription for user NHl80OFkKm
  Input: {...}
  Result: {...}
I2015-02-17T23:10:15.073Z] v268: before_save triggered for Subscription for user NHl80OFkKm
  Input: {...}
  Result: {...}
I2015-02-17T23:10:15.145Z] 1
I2015-02-17T23:10:15.224Z] v268: before_save triggered for _User for user NHl80OFkKm
  Input: { ... "update":{"subscriptionCount":1}}
  Result: Update changed to {"followersCount":0,"followingCount":0,"subscriptionCount":1}
I2015-02-17T23:10:15.244Z] 1
I2015-02-17T23:10:15.257Z] 1
I2015-02-17T23:10:15.276Z] v268: before_save triggered for _User for user NHl80OFkKm
  Input: { ... "update":{"subscriptionCount":1}}
  Result: Update changed to {"followingCount":0,"subscriptionCount":1,"followersCount":0}
I2015-02-17T23:10:15.329Z] v268: before_save triggered for _User for user NHl80OFkKm
  Input: { ... "update":{"subscriptionCount":1}}
  Result: Update changed to {"subscriptionCount":1,"followersCount":0,"followingCount":0}
I2015-02-17T23:10:15.576Z] v268: before_save triggered for Subscription for user NHl80OFkKm
  Input: {...}
  Result: {...}
I2015-02-17T23:10:15.611Z] v268: before_save triggered for Subscription for user NHl80OFkKm
  Input: {...}
  Result: ...
I2015-02-17T23:10:15.685Z] v268: before_save triggered for Subscription for user NHl80OFkKm
  Input: {...}
  Result: ...
I2015-02-17T23:10:15.692Z] 2
I2015-02-17T23:10:15.706Z] 2
I2015-02-17T23:10:15.715Z] v268: before_save triggered for _User for user NHl80OFkKm
  Input: { ... "update":{"subscriptionCount":2}}
  Result: Update changed to {"subscriptionCount":2,"followersCount":0,"followingCount":0}
I2015-02-17T23:10:15.732Z] v268: before_save triggered for _User for user NHl80OFkKm
  Input: { ... "update":{"subscriptionCount":2}}
  Result: Update changed to {"followersCount":0,"followingCount":0,"subscriptionCount":2}
I2015-02-17T23:10:15.789Z] 3
I2015-02-17T23:10:15.817Z] v268: before_save triggered for _User for user NHl80OFkKm
  Input: { ... "update":{"subscriptionCount":3}}
  Result: Update changed to {"followersCount":0,"followingCount":0,"subscriptionCount":3}

Same thing is happening in afterDelete. Any idea how I can get around this? The only other option I can think of to accomplish this is a direct query on the subscriptions class, but that is a very inefficient approach.

1

1 Answers

1
votes

I should've perused the documentation a little more. This use case is documented here: https://parse.com/docs/js_guide#objects-updating.

Simply replace user.set("subscriptionCount", subscriptionCount + 1); with user.increment("subscriptionCount", 1);

Increment is an atomic operation.