Skip to content

Add index and count properties to beforeSave and afterSave hooks #5667

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
stevestencil opened this issue Jun 11, 2019 · 12 comments
Closed

Add index and count properties to beforeSave and afterSave hooks #5667

stevestencil opened this issue Jun 11, 2019 · 12 comments
Labels
type:feature New feature or improvement of existing feature

Comments

@stevestencil
Copy link
Contributor

Is your feature request related to a problem? Please describe.
When saving a bunch of objects at once (i.e. Parse.Object.saveAll()), It would be nice to be able to run a beforeSave or afterSave hook once for all objects.

Describe the solution you'd like
It would nice to have additional properties on the request argument like objectCount and index where objectCount would represent the number of objects that were saved and index would be the index of the current object that is calling the beforeSave hook. You could then use these two properties to check if the object is first index, last index, etc.

Describe alternatives you've considered
Another option would be to create a beforeSaveAll and afterSaveAll function that would be called once before all objects are saved and it would pass in the array of objects. We could then manipulate all objects at once in the beforeSave without having to make a callout for each object.

Additional context
I would be happy to try and tackle this feature if you point me in the right direction on where to start and any feedback on ways to make it better.

@acinader
Copy link
Contributor

@stevestencil I'm curious why you would want this feature?

@stevestencil
Copy link
Contributor Author

Let’s say I have a collection of 1000 objects that the client app needs to download and store locally in order to work offline. Anytime any one of those 1000 objects change or another is added or deleted, I need the client to download all objects again. In the beforeSave of these objects I am incrementing a “version” property of an object in a different class. The app will then check this version with the version that was stored the last time it was downloaded and if it’s different it will redownload all objects again. The issue with this is if I call saveAll on 1000 objects, then I’m querying the database and incrementing the “version” property once for each object. If I had a count and index property in the beforeSave hooks, I could check if it’s the first or last object being saved and then only perform the query/increment once. I hope this makes sense?

Basically I want to query the database and update an object only once when using the saveAll function no matter if I’m saving 1 object or 1000.

@dplewis
Copy link
Member

dplewis commented Jun 12, 2019

Can't you use liveQuery to check if an object has changed?

@stevestencil
Copy link
Contributor Author

using liveQuery will not get me around calling the same function once for each of the 1000 objects that are being saved in the beforeSave hook... I want to do a check to see if it's the last object in the batch and then call a function once for the entire batch of objects. In the beforeSave I have to query the database 2-3 times to update an object anytime something in a specific class changes... if it's a batch save then I only need to make this change once, not 1000 times (one for each object).

@dplewis
Copy link
Member

dplewis commented Jun 12, 2019

Add index and count properties to beforeSave and afterSave hooks

Since the hooks fire off at random times (saveAll isn't parallel), this might be difficult

beforeSaveAll and afterSaveAll

saveAll uses both /batch and /classes router. The batch endpoint is from your client taking your 1000 objects and breaks it up into multiple calls of 20 objects per call (or what your batchSize is set too). So a beforeSaveAll would be triggered multiple times for 1 saveAll call.

If you want to dig around the code

batch
ClassesRouter
Triggers

@acinader
Copy link
Contributor

I've been thinking about your use case and I can't come up with a more clever solution than what you propose.

If index and count or something like that can be added to request or request.context without a performance hit, I think it would be a useful improvement and would be glad to review it and work with you on implementation.

It'd need to be covered by tests and ideally documented with some example code.

PS @dplewis please don't let me discourage you from coming up with a more clever solution ;)

@stevestencil
Copy link
Contributor Author

If I could get the index and count on the request then I can accomplish what I'm trying to do. I have been digging through the code trying to understand how everything works under the hood so I can see if this is an easy add. If you @acinader or @dplewis point me in the right direction to add these two values I'd be more than happy to give it a shot.

@stevestencil
Copy link
Contributor Author

stevestencil commented Jun 12, 2019

part of the reason of me trying to implement this is because the cloud code does not access the database directly. So when you query for a specific object in the database in the beforeSave (or afterSave) it makes a callout once for each object. So if you save say 10,000 objects at once, then the number of request to the server spike drastically. By adding this index and count property, we can cut down on the number of callouts that are made when you only need to do it once per batch save, instead of per object and gain a lot of performance. If I'm missing something here please let me know.

@dplewis
Copy link
Member

dplewis commented Jun 12, 2019

@stevestencil Feel free to open a PR, we'll be glad to review it. You can add those properties here.

@stevestencil
Copy link
Contributor Author

Ok I have been looking into the code and I get to the RestWrite.js which calls this.runBeforeSaveTrigger but I cannot figure out how this is being called for each object that's being saved. Somewhere there should be a loop that calls the beforeSave trigger once for each object?

@dplewis
Copy link
Member

dplewis commented Jun 12, 2019

You might want to check batch.js. You can check my previous comments if that helps.

@stale
Copy link

stale bot commented Aug 20, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Aug 20, 2019
@stale stale bot closed this as completed Aug 27, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:feature New feature or improvement of existing feature
Projects
None yet
Development

No branches or pull requests

4 participants