Parse Cloud Code - Notifcation not working and objects not deleting - javascript

I have a Parse Cloud Code function that will act as my background job. Right now I am in my debugging stage. The function does not throw an error and it is not doing what it is supposed to do. The function entitled "backgroundJob" is supposed to go through all the "Group" objects that have been created. Each "Group" object has an Array of "Event" objects, and all you have to know about the "Event" object is it has a date property called "date".
The function should go through all the events for each group object and if the event's date is the same as the current time the function should send a notification to all "Users" who are apart of that group and then delete that event. Right now the function is not deleting the event if it is the same time as the current time and is not notifying members of the group.
My function is below.
Parse.Cloud.define("backgroundJob", function(request, response) {
Parse.Cloud.useMasterKey();
var moments = require("cloud/moment.js");
moments().format();
var _ = require('cloud/underscore.js');
// Get the actual time, for use in non testing
// var now = moments();
// For testing edit time in ()
var now = moments("2015-23-11 19:30", "YYYY-MM-DD HH:mm");
var out = now;
console.log(out);
var groupObject = Parse.Object.extend("Group");
var query = new Parse.Query(groupObject);
var eventObject = Parse.Object.extend("Event");
query.find().then(function(groups) {
var promise = Parse.Promise.as();
var groupArray = groups;
for (var i = 0; i < groupArray.length; i++) {
promise = promise.then(function() {
var count = 0;
var eventArray = groupArray[i].get("Events");
for (count = 0; count < eventArray.length; count++) {
if (now == eventArray[count].get('date')) {
var curEvent = eventArray[count];
eventArray[count].destory();
var relationc = result.get("created");
var createdq = relationc.query();
var relationj = result.get("created");
var joinedq = relationj.query();
var partOnee = curEvent.get("name");
var outString = partOnee.concat(" is now");
Parse.Push.send({
where : createdq,
data : {
alert : outString
}
}).then(function() {
response.success();
}, function(error) {
response.error(error);
});
Parse.Push.send({
where : joinedq,
data : {
alert : outString
}
}).then(function() {
response.success();
}, function(error) {
response.error(error);
});
var e = eventArray[count];
var destroyp = Parse.Promise.as();
destroyp = promise.then(function() {
return e.destroy();
}, function(error) {
response.error(error);
});
}
}
});
}
}).then(function() {
response.success()
}, function(error) {
response.error(error);
});
});
Thank you.
For reference in the code there are two separate relations to users a "created" and a "joined", this is why in the code I have a created query and a reaction query.

You have a typo in your code. Maybe this is not the cause of the issue, but anyways, check it.
eventArray[count].destory();
Seems silly, but, who knows...

Related

Parse server save data in series

So we have large data in JSON format.
We want to save it to a class (table) in our Parse app.
I wrote a JS script which can read the file and go through the JSON data.
But when is do the saving it all gets messed up. Its loops in the first one for ever. I understand that there is something called promise bt I don't understand how to use it? Can anyone help. My code is given below.
function processJson(result) {
object = JSON.parse(result);
verbose.textContent = "Read " + object.results.length + " objects";
var count = object.results.length;
var countAc = 0;
logger("To save: " + count);
i = 0;
while (i < count) {
if (object.results[i].areaType == 'ac') {
save(i).then(function (object) {
i = i + 1;
logger("Success: " + object.id);
});
} else {
logger("ac not found");
i = i + 1;
}
}
}
function save(i) {
logger("ac found");
var constituency = new Constituency();
constituency.set("points", object.results[i].points);
constituency.set("areaType", object.results[i].areaType);
constituency.set("name", object.results[i].name);
constituency.set("state", object.results[i].state);
constituency.set("index", object.results[i].index);
constituency.set("pc", object.results[i].pc);
constituency.set("center", object.results[i].center);
constituency.set("oldObjectId", object.results[i].objectId);
return constituency.save();
/*constituency.save().then(function(obj) {
// the object was saved successfully.
i = i + 1;
logger("Success: " + obj.id);
}, function(error) {
// the save failed.
logger(error.message);
i = i + 1;
});*/
}
I would do something like that:
function processJson(result) {
var object = JSON.parse(result);
for (var i = 0; i < object.results.legnth; i++){
var parseObject = createParseObjectFromJSONObject(object.results[i]);
parseObject.save(null).then(function(object){
console.log("object saved: " + object.id);
},function(error){
console.log("error: " + error);
});
}
}
function createParseObjectFromJSONObject(jsonObject){
var constituency = new Constituency();
constituency.set("points", jsonObject.points);
constituency.set("areaType", jsonObject.areaType);
constituency.set("name", jsonObject.name);
constituency.set("state", jsonObject.state);
constituency.set("index", jsonObject.index);
constituency.set("pc", jsonObject.pc);
constituency.set("center", jsonObject.center);
constituency.set("oldObjectId", jsonObject.objectId);
return constituency;
}
You can do it even better..
You can first push all the parse objects into array and then call saveAll to save all the parse objects in one request. This solution is good for < 1000 records .. if you have more than 1000 then you can do paging (first 1000 and saveAll, other 1000 and saveAll ....)
In this version your code will look like this:
function processJson(result) {
var object = JSON.parse(result);
var allObjects = [];
for (var i = 0; i < object.results.legnth; i++){
var parseObject = createParseObjectFromJSONObject(object.results[i]);
allObjects.push(parseObject);
}
// outside the loop we are ready to save all the objects in
// allObjects array in one service call!
if (allObjects.length > 0){
Parse.Object.saveAll(allObjects).then(function(){
console.log("all objects were saved!");
// all object ids are now available under the allObjects array..
},function(error){
console.log("error: " + error);
});
}
}
function createParseObjectFromJSONObject(jsonObject){
var constituency = new Constituency();
constituency.set("points", jsonObject.points);
constituency.set("areaType", jsonObject.areaType);
constituency.set("name", jsonObject.name);
constituency.set("state", jsonObject.state);
constituency.set("index", jsonObject.index);
constituency.set("pc", jsonObject.pc);
constituency.set("center", jsonObject.center);
constituency.set("oldObjectId", jsonObject.objectId);
return constituency;
}
Good Luck :)

