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

[NT-463] Improve error handling for graph requests #918

Merged
merged 12 commits into from
Oct 30, 2019

Conversation

ifbarrera
Copy link
Contributor

@ifbarrera ifbarrera commented Oct 28, 2019

📲 What

This PR makes some changes to how we make Graph requests, and how we parse responses from Graph requests.

🤔 Why

To improve error parsing/handling for graph requests and make our requests more robust to changes in the JSON structure coming back from the API. Also, to make graph requests more consistent with how our v1 requests are made.

🛠 How

Previously, we made all graph requests through a single performRequest function that started a data task within a producer and parsed errors and data in the completion block of that task. This approach was a little inconsistent with our approach for v1 requests, which splits up error handling and model decoding by running all error handling through rac_* helper functions defined in an extension of URLSession. These helpers also make use of Reactive Swift's data(with request:) function which is specially designed to return a SignalProducer which "performs work associated with an NSURLSession". It seemed like a good idea for Graph requests to follow a similar pattern of doing error handling in a similar rac_graphDataResponse function, and then running the resulting Data through a decoding function (decodeGraphModel).

Now, v1 requests are made like this (no change here):

 return Service.session.rac_JSONResponse(preparedRequest(forURL: paginationUrl))
      .flatMap(self.decodeModel)

... and Graph requests are made like this:

return Service.session.rac_graphDataResponse(request)
        .flatMap(self.decodeGraphModel)

♿️ Accessibility

N/A

🏎 Performance

N/A

✅ Acceptance criteria

Setup: Using Charles Proxy, set up a breakpoint such that all requests hitting the Graph endpoint are intercepted.

  • Test that aborted requests correctly show a request error.
  • Test that removing the "data" field from a request with a validation error (ex. entering the wrong password when trying to change your email) does not affect parsing of the returned error. The message banner should still show the validation error returned from the API.
  • Test that errors returned from the API (ex. entering the wrong password when changing your email) are correctly parsed and displayed.
  • Test that modifying the response body to an invalid object correctly produces a decoding error

@@ -3,7 +3,10 @@ import Prelude
// MARK: - Graph Response

public struct GraphResponse<T: Decodable>: Decodable {
let data: T?
let data: T
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here we decouple data and errors by removing the errors from GraphResponse and giving them their own GraphResponseErrors struct. This allows us to decode errors separately from data.

@@ -43,45 +43,23 @@ extension Service {
.map { json in decode(json) as M? }
}

private func performRequest<A: Swift.Decodable>(request: URLRequest) -> SignalProducer<A, GraphError> {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The performRequest function has been removed in favor of a decodeGraphModel function that decodes Data into objects, and an rac_graphDataResponse function which is responsible for actually making the request and parsing any resulting errors.

Copy link
Contributor

@justinswart justinswart left a comment

Choose a reason for hiding this comment

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

Thanks for digging into this, I think this is certainly better than what we have currently!

Now that I've had a bit of time to think through it a bit more I have some suggestions since our pairing on it, just to simplify and improve readability I think.

KsApi/GraphSchema.swift Outdated Show resolved Hide resolved
KsApi/extensions/NSURLSession.swift Outdated Show resolved Hide resolved
KsApi/extensions/NSURLSession.swift Outdated Show resolved Hide resolved
KsApi/extensions/NSURLSession.swift Show resolved Hide resolved
KsApi/extensions/NSURLSession.swift Show resolved Hide resolved
KsApi/extensions/NSURLSession.swift Outdated Show resolved Hide resolved
Copy link
Contributor

@justinswart justinswart left a comment

Choose a reason for hiding this comment

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

This all checks out! Only thing to mention is that during testing, it correctly produced a decoding error by way of entering that part of the code, but the message is still just "Something went wrong". Was that your intention?

If so - :shipit:

@ifbarrera
Copy link
Contributor Author

This all checks out! Only thing to mention is that during testing, it correctly produced a decoding error by way of entering that part of the code, but the message is still just "Something went wrong". Was that your intention?

If so - :shipit:

By "decoding error" are you referring to the error that results if the structure of the data doesn't match our expectation? If so, then yes this is the expected behavior.

@justinswart
Copy link
Contributor

By "decoding error" are you referring to the error that results if the structure of the data doesn't match our expectation? If so, then yes this is the expected behavior.

Yes. The console of course still said that it was a decoding error.

@justinswart justinswart merged commit 9caaf95 into master Oct 30, 2019
@justinswart justinswart deleted the ignore-data-field-when-error branch October 30, 2019 18:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants