Parse dot com destroy all userdata from parse database - javascript

I want to set up my custom code in cloud code of parse.
Parse.Cloud.job("deleteUser", function(request, status) {
const query = new Parse.Query("SegmentData");
query.equalTo("userID", request.userID);
query.find()
.then(Parse.Object.destroyAll)
.catch(function(error) {
console.error("Error finding related comments " + error.code + ": " + error.message);
});
const query2 = new Parse.Query("ShowData");
query.equalTo("userID", request.userID);
query.find()
.then(Parse.Object.destroyAll)
.catch(function(error) {
console.error("Error finding related comments " + error.code + ": " + error.message);
});
});
This is the code I have written so far. I want to destroy all the users that have username. They can be even more than 1000. Will this work if the users have more than 1000 records or do I have to amend my code?

With the parse-server the limit of each query is 100 you need to set to
query.limit(1000);
If you want to have 1000 users maximum
You can see here how parse-server test and set the limit of each query:
https://github.com/parse-community/parse-server/blob/master/spec/ParseAPI.spec.js#L314
https://github.com/parse-community/parse-server/blob/master/src/Routers/ClassesRouter.js#L29

Related

How to get all columns from a Parse platform class

I am trying to get all columns from a class in a Parse platform using cloud code that returns a list/array of all the names of the columns.
I am looking at the schema section of the documentation, but I can't find how to get the column's names, only adding, deleting, ...
However, I found this method, but I haven't figured out how to use it neither found any example.
This is what I have right now (doesn't work, neither is the only thing I tried, but hopefully it can help you understand my situation):
Parse.Cloud.define("getAllProperties", async (request) => {
var mySchema;
try {
mySchema = new Parse.Schema('Entry');
} catch (error) {
console.error("ERROR " + error.code + ': ' + error.message);
return error;
}
console.log("CloudFunction 'getAllProperties' executed successfully.");
return mySchema.toString();
});
I found a way to do it:
Parse.Cloud.define("getAllProperties", async (request) => {
var mySchema;
try {
mySchema = new Parse.Schema('Entry');
mySchema = await mySchema.get()
} catch (error) {
console.error("ERROR " + error.code + ': ' + error.message);
return error;
}
console.log("CloudFunction 'getAllProperties' executed successfully.");
return JSON.stringify(mySchema);
});

Firebase cloud functions: "Unhandled error RangeError: Maximum call stack size exceeded"

I have a cloud function that uses firebase and after I call it from my angular app I get the mentioned above error:
Unhandled error RangeError: Maximum call stack size exceeded
at baseKeys (/workspace/node_modules/lodash/lodash.js:3483:12)
at keys (/workspace/node_modules/lodash/lodash.js:13333:60)
at /workspace/node_modules/lodash/lodash.js:4920:21
at baseForOwn (/workspace/node_modules/lodash/lodash.js:2990:24)
at Function.mapValues (/workspace/node_modules/lodash/lodash.js:13426:7)
at encode (/workspace/node_modules/firebase-functions/lib/providers/https.js:184:18)
at /workspace/node_modules/lodash/lodash.js:13427:38
at /workspace/node_modules/lodash/lodash.js:4925:15
at baseForOwn (/workspace/node_modules/lodash/lodash.js:2990:24)
at Function.mapValues (/workspace/node_modules/lodash/lodash.js:13426:7
I've searched stack to find solutions - but in most cases there was serialization problem, that I believe DOES NOT happen here.
Here is my function:
exports.createCase = functions.region('europe-west2').https.onCall((data, context) => {
console.log("creating new case");
if (!context.auth) {
throw new functions.https.HttpsError('failed-precondition', 'This function must be called ' +
'while authenticated.');
}
const caseName = data.caseName;
// Authentication / user information is automatically added to the request.
const uid = context.auth.uid;
const name = context.auth.token.name || null;
const picture = context.auth.token.picture || null;
const email = context.auth.token.email || null;
console.log("caseName=" + caseName + " uid=" + uid + " name=" + name + " picture=" +
picture + " email=" + email);
var operationResult = new Promise ((resolve, reject) => {
var accessData : any = {};
var accessId = admin.database().ref('/access/').push();
var operationId = admin.database().ref('/operationslog/' + accessId.key + '/').push();
console.log("accessId created=" + accessId + ' || ' + accessId.key + ' operations id=' +
operationId + ' || ' + operationId.key);
let now: number = Date.now();
accessData[`/access/` + accessId.key] = new Access(caseName, uid, email);
accessData[`/operationslog/` + accessId.key + `/` + operationId.key] = {
date: now,
performedByUser: uid,
performedByMail: email,
performedByImg: picture,
performedBySystem: false,
operationType: 'CREATE',
order: (REVERSE_ORDER_MAX - now),
details: {creator: uid, name: caseName}
};
console.log('commiting data');
admin.database().ref().update(accessData).then( (value: void) => {
console.log("returning ok result");
resolve({
status: "Ok",
accessId: accessId,
description: 'Case created'
});
}, err => {
console.log("Error while trying to create case: " + err);
reject("CASE NOT CREATED");
}
).catch(exception => {
console.log("Error while trying to create case: " + exception);
reject("CASE NOT CREATED");
}
);
}
);
return operationResult;
});
and the call from Angular app:
let createCaseCall = functions.httpsCallable('createCase');
createCaseCall({caseName: value.caseName}).then(result => {
// Read result of the Cloud Function.
console.log("got result: " + result);
if (result.data.status == 'Ok') {
this.showSuccessMessage('Case created.');
}
}).catch(err => {
console.log("Error while calling cloud functions: " + err);
this.showErrorMessage('Error while creating the case.');
});
Now, the important information is that, the data in firebase realtime database IS CREATED when this function is called and console log does contain "returning ok result" line...
It is still a serialization problem.
Here's what you're trying to send back to the client:
resolve({
status: "Ok",
accessId: accessId,
description: 'Case created'
});
accessId is the result of a push operation:
var accessId = admin.database().ref('/access/').push();
That means it's a DatabaseReference object, which contains circular references that can't be serialized. It's not a simple data type, like a string.
You'll want to think more carefully about what you want exactly you want to send back to the client app. Maybe you wanted to send back the name or path of the child key that was created by push()?
Also, you'll probably want to remove the whole new Promise() thing, as that's an anti-pattern here. There is no need to create a new promise when you have promises from all the other database operations available to work with.

Using promises in Geofire

The Geofire documentation says that Geofire returns promises when reading and writing data but I cannot seem to find any examples of this. I was wondering how I could use this in javascript to attach a function onto the end of the listener that fired when the geofire promise is fulfilled. My code is:
var onKeyEnteredRegistration = this.geoQuery.on("key_entered", function(key, location, distance) {
console.log(key + " entered query at " + location + " (" + distance + " km from center)");
}).then(function(result){
console.log("promise resolved with:" + result);
}, function(error){
console.error(error)
});
But this is outputting an error saying 'undefined is not a function' referencing the chained function. Does anyone know how to use promises in Geofire?
Thanks
So only the get, set and remove functions on the GeoFire class return promises. Like so:
geoFire.get("some_key").then(function(location) {
if (location === null) {
console.log("Provided key is not in GeoFire");
}
else {
console.log("Provided key has a location of " + location);
}
}, function(error) {
console.log("Error: " + error);
});
However the on function instead returns a GeoQuery whose on function returns a GeoCallbackRegistration which is used to kill the query with the cancel function (which does not return anything.)
var onKeyEnteredRegistration = this.geoQuery.on("key_entered", function(key, location, distance) {
console.log(key + " entered query at " + location + " (" + distance + " km from center)");
});
onKeyEnteredRegistration.cancel(); // the "key_entered" event will stop firing

azure custom apis: performing database transaction returns a timeout

On a azure custom api, I'm attempting to perform bulk insert operation to three tables utilising database transctions.Then I'm facing this error on the console.
The request 'POST /api/saveinvite' has timed out. This could be caused by a script that fails to write to the response, or otherwise fails to return from an asynchronous call in a timely manner.
exports.post = function (request, response) {
console.log("save invite executed!!");
var jsonfriendcircle = request.body.jsonfriendcircle;
var jsoninviteelist = request.body.jsoninviteelist;
var jsoninviteefriendcirclelist = request.body.jsoninviteefriendcirclelist;
console.log("Circle is :" + jsonfriendcircle);
console.log("Inviteelist is :" + jsoninviteelist);
console.log("Inviteefriendcirclelist is :" + jsoninviteefriendcirclelist);
var parsedjsfrcircle = JSON.parse(jsonfriendcircle);
var mssql = request.service.mssql;
console.log("mssql obj :" + mssql);
mssql.open({
success: function (connection) {
console.log("connection to db success");
console.log("circle id: " + parsedjsfrcircle["id"]);
console.log("circle name :" + parsedjsfrcircle["circle_name"]);
var sqlst1 = 'insert into friendcircle (id,circle_name)values(?,?)';
connection.query(sqlst1, [parsedjsfrcircle["id"], parsedjsfrcircle["circle_name"]], function (err, results) {
if (err) {
console.log("Error:" + err);
connection.rollback();
response.send(statusCodes.Error, { message: '' });
connection.close();
return;
} else {
// connection.commit();
// connection.close();
}
});
}
, error: function (err) {
console.log("Unable to connect to DB :" + err);
response.send(statusCodes.Error, { message: err });
}
});
};
It doesn't look like your trying to do too much. Inserting a few hundred rows should come back before the timeout.
You'll get a timeout if there is permissions issues with the Mobile Services user on the database table and your transaction and custom error handling may be hiding that. Ensure you've run a
GRANT SELECT, INSERT, UPDATE ON OBJECT::[dbo].[Invitee_FriendCircle] TO [Created_MobileServicesLogin_User]
--For whatever name was created when you made the app (not the name you entered when you created the app, but the wacky one that mobile services made)
Some things to try:
Ensure the tables you are inserting to are indexed for the type of insert you're doing. If it's a huge table and indexing is an issue, let the mobile api insert to a small temp table and then run an asynch job with sp_start_job to update the main table with the temp table. That way you are not waiting while the table does the update.
Write stored procedures in the database that contain the inserts and pass the variables into them instead of writing the INSERT query here. Inside the sproc you can also do BULK INSERT if you really are passing a lot of values and need to do it quick.
Modify the ConnectionTimeout property in the connection string to your database.
You can modify the request.service.config.sqlConnectionString.
Try stripping it down to find the problem. Remove the transaction and just try doing it without the transaction and custom error handlers, on just one table at a time. Try
exports.post = function(request, response) {
var jsonfriendcircle=request.body.jsonfriendcircle;
var jsoninviteelist=request.body.jsoninviteelist;
var jsoninviteefriendcirclelist=request.body.jsoninviteefriendcirclelist;
var mssql=request.service.mssql;
var sqlst1='insert into FriendCircle (id,circle_name)values(?,?)' ;
mssql.query(sqlst1,[jsonfriendcircle.id,jsonfriendcircle.circle_name], {
success: function(results) {
response.send(statusCodes.OK, { message : 'success' });
},
error: function(err) {
console.log("error is: " + err);
}
});
};
Try them one at a time to see if anything fails, and if it does, check the LOGS on the Azure portal to see if it was a permission issue.
Good Luck!
Probably a transaction timeout after 30 seconds?
In SQL What is the default max transaction timeout
Try to rewrite the insert into multiple smaller transactions

Destroying objects from Parse Cloud is unreliable

I'm trying to delete all objects in a class, but whenever I attempt to delete objects from a cloud function or job I get an inconsistent number of objects left over. The jobs always take under second, so I don't think that's the issue (working with under 100 objects anyway). I seem to always have a random number of objects left over and no errors. This is what I'm working with now.
Parse.Cloud.job("deletePosts", function(request, status) {
Parse.Cloud.useMasterKey();
var query = new Parse.Query("Posts");
query.find({
success: function(results) {
Parse.Object.destroyAll(results).then(function() {
console.log("Delete job completed.");
status.success("Delete job completed.");
});
},
error: function(error) {
console.log("Error in delete query error: " + error);
status.error("Error in delete query error: " + error);
}
});
});
When deleting objects in cloud code, use query.each instead of query.find to ensure that you delete all objects matching the query .
find has the query limitation of 100 objects returned by default (or up to 1000 if limit is used). Source
Below is an example of using a promise chain which calls destroy on each Post object. When all of the destroy promises have completed, the success status will be reached, and if any of the destroys fail then the error status will be reached.
Parse.Cloud.job("deletePosts", function(request, status) {
Parse.Cloud.useMasterKey();
var query = new Parse.Query("Posts");
query.each(function(post) {
return post.destroy();
}).then(function() {
console.log("Delete job completed.");
status.success("Delete job completed.");
}, function(error) {
alert("Error: " + error.code + " " + error.message);
status.error("Error: " + error.code + " " + error.message);
});
});

Categories

Resources