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

Handling requests w/ 400/500 status code #836

Closed
jameslaneconkling opened this issue Mar 23, 2017 · 3 comments
Closed

Handling requests w/ 400/500 status code #836

jameslaneconkling opened this issue Mar 23, 2017 · 3 comments

Comments

@jameslaneconkling
Copy link

jameslaneconkling commented Mar 23, 2017

What are the available options for handling server errors that are thrown before the request even makes it to the falcor router middleware? I'm thinking specifically of 500 network errors and 401 authentication errors.

The problem I'm running into is that if the datasource emits an error event for a request, the model will correctly emit that same error, but will also populate the cache w/ error sentinels for all nodes in the expected jsonGraph response. So, subsequent requests for those same resources (e.g. to try again in the case of a network error, or after the user has logged in in the case of an auth error) hit the cache, don't bother making the request again, and return the error sentinels.

For some types of errors, this might make sense. But in plenty of cases (authorization, network errors, etc.), the expectation is that the request could work if tried again, and so the error sentinels shouldn't be cached.

What I had hoped to do was add $expires metadata to the response sentinels in the datasource, e.g. (pseudo-ish code)

class DataSource() {
  get(paths) {
    return request$(paths)
      .catch(err => {
        if (err.status === 401) {
          return { $type: 'error', $expires: 1, value: '401: Unauthorized.  Please log in' };
        } else if (err.status === 500) {
          // more special handling for other error status codes
          // ...
        }

        // generic error or some such
        return { $type: 'error', value: `${err.status}: Error` };
      });
  }
}

...but the datasource expects values to be emitted, not the boxed sentinels, meaning no metadata
can be attached.

Wondering what other recommended approaches there are.

@jameslaneconkling
Copy link
Author

Actually, I misread the source code. If you return a proper sentinel w/ a $type, it will be treated as the boxed value, not the inner value (relevant code).

The example code above does this ({ $type: 'error', $expires: 0, value: '401: Unauthorized. Please log in' }, if I'd bothered to actually run it, I would have seen that it works. In my own code, I was only returning { message: errorMessage, status, $expires: 0 }. 🙁 ).

It should be noted that this is not the default behavior of the netflix http-datasource, which returns an error object, rather than an error sentinel (see this issue). But creating a datasource interface that handles these cases is pretty easy.

@jameslaneconkling
Copy link
Author

For the record, returning a $expires: 0 metadata will result in an infinite request loop, as the value is no longer in the cache when the model tries to confirm it's been returned. Only return $expires: 1 from the datasource.

Also, it appears sentinel metadata (beyond $type) is not actually preserved. So in the above example, $expires: 1 is not actually applied to the node.

@jameslaneconkling
Copy link
Author

nm, if I'd actually read the docs, $expires: 1 means never expire, not expire in 1 second. $expires: -1 does the trick.

So, looks like with some minimal tweaks to the http-datasource, setting the expiry metadata will keep errors out of the cache.

Closing.

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

1 participant