-
Notifications
You must be signed in to change notification settings - Fork 730
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
Result
ALL THE THINGS!!!
#644
Conversation
} else { | ||
XCTFail("Unexpected error: \(error)") | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test represents a breaking change: Before if you cleared the cache and requested the same info again, you would get nil
for both the GraphQLResult
and the Error
. Now you will receive an error since there is nothing to decode for that result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That definitely seems correct to me, I think the previous behavior was a mistake.
let websocketError = WebSocketError(payload: payload, | ||
error: error, | ||
kind: .neitherErrorNorPayloadReceived) | ||
responseHandler(.failure(websocketError)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a new error type to help handle cases where we previously could have sent nil
for both the payload and the error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have the full context here (this was contributed by someone else), but I'm wondering when this condition would actually occur. I suspect this is something that should be solved in OperationMessage.parse
, because it seems like a protocol error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I plan to look at that in more depth when I do some much more detailed looks at the WebSocket stuff- this is at least to get this out the door in a way that still gives us some kind of semi-meaningful error about what went wrong.
} else { | ||
XCTFail("Unexpected error: \(error)") | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test also represents a breaking change - I think that this has an outer GraphQLResultError
since there's some data in the cache, but not all of it.
Twitter feedback on this change has been positive so far - gonna let @martijnwalraven tell me what I'm doing wrong tomorrow and then leave it open for further feedback for a day or two. |
0e9fc98
to
bda9b6a
Compare
Sources/Apollo/ApolloClient.swift
Outdated
|
||
@available(*, deprecated, renamed: "GraphQLResultHandler") | ||
public typealias OperationResultHandler<Operation: GraphQLOperation> = GraphQLResultHandler<Operation.Data> | ||
/// - result: The result of a performed operation. Will have a `GraphQLResult` with the data of the requested type on `success`, and an `Error` on `failure`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is needed, but we may want to mention GraphQLResult
can contain GraphQL errors in addition to data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah good call
@@ -26,11 +26,17 @@ public final class GraphQLQueryWatcher<Query: GraphQLQuery>: Cancellable, Apollo | |||
} | |||
|
|||
func fetch(cachePolicy: CachePolicy) { | |||
fetching = client?.fetch(query: query, cachePolicy: cachePolicy, context: &context) { [weak self] (result, error) in | |||
fetching = client?.fetch(query: query, cachePolicy: cachePolicy, context: &context) { [weak self] outerResult in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if we can find a more descriptive name than outerResult
, but I don't have any great suggestions. Or maybe just result
and graphQLResult
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah that works - i'll try to change that throughout when there's not a 2nd result being wrapped
let websocketError = WebSocketError(payload: payload, | ||
error: error, | ||
kind: .neitherErrorNorPayloadReceived) | ||
responseHandler(.failure(websocketError)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have the full context here (this was contributed by someone else), but I'm wondering when this condition would actually occur. I suspect this is something that should be solved in OperationMessage.parse
, because it seems like a protocol error.
} else { | ||
XCTFail("Unexpected error: \(error)") | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That definitely seems correct to me, I think the previous behavior was a mistake.
|
||
client.fetch(query: query, cachePolicy: .returnCacheDataDontFetch) { (result, error) in | ||
client.fetch(query: query, cachePolicy: .returnCacheDataDontFetch) { innerResult in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this called innerResult
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because this is a nested callback - we already have outerResult
above.
bda9b6a
to
d644a75
Compare
Hey, not an expert wrt. swift, but maybe one could add the old signature with a |
@mormahr Definitely doable, but it's pretty significant maintenance overhead to maintain all of the old public method signatures and basically need to do this with every single one: @available(*, deprecated, message: "Use the method with the `Result` completion handler instead")
func oldMethod(completion: @escaping (_ parameter: Parameter?, _ error: Error?)) {
self.newMethod { result in
switch result {
case .success(let parameter):
completion(parameter, nil)
case .failure(let error):
completion(nil, error)
}
}
} Unless there's a real good reason not to, I'd kinda prefer to rip the band-aid off here. |
OK folks - leaving this open for further comment until 10pm Netherlands Time (1pm US-Pacific) on Monday. Speak now or forever be mad at me for breaking your shit! |
…nforming to the `NetworkTransport` protocol
…gate` into extensions.
Yo dawg I heard you like Result so I put a Result in your Result
daca9bd
to
c8b94d8
Compare
May [deity of choice] have mercy on us all. Merging! |
what's wrong with that, get a schema.json, but swift API |
This PR changes pretty much all of our completion closures to take advantage of Swift 5's built-in
Result
type. This is going to be a SUPER-BREAKING CHANGE™, though I believe it will help significantly in disambiguating whether a particular request has succeeded or failed, which is why I've done it in the first place.If you have reasons you think I should abandon this path, I'd love to hear them - please let me know in the comments!
In this PR:
Result
type to make it WAY easier to tell when a request has failed prior to parsing. This does cause a couple of significant changes:Previously, there were cases where we would return neither a result nor an error. These cases will now always return a result.
This leads to some extra-fun and inscrutable compiler errors when you're going through and updating everything:
What this error is attemping to tell you is that you need to change the two-parameter completion closure into a single-parameter one. It's telling you that in a very, very opaque fashion, though. I plan to document this in the release notes as well.
OperationResultHandler
typealias since I'm already breaking the crap out of everything