2

I have created a background job to run every minute. The purpose of it is to delete old or outdated data within the database. In this case, the user submits a time which has an attached timestamp to it, and the two values are stored in arrays times and timestamp. So I wrote my cloud code to check if the times are older than an hour via their timestamps. If so, delete them from the database. However, that's the part I'm having trouble with. Here's my cloud code so you can see what's going on:

Parse.Cloud.job("expireTimes", function(request, response){
Parse.Cloud.useMasterKey();
var currentTime = new Date().getTime() / 1000;
var query = new Parse.Query("Wait");
query.find().then(function(results) {
    var times = (results.length>0)? results[0].get("times") : "n/a";
    var timestamps = (results.length>0)? results[0].get("timestamp") : "n/a";
    console.log("Got " + results.length + " Times: " + times);
    console.log("Got " + results.length + " Timestamps: " + timestamps);
    for (var i = 0; i < timestamps.length; i++) {
        if (currentTime >= timestamps[i] + 3600) {
            // Delete old wait times
            timestamps.splice(i, 1);
            times.splice(i, 1);
            i--;
        } else {
            break;
        }
    };

    response.success("success");
}, function(error) {
    response.error(error);
});
})

How do I update the database and delete the values within the array. Because when a user submits the time, it just adds to the times array. Well, if I have the background job going every minute, some entries aren't going to be over an hour old. I want to keep those, but get rid of the other ones.

Any ideas? Any help is much appreciated. Thank you

2 Answers 2

0

The essential part of the answer is that object properties can be set with set() and objects are saved with save(). Here's a quick example of just that...

    // say object is some object that's been retrieved from the database
    var times = object.get("times");
    var timestamps = object.get("timestamp");  // would be better to make the array name plural in the database

    // do whatever you want to the arrays here, then ...

    object.set("times", times);
    object.set("timestamp", timestamps);
    return results[0].save();
}).then(function(result) {
        response.success("success");
}, function(error) {
        response.error(error);
});

But I understand you really want to do this for many Wait objects, so we're going to need a stronger design. Let's start getting into the habit of building functions that do logical chunks of work. Here's one that fixes those arrays for a given Wait object...

// delete parts of the waitObject time arrays prior to currentTime
function removeOldWaitTimes(waitObject, currentTime) {
    var times = waitObject.get("times");
    var timestamps = waitObject.get("timestamp");
    for (var i = 0; i < timestamps.length; i++) {
        if (currentTime >= timestamps[i] + 3600) {
            // Delete old wait times
            timestamps.splice(i, 1);
            times.splice(i, 1);
            i--;
        } else {
            break;
        }
    };
    waitObject.set("times", times);
    waitObject.set("timestamp", timestamps);
}

We need to call this in a loop, for each Wait object found. When we're done, we need to save all of the objects that were changed...

Parse.Cloud.job("expireTimes", function(request, response){
    Parse.Cloud.useMasterKey();
    var currentTime = new Date().getTime() / 1000;
    var query = new Parse.Query("Wait");
    query.find().then(function(results) {
        for (var i=0; i<results.length; i++) {
            removeOldWaitTimes(results[i], currentTime);
        }
        return Parse.Object.saveAll(results);
    }).then(function(result) {
        response.success("success");
    }, function(error) {
        response.error(error);
    });
});

Please note that as the number of objects in the Wait class grows large, the job might get too long or the query (which can be set to a max limit of 1k objects returned) might miss results. We'll need to improve the query if that becomes a risk. (e.g. if the job runs every hour, there's no reason to retrieve Wait objects that were updated more than an hour ago).

EDIT say you want to update some as above, and destroy others. You'll need to handle two promises to do that...

Parse.Cloud.job("expireTimes", function(request, response){
    Parse.Cloud.useMasterKey();
    var destroyThese = [];
    var currentTime = new Date().getTime() / 1000;
    var query = new Parse.Query("Wait");
    query.find().then(function(results) {
        var updateThese = [];
        for (var i=0; i<results.length; i++) {
            var result = results[i];
            if (result.get("times").length > 0) {
                removeOldWaitTimes(result, currentTime);
                updateThese.push(result);
            } else {
                destroyThese.push(result);
            }
        }
        return Parse.Object.saveAll(updateThese);
    }).then(function(result) {
        return Parse.Object.destroyAll(destroyThese);
    }).then(function(result) {
        response.success("success");
    }, function(error) {
        response.error(error);
    });
});

We place destroyThese array in the enclosing scope so that it is available to the next step in the chain of promises.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you so much for doing this for me. I really appreciate it so much. Is there a way that we can check in the delete function if the array is empty to just delete the whole object? Or should I create another background function that just checks if the times array is empty and if so, delete the whole object?
You may also delete a batch at a time with destroyAll(), but these will be two asynch operations, and we'll need a little more sophistication to do that properly. I'll try to answer in an edit...
Okay, thank you so much! This has helped me so much!
A quick peek at the docs says that Parse.Object.saveAll does not return a promise... (they may be outdated) quickfix : gist.github.com/hhanesand/b809d6f1d438174e2d91
@lightice11 - saveAll() returns a promise. Error of omission in the docs. The gist looks right but unnecessary.
|
0

Currently, i didn't find the best solution, but it's working for me now.

var Progress = Parse.Object.extend(PROGRESS);
var progressQuery = new Parse.Query(Progress);
progressQuery.equalTo("userId", userId)
progressQuery.find({
    success: function (progress){
        for (i = 0; i < progress.length; i++){
            progress[i].set("lastUse", false)
            progress[i].save()
        }

    },
    error: function(object, error) {
        console.log(error)
    }
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.