NodeJS some modules not working

I'm making a game with socket.io and nodejs, and I'm making a module called rooms.js, this module require users.js module and fiveSocket.js module
but when I call Rooms.New from the main server file, it says that fiveSocket is undefined, same problem when Rooms.New calls a users.js function, I got TypeError: Cannot read property 'getSocketIDbyId' of undefined
rooms.js:
var mysql = require('../mysql/mysql.js');
var headers = require('./headers.js');
var users = require('./users.js');
var fiveSocket = require('./sockets.js');
var Rooms = {
Obj: {},
Room: function(data) {
var room = this;
this.name = data.name;
this.users = [];
this.floorCode = data.floor;
this.description = data.desc;
this.maxUsers = data.maxUsers;
this.owner = data.owner;
this.setTime = new Date().getTime();
this.dbID = data.dbID;
this.doorx = data.doorx;
this.doory = data.doory;
this.doordir = data.doordir;
},
New: function(socketID, roomID) {
var keys = Object.keys(Rooms.Obj).length;
var id = keys + 1;
var callback = function(row) {
fiveSocket.emitClient(socketID, headers.roomData, {
title: row.title,
desc: row.description,
mapStr: row.floorCode,
doorx: row.doorx,
doory: row.doory,
doordir: row.doordir
});
var uid = users.getIdBySocketID(socketID);
users.Obj[uid].curRoom = roomID;
var rid = Rooms.getIdByDbID(roomID);
Rooms.Obj[rid].users.push(uid);
}
if(Rooms.getIdByDbID(roomID) != false) {
var room = Rooms.getIdByDbID(roomID);
var row = { title: room.name, description: room.description, floorCode: room.foorCode, doorx: room.doorx, doory: room.doory, doordir: room.doordir };
callback(row);
} else {
mysql.Query('SELECT * FROM rooms WHERE id = ? LIMIT 1', roomID, function(rows) {
if(rows.length > 0) {
var row = rows[0];
Rooms.Obj[id] = new Rooms.Room({name: row.title, floorCode: row.floorCode, desc: row.description, maxUsers: row.maxUsers, owner: row.owner, dbID: row.id, doorx: row.doorx, doory: row.doory, doordir: row.doordir});
callback(row);
}
});
}
},
removeUser: function(DBroomID, userID) {
var rid = Rooms.getIdByDbID(DBroomID);
var room = Rooms.Obj[rid];
var index = room.indexOf(userID);
if (index > -1) array.splice(index, 1);
},
Listener: function(users) {
setInterval(function(){
for(var roomID in Rooms.Obj) {
var room = Rooms.Obj[roomID];
// send users coordinates
room.users.forEach(function(uid) {
var socketID = users.getSocketIDbyId(uid);
var data = Rooms.getUsersInRoomData(roomID);
fiveSocket.emitClient(socketID, headers.roomUsers, data);
});
// unload inactive rooms (no users after 10 seconds)
var activeUsers = room.users.length;
var timestamp = room.setTime;
var t = new Date(); t.setSeconds(t.getSeconds() + 10);
var time2 = t.getTime();
if(activeUsers <= 0 && timestamp < time2) {
Rooms.Remove(roomID);
}
}
}, 1);
},
getUsersInRoomData: function(roomID) {
var room = Rooms.Obj[roomID];
var obj = {};
room.users.forEach(function(uid) {
var user = users.Obj[uid];
obj[uid] = {
username: user.username,
position: user.position,
figure: user.figure
};
});
return obj;
},
Remove: function(id) {
delete Rooms.Obj[id];
},
getIdByDbID: function(dbID) {
var result = null;
for(var room in Rooms.Obj) {
var u = Rooms.Obj[room];
if(u.dbID == dbID) var result = room;
}
if(result == null) return false;
else return result;
},
getDbIDbyId: function(id) {
return Rooms.Obj[id].dbID;
}
}
Rooms.Listener();
module.exports = Rooms;
EDIT: (if it can be helpful)
When I console.log fiveSocket on the main file
When I console.log fiveSocket on the rooms.js file
EDIT2: When I've removed var users = require('./users.js'); from fiveSocket, when I console.log it in rooms.js it works, why ?
EDIT3: I still have the problem
If you need the others modules sources:
Users.JS: http://pastebin.com/Ynq9Qvi7
sockets.JS http://pastebin.com/wpmbKeAA
"Rooms" requires "Users" and vice versa, so you are trying to perform "circular dependency".
Quick search for node.js require circular dependencies gives a lot of stuff, for example :
"Circular Dependencies in modules can be tricky, and hard to debug in
node.js. If module A requires('B') before it has finished setting up
it's exports, and then module B requires('A'), it will get back an
empty object instead what A may have intended to export. It makes
logical sense that if the export of A wasn't setup, requiring it in B
results in an empty export object. All the same, it can be a pain to
debug, and not inherently obvious to developers used to having those
circular dependencies handled automatically. Fortunately, there are
rather simple approaches to resolving the issue."
or
How to deal with cyclic dependencies in Node.js

