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

Batching with Apollo #89

Closed
maxsalven opened this issue Jun 12, 2017 · 9 comments
Closed

Batching with Apollo #89

maxsalven opened this issue Jun 12, 2017 · 9 comments

Comments

@maxsalven
Copy link

I'm not sure whether this is an issue with Apollo or Absinthe, but figured I would start here in case batched responses don't match the Apollo expectations.

I have a very basic query:
{ users { id name } }

and am using {:absinthe_plug, git: "https://github.com/absinthe-graphql/absinthe_plug.git"}, in my mix.deps file.

This query works fine when I have batching switched off in Apollo, but I get an error with I switch it on (note I'm not even trying to send multiple queries at once, just one query):

Network error: Error writing result to store for query { users { id name } } /nCannot read property 'users' of undefined

The response from Absinthe is:
[{"operationName":null,"payload":{"data":{"users":[]}}}]

@yury-dymov
Copy link
Contributor

yury-dymov commented Jun 12, 2017

Hi @maxsalven, apollo and absinthe have a different protocol for batching. Code below might help you

export default function createApolloClient({ uri = 'http://localhost:4000/graphql' }) {
  const networkInterface = createBatchingNetworkInterface({ uri, batchInterval: 10 });

  const absintheAfterware = {
    applyBatchAfterware(res, next) {
      res.responses.forEach((resp) => {
        resp.data = resp.payload.data;
      });

      next();
    },
  };

  networkInterface.useAfter([absintheAfterware])

  const client = new ApolloClient({
    networkInterface,
  });

  return client;
}

@benwilson512
Copy link
Contributor

Absinthe plug's batching mechanism is generic over both apollo and relay, you just gotta supply the correct result manipulators.

@skosch are you able to mention whatever it is you do for that?

@skosch
Copy link
Contributor

skosch commented Jun 12, 2017

Hey, interesting stuff. Guess what, after all the effort we put into batching, Apollo just worked for me, and I never had to use batching at all! That being said, I can reproduce the error, and I can confirm that @yury-dymov's absintheAfterware function makes it work.

@maxsalven, for context, when Absinthe gets an array of requests (instead of just one, as per the spec), it returns a corresponding array of results. You simply need to configure Apollo to go through that array and pick out the result objects (payload.data), which is just what the above code accomplishes.

@benwilson512 This should probably be documented somewhere?

@benwilson512
Copy link
Contributor

It should definitely be documented yeah. Not entirely sure where though. I'll look around.

@maxsalven
Copy link
Author

Many thanks all, I couldn't see anything in the Apollo documentation that says what shape their batching transport expects in terms of server response, so yeah putting something in the Absinthe docs with @yury-dymov's afterware would certainly be helpful.

I assume Absinthe responds to batched requests in the shape that Relay expects? Or is there a formal spec for the official expected shape of batched requests that is adhered to here? If neither of the two, then perhaps worth considering changing the batched response shape to match either of Relay or Apollo, given they seem to be the main 'consumers' of GraphQL these days.

@benwilson512
Copy link
Contributor

@skosch can say more about what the default format is. I do see the value in having out of the box defaults that line up with apollo. My main concern with trying to target one format or another by default is that suddenly their release schedule affects the maintenance of Absinthe.Plug. If they release some backwards incompatible change that's suddenly on us to make changes that support it.

@skosch
Copy link
Contributor

skosch commented Jun 13, 2017

Actually, maybe hold off on that. I think this is an oversight in Apollo, plain and simple.

There is no spec for this. Apollo and nodkz's react-relay-network-layer's batched requests look slightly different (see this thread). Absinthe is built to work with both (i.e. it returns the results in the right order, and adds the id field if present). RRNL knows how to handle the batched response, but Apollo seemingly doesn't.

I've taken a very cursory look at Apollo's own batching PR and all the tests I see say "here's what the response should look like", but not "here's what the store should look like after getting the batch response back". My hunch (I may be wrong!) is that they implemented this without actually ever using it, and so they forgot about the afterWare part that's needed. @maxsalven Would you like to open an issue over there and reference this discussion?

@skosch
Copy link
Contributor

skosch commented Jun 22, 2017

@maxsalven @benwilson512 I've opened an issue with them, feel free to chime in!

@benwilson512
Copy link
Contributor

All the related issues seem closed and I know people are doing batching. Feel free to re-open if there are still issues.

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

4 participants