Search code examples
javascriptherokuparse-platformparse-serverparse-cloud-code

Parse Server populating and updating a column automatically with cloud code


I have a class called Stats which contains the columns secondsPlayed (number), createdAt (date) and timeScore (number)

This class contains thousands of objects but the timeScore column is empty.

I want to populate the timeScore column with a formula using the columns secondsPlayed (number), createdAt (date) like you would do in Excel. The formula is:

(secondsPlayed*10^8)/(Date.now()-createdAt.getTime())

As you can see the values of the timeScore column should change every second since Date.now() and secondsPlayed are variables that are constantly changing.

Because of this I want to update and repopulate the timeScore column every 5 minutes. This should happen automatically.

What is the best way to do this? I figured using cloud code to compute and populate the timeScore column and then just get the timeScore list with a simple Parse query would be best compared to downloading thousands of objects to each device and computing and updating every 5 minutes client side.

I dont know much about writing cloud code but by reading this guide and this SO question I came up with the following code.

const _ = require("underscore");
Parse.Cloud.define("timeScore", function(request, response) {
  const query = new Parse.Query("Stats");
  const maxSeconds = (Date.now() - new Date('2017-12-12T06:00:04.022Z').getTime())/1000;
  query.lessThan("secondsPlayed", maxSeconds);
  query.find().then(function(results) => {
        _.each(results, function(result) {
            var secondsPlayed = result.get("secondsPlayed") || 0;
            var createdAt = result.get("createdAt") || new Date('2017-12-12T06:00:04.022Z');
            result.set("timeScore", (secondsPlayed*100000000)/(Date.now()-createdAt.getTime()));
      });
        return Parse.Object.saveAll(results);
    }).then(function(results) {
        response.success(results);
    }, function(error) {
        response.error(error);
    })
    .catch(() =>  {
      response.error("FAILED");
    });
});

I do not know what to do with this code. I dont know how to test it or if it even works. How should I proceed?

Do I need to call it from the xamarin app? I just need the column to be populated and updated every 5 minutes according to the code. I should not need to call the cloud code from the app. I just want to query the timeScore column from the app. Is this possible?


Solution

  • To test from a .net client, ParseCloud provides CallFunctionAsync. See the guide for an example here.

    At least one problem you'll find with the code is that query will return 1k objects maximum, so the query/update/save logic will have to cursor through the Stats objects each time this runs.

    Once tested, you'll need to create a web worker which Heroku will let you schedule. See their guide about that here.

    But I'm reluctant to go into further detail on any of these points, because I disagree with a premise of the question: that this update should be done, or done recurrently.

    Consider that running this code adds no new information to the system. The createdAt field remains fixed. All that this code does is produce a strange way of representing the current time (as a createdAt time and an interval since then) thousands of times per run. This is exactly the sort of thing that should be done only when that interval (now - createdAt) needs to be known for a given object.