Skip to content
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

Guard against exceptions in the setup steps. #73

Merged
merged 3 commits into from
Jul 6, 2015
Merged

Guard against exceptions in the setup steps. #73

merged 3 commits into from
Jul 6, 2015

Conversation

winding-lines
Copy link
Contributor

When there are exceptions in the setup steps (for example needs component missing)
the implementation is not properly capturing those exceptions.
This fix uses the slighlty longer syntax for creating promises which
wraps the call in a function and allows RSVP to properly capture
the exception. When using the shorter RSVP.resolve() form the exception
happens outside (before) the RSVP invocation and cannot be captured.

When there are exceptions in the setup steps (for example needs component missing)
the implementation is not properly capturing those exceptions.
This fix uses the slighlty longer syntax for creating promises which
wraps the call in a function and allows RSVP to properly capture
the exception. When using the shorter RSVP.resolve() form the exception
happens outside (before) the RSVP invocation and cannot be captured.
@@ -107,7 +107,8 @@ export default Klass.extend({
function nextStep() {
var step = steps.shift();
if (step) {
return Ember.RSVP.resolve(step.call(context)).then(nextStep);
// guard against exceptions, for example missing components referenced from needs.
return new Ember.RSVP.Promise(function(ok) {ok(step.call(context));}).then(nextStep);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this just work.

  return Ember.RSVP.resolve(step.call(context)).then(nextStep, function(err) {
   throw err;
  })

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chadhietala your proposal does not work. You can rewrite both the original code and your proposal as the following:

var current = step.call(context); // throws exception, promise code never reached
return Ember.RSVP.resolve(current).then(..)

The call to step.call() will happen before the promise, even though it is written on the same line. With the proposed change the promise is active before the throwing call and can setup a try-catch to catch the exception.

Note that promise.resolve() creates a new function anyways so there is no change in performance or memory allocation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is roughly what I was thinking also (though with .catch instead of two args to .then).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rwjblue a .catch() won't work either. The issue is with capturing the exception and translating it to a rejected promise. The .catch() only changes how that promise is handled later on.

You can play with the following code to better understand what I mean. The commented code is my proposal, the uncommented code is the current approach.

var RSVP = require('rsvp');

function throws() {
  throw Error("a");
}


/*
var promise = new RSVP.Promise(function(resolve, reject) {
  resolve(throws());
});
*/

var promise = RSVP.resolve(throws());

promise.then(function(value) {
  console.log( "then -> " + value );
}, function(value) {
  console.log( "failure -> " + value );
});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use RSVP.resolve().then(function() { return step.call(); })

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rwjblue yes that would also work, however you are 'wasting' a resolve().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya,
makes sense

@rwjblue
Copy link
Member

rwjblue commented Jul 5, 2015

This looks good, can you add a test for this?

@winding-lines
Copy link
Contributor Author

@rwjblue I've added the test. Without the improved exception handling the whole test loop breaks when the new test is hit - it's test 14 below. What we are seeing in production is that the CI builds 'hang'. broken

With the new code the processing continues after test 14. In normal operation the test itself would fail instead of their setup. More importantly for us there is no 'hanging'. working

@winding-lines
Copy link
Contributor Author

Let me know if I should collapse all the commits in one.

rwjblue added a commit that referenced this pull request Jul 6, 2015
Guard against exceptions in the setup steps.
@rwjblue rwjblue merged commit fc75953 into emberjs:master Jul 6, 2015
@rwjblue
Copy link
Member

rwjblue commented Jul 6, 2015

Thanks for your work on this!

@winding-lines
Copy link
Contributor Author

Thanks for merging!

On Jul 6, 2015, at 5:32 AM, Robert Jackson [email protected] wrote:

Thanks for your work on this!


Reply to this email directly or view it on GitHub.

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

Successfully merging this pull request may close these issues.

3 participants