Variable from for loop always returns 0

I am reasonably new to node.js / sails.js and have run into a problem that I know the answer is simple but I cannot seem to work it out.
My code is as follows
SendCompleted : function(req,res)
{
var updated = 0;
var params = req.params.all();
var dt = JSON.parse(decodeURI(params.id));
var connection = new sql.Connection(testrmis, function (err)
{
if (err) {
}
for(var i = 0; i < dt.length; i++) {
var obj = dt[i];
var request = new sql.Request(connection);
request.stream = true;
request.input('branchid', sql.Int(), obj.branch_id);
request.input('picklistid', sql.Int(), obj.picklist_id);
request.input('scanned',sql.Int(),obj.scanned);
request.input('expected', sql.Int(),obj.expected);
request.input('poscode', sql.VarChar(),obj.poscode);
request.input('label', sql.VarChar(), obj.label);
request.input('dt', sql.VarChar(), obj.dt);
request.execute('WAREHOUSE_InsertPiPackData');
request.on('done', function(returnValue) {
updated = updated + returnValue;
console.log(updated);
});
}
res.send("[{\"ReturnValue\":" + updated + "}]");
});
}
I am sending in 4 lines of results and my console.log(updated) counts up as it should for each line, e.g 1,2,3,4
However the res.send result for updated is always 0.
Could anyone please explain why this is happening? My var updated is outside of my loop and this is getting updated correctly, however when the loop is finished it seems to get reset to 0?
returnValue == ##rowcount from the stored procedure
request is async so
res.send("[{\"ReturnValue\":" + updated + "}]");
gets executed even before you get the callback on request as JS doesn't wait for the callback and executes the next line. What you can do is use a counter and place your res.send inside for loop.
SendCompleted : function(req,res)
{
var updated = 0;
var params = req.params.all();
var dt = JSON.parse(decodeURI(params.id));
var connection = new sql.Connection(testrmis, function (err)
{
if (err) {
}
var count = dt.length;
for(var i = 0; i < dt.length; i++) {
var obj = dt[i];
var request = new sql.Request(connection);
request.stream = true;
request.input('branchid', sql.Int(), obj.branch_id);
request.input('picklistid', sql.Int(), obj.picklist_id);
request.input('scanned',sql.Int(),obj.scanned);
request.input('expected', sql.Int(),obj.expected);
request.input('poscode', sql.VarChar(),obj.poscode);
request.input('label', sql.VarChar(), obj.label);
request.input('dt', sql.VarChar(), obj.dt);
request.execute('WAREHOUSE_InsertPiPackData');
request.on('done', function(returnValue) {
count--;
updated = updated + returnValue;
console.log(updated);
if(count == 0) res.send("[{\"ReturnValue\":" + updated + "}]");
});
}
});
}
Try for this:
May be Async problem:
for(var i = 0; i < dt.length; i++) {
//Your logic
if(i=== dt.length){
res.send("[{\"ReturnValue\":" + updated + "}]");
}
}
This is because at the time you do request.send, the value of updated is not incremented. This is because request.execute is asynchronous and done handler will be invoked after the res.send has been executed.
I would recommend a promise library (example, q). You can combine the promises and then use Q.all to do req.send when all the promises are done.
See more details here

