Skip to content

Why afterSave trigger is run asynchronously of the RestWrite.execute flow? #2489

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
cipiripper opened this issue Aug 9, 2016 · 9 comments
Closed

Comments

@cipiripper
Copy link
Contributor

Issue Description

We are migrating app from api.parse.com. In cloud code we have afterSave triggers on all classes, where we set ACL, and other stuff.

When we save a Class object, and when save() is done, we direct user to URL of that object in form of http://server/OBJECT_ID. On parse.com - this works. When object.save() is completed, triggers that set ACL are completed as well, and user can open that URL.

On parse-server, this is not the case. When user is navigated to URL, he gets an error. And if we set timeout like 2sec before navigating user to newly created object, and after save completes, URL works!

We cannot use beforeSave because we need ID of the object being created.

Steps to reproduce

  1. Create afterSave trigger on a Class that sets public read ACL on an object in cloud code
  2. Create an instance using Parse API, with restricted access ACL
  3. Save instance, and when it saves, try to fetch it

Expected Results

User should see his object, because afterSave should set public read ACL when save() is called by user.

Actual Outcome

User gets an error, because ACL is restricted.
If user tries again in 2 sec, he will see this object, because by now afterSave has completed.

Problematic Code (workaround)

So THIS LINE is the root of my problems... I had to return the promise maybeRunTrigger returns, this chained afterSave promise, and made it sync with RestWrite.execute. I also had to accept response in afterSave trigger and call response.success and response.error to resolve a promise...

But I guess this is not a parse thing to do because declaration of afterSave trigger has to change... :)

@flovilmart
Copy link
Contributor

This problem is due to to an architectural change. Initially parse.com was written in GO with a v8 engine spawn at each request. The go web app would likely wait for the execution to terminate and spin out the response at that moment.

Here we're only in JS, so there is no way to wait for the execution of a function to be completed the same way without introducing callbacks (like you did).

We have 2 obvious options here:

  1. introduce the response callback in afterSave, afterDelete
  2. run the cloudCode functions/hooks inside a separate process/vm, for each hook.

Not sure what the best approach is here. @drew-gross, @nlutsenko what do you think?

@drew-gross
Copy link
Contributor

Probably we need to wait for the after save before returning the response to the client, if that's what api.parse.com does. It's possible that that's not what it does, though, and it just happened to be fast enough, while parse-server isn't. Doing the ACL modification in beforeSave should work as well though.

@flovilmart
Copy link
Contributor

Problem is that we don't expose callbacks in afterSave. I suspect in parse.com the afterSave was run and waiting for the vm process to terminate no?

@drew-gross
Copy link
Contributor

True. Not sure what we can do about that. We could start exposing "done" callbacks, and only require that they be called if they are used or if the afterSave opts in some other way. Jest/Jasmine/Mocha/etc. pull this off by using the length property of the function. A bit janky, but it would work. Or we could just tell everyone to move their afterSave logic that needs to be completed before the next fetch to their beforeSave.

@flovilmart
Copy link
Contributor

done callback seem OK, check if it returns a promise too can work too. It's possible some users have a bad function signature (function(req, res) {}) and would never call done therefore blocking the whole thing.

The Promise return seems to be the safest at the moment.

@flovilmart
Copy link
Contributor

flovilmart commented Aug 9, 2016

@cipiripper as you started the workaround can you open a PR with the proposed fix?

which is:

if the afterSave/afterDelete function returns a promise, 
wait for the promise to return the response, the promise can resolve or reject, 
that should not affect the outcome of the save operation (it should succeed both ways)

@cipiripper
Copy link
Contributor Author

@flovilmart Sure.

@cipiripper
Copy link
Contributor Author

PR: #2499

flovilmart pushed a commit that referenced this issue Aug 17, 2016
* Implemented syncing afterSave/afterDelete trigger calls with REST request execution flow (Issue 2489). After this change, afterSave and afterDelete triggers CAN return a promise, which needs to be resolved inside a trigger for REST request flow to continue. If trigger doesn't return a promise, request flow continues.

* Added {} to multiline if.

* Fixed bad commit.

* Fixed problem with beforeSave triggers becoming async.
caoer added a commit to caoer/parse-server that referenced this issue Aug 29, 2016
* ParsePlatform/master: (100 commits)
  Only allow basic auth credentials with a known appId (parse-community#2574)
  vk.com provider registered (parse-community#2579)
  chore(package): update parse-server-push-adapter to version 1.1.0 (parse-community#2588)
  vk.com auth data manager implemented (parse-community#2578)
  Fix a typo (parse-community#2563)
  Makes sure routes don't overlap and yield a header set error (parse-community#2559)
  Postgres: $all, $and CLP and more (parse-community#2551)
  Changelog 2.2.18 (parse-community#2558)
  chore(package): update winston-daily-rotate-file to version 1.3.0 (parse-community#2547)
  chore(package): update parse-server-s3-adapter to version 1.0.5 (parse-community#2536)
  Adds bcrypt native binding for better login performance (parse-community#2549)
  chore(package): update mongodb to version 2.2.7 (parse-community#2554)
  Make parse-server cloud code logging closer parse.com legacy (parse-community#2550)
  chore(package): update pg-promise to version 5.3.1 (parse-community#2519)
  Postgres: Operations, Hooks, OAuth login, Files support (parse-community#2528)
  Syncing afterSave/afterDelete trigger calls (Issue parse-community#2489) (parse-community#2499)
  Updated README.md (parse-community#2538)
  Fix capitalization, typo, and grammar mistake (parse-community#2533)
  Update ISSUE_TEMPLATE.md
  fix typo (parse-community#2525)
  ...
@flovilmart
Copy link
Contributor

Closed as resolved by #2499

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants