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

GET as a transport option instead of a parameter + ErrorCancellable #599

Merged
merged 18 commits into from
Jul 2, 2019

Conversation

designatednerd
Copy link
Contributor

@designatednerd designatednerd commented Jul 1, 2019

I had a chat with @martijnwalraven about how using GET vs POST was handled in #572, and he had a couple good points I missed in the review: First, passing the fetch method as a parameter doesn't make sense if it's going to eventually be handed off to a web socket, since it'll ignore that parameter anyway. Second, if someone wants to use GET for a fetch request, they almost certainly want to use it for all fetch requests.

His suggestion (which I agreed with and implement here) was to use a parameter on the HTTPNetworkTransport to set whether fetches should use GET or POST - I left the default as POST to match existing behavior, but I think this will make things a lot simpler for the end user.

@dmandarino I'd love to hear your thoughts on this as it's a pretty significant change to what you proposed, but I think with the same end result.

Also in this PR:

  • Added ErrorCancelable return type which allows you to return a Cancellable after encountering an error that should early-exit.
  • Updated .xcodeproj files to ensure 2-space formatting for the Apollo projects (note: Didn't fix any existing 4-space formatting, will do that in a separate PR when I have more time)
  • Fixed a couple of warnings in the web socket tests
  • Started pulling a few things out into their own files to make them easier to find

// MARK: - Early-Exit Helper

/// A class to return when an error that should cause us to bail out of something still needs to return `Cancellable`.
public final class ErrorCancellable: Cancellable {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm wondering if this should really be tied to errors, or whether something more generic like an EmptyCancellable or NullCancellable (from null object pattern), would make sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ooh good call - EmptyCancellable is way more accurate

@designatednerd designatednerd force-pushed the update/get-as-option branch from d2059ab to 6a89b50 Compare July 2, 2019 07:17
Copy link

@dmandarino dmandarino left a comment

Choose a reason for hiding this comment

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

@designatednerd thank you for considering me in this PR and for asking for my opinion.

I just did as parameter, so the user can choose between GET and POST whenever he/she wants to without instantiating Apollo again. And I thought that int the future, persisted query would be a parameter too.

But I checked out on others proposes in issues and open PR, and most of them are suggesting to use it as a property in HTTPNetworkTranspot. So I agree with this solution and that it looks better in this way, since WebSocket was ignoring the HTTPMethod parameter.

And I liked the way you solved the Cancellable issue and return. Nice!

} else {
completionHandler(nil, GraphQLHTTPRequestError(kind: .serializedQueryParamsMessageError))
completionHandler(nil, GraphQLHTTPRequestError.serializedQueryParamsMessageError)
return EmptyCancellable()

Choose a reason for hiding this comment

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

Nice touch!

@SirensOfTitan
Copy link

@designatednerd: Perhaps I'm thinking too big picture here, but it might be worthwhile to look how custom extensions will evolve as apollo-ios does:

  1. Will apollo-ios adopt the ApolloLink strategy like other clients?
  2. Or perhaps something more idiomatic swift?

... we've been using NetworkTransports to compose different layers of behavior together into one larger NetworkTransport. For example, we have one NetworkTransport for Authentication-retries (i.e. when the user has to request a token from the server to continue requests), and (as of yesterday) one for PersistedQuery management.

If the GET query option is baked into HTTPNetworkTransport (which does feel a lot cleaner as some transports like WebsocketTransport don't need it) as-is, we'd need to re-create network transports for the composition pattern I mentioned above to work (as we'd first want to optimistically send the GET request then send a POST for the full query if we don't have the query cached).

@designatednerd
Copy link
Contributor Author

@SirensOfTitan Definitely good to keep the big picture in mind but I think at this point, particularly given that a) We're at a 0.x release and will be for a while, so "This may evolve" is kind of baked in, and b) People have been requesting this feature for literally years, I would prefer to err on the side of shipping this and making changes when we make decisions about the ApolloLink strategy later.

@dmandarino
Copy link

I agree with @designatednerd. People are asking for it since 2017 and there were issues opened last year too. The implementation may change in the future while the project goes on, and the need changes.

@SirensOfTitan
Copy link

@designatednerd @dmandarino Sorry, I'm not arguing against GET, I'm saying that the general, fuzzy idea of how the API will evolve could act as a useful heuristic as to whether we should keep GET as a parameter in send or as a parameter on HTTPNetworkTransport.

@designatednerd
Copy link
Contributor Author

Totally understand your point @SirensOfTitan, but at this point I want to get this out the door for day to day usage.

I'm definitely planning on revisiting some of this architecture when I get the bugs to a manageable point, but with 173 open issues (as of right this second) that may be a minute 😃

# Conflicts:
#	Sources/Apollo/ApolloClient.swift
#	Sources/Apollo/GraphQLQueryWatcher.swift
@designatednerd
Copy link
Contributor Author

Screen Shot 2019-07-02 at 9 04 59 PM

^ taking this as an approval and merging!

@designatednerd designatednerd merged commit 9451b35 into master Jul 2, 2019
@designatednerd designatednerd deleted the update/get-as-option branch July 2, 2019 19:06
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.

4 participants