Parse.com: cannot create more than 9 objects using cloud job

I have Cloud Job code like this:
Parse.Cloud.job("createMySpecialObjects", function(request, status) {
var MySpecialObject = Parse.Object.extend("MySpecialObject");
var count = 20 // 20 is greater than 9!
for (var i = 0; i < count; i++) {
var myObject = new MySpecialObject();
myObject.save();
}
status.success("Objects created successfully.");
});
And I have only 9 created objects as result.
I suppose it is connected with 30 API calls per second. But maybe somebody else knows better?
The code snippet below shows how to save multiple objects by using Parse.Object.saveAll.
Parse.Cloud.job("createMySpecialObjects", function(request, status) {
var MySpecialObject = Parse.Object.extend("MySpecialObject");
var count = 20 // 20 is greater than 9!
var toSaves = [];
for (var i = 0; i < count; i++) {
var myObject = new MySpecialObject();
toSaves.push(myObject);
}
Parse.Object.saveAll(toSaves, {
success: function(saveList) {
status.success("Objects created successfully.");
},
error: function(error) {
status.error("Unable to save objects.")
}
}
});

Parse.com Cloud Code, trying to filter query, but query still contains all objects

I'm trying to add unique objects to my parse database, that is, the name property must be different for each object. I try to query for all objects with a given name like so
var query = new Parse.Query(Food);
query.exists("name", name);
query.count({
success: function(number) {....}
However, query.count is always the total number of objects (90) stored on the database, even though there should be 0 or 1 objects with a given name stored.
EDIT:
Following one of the answers, I modified the code to this. However, I still see duplicates in the database.
var query = new Parse.Query(Food);
query.equalTo("name", name);
query.first({
success: function(results) {...}
Below is the entire (edited) function
Parse.Cloud.define("recordFavorite", function(request, response) {
var foodList = request.params.foodList; //string array of food names
var foodListCorrected = new Array();
var Food = Parse.Object.extend("Food");
// Wrap your logic in a function
function process_food(i) {
// Are we done?
if (i == foodList.length) {
//console.log("count is " + foodListCorrected.length);
Parse.Object.saveAll(foodListCorrected, {
success: function(foodListCorrected) {},
error: function(foodListCorrected) {}
});
return;
}
var name = foodList[i];
//console.log("before name is " + name);
var query = new Parse.Query(Food);
query.equalTo("name", name);
query.first({
success: function(results) {
if(!results){
console.log("new");
var food = new Food();
food.set("name", name);
foodListCorrected.push(food);
// console.log(foodListCorrected.length);
} else {
//don't create new food
console.log("exists");
}
process_food(i+1)
},
error: function(error) {
console.log("error");
}
});
}
// Go! Call the function with the first food.
process_food(0);
});
EDIT:
I've tried an alternate approach to this problem using promises, but the line
return Parse.Object.saveAll(foodListCorrected);
does not seem to be executing. I've verified that foodListCorrected is a non-empty array. Below is the entire code for the function.
Parse.Cloud.define("recordFavorite", function(request, response) {
var foodList = request.params.foodList; //string array of food names
var foodListCorrected = new Array();
var Food = Parse.Object.extend("Food");
var query = new Parse.Query(Food);
query.find().then(function(foods) {
for (i = 0; i < foodList.length; i++) {
var j;
for (j = 0; j < foods.length; j++){
if (foodList[i] == foods[j])
break;
}
if (j==foods.length)
foodListCorrected.push(foodList[i]);
}
console.log(foodListCorrected.length);
return Parse.Object.saveAll(foodListCorrected);
}).then(function() {
// Everything is done!
})
});
Try this:
Parse.Cloud.define("recordFavorite", function(request, response) {
var foodList = request.params.foodList; //string array of food names
var saveThese = [];
var FoodClass = Parse.Object.extend("Food");
for(var i = 0; i < foodList.length; ++i){
var food = new FoodClass();
food.set("name", foodList[i]);
saveThese.push(food);
}
Parse.Object.saveAll(saveThese, {
success: function(list){
response.success();
},
error: function(error){
response.error("Failure on saving food");
}
});
});
//If a food already exists in the database, then don't save it
Parse.Cloud.beforeSave("Food", function(request, response){
var query = new Parse.Query("Food");
query.equalTo("name", request.object.get("name"));
query.count({
success: function(count){
if(count > 0)
response.error("Food already exists");
else
response.success();
},
error: function(error){
response.error(error);
}
});
});
The "exists" condition takes in one argument, the name of a key and sees if it exists for a row. So it will return every row where your "name" column has a value, any value. What you're looking for is something like this:
var query = new Parse.Query(Food);
query.equalTo("name", name);
query.first(...)

Categories