-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Run Middleware/Afterware once on batchedNetworkInterface #1285
Conversation
…face Before working code to make sure batchedNetworkInterface works as expected. Add a test
@lewisf: Thank you for submitting a pull request! Before we can merge it, you'll need to sign the Meteor Contributor Agreement here: https://contribute.meteor.com/ |
@helfer can i get some feedback on the batchrequest types and usage here? i'm not super familiar with typescript and i'm not sure if this is the right way to do it, thanks! hoping to see that the implementation details look good before adding to the docs and stuff :) |
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.
Thanks @lewisf! I think the proper way to do it in Typescript would be to keep middleware for normal network interfaces and middleware for the batchNetworkInterface separate. One takes a RequestAndOptions, the other one takes a BatchRequestAndOptions. In order to do that, you'll have to define separate use
and useAfter
functions for the batchNetworkInterface (although you can reuse most of the code). The most important thing is that people using middleware or afterware with Typescript get an error if they try to apply non-batched afterware to a BatchedNetworkInterface.
I hope that makes sense. If not, let me know!
requests.forEach((request) => { | ||
middlewarePromises.push(this.applyMiddlewares({ | ||
// Refine the BatchRequest as a request to satisfy applyMiddlewares signature. | ||
const request: Request = requests; |
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 know if this would work, but I don't think it's advisable anyway because it makes type checks afterwards impossible. Instead of doing this (and the same thing for afterwares) I would redefine the afterwares signature for the batchNetworkInterface by overriding the use
and useAfter
methods to take a batchMiddleware or batchAfterware instead (which you have to write).
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.
okay cool, makes sense. i'll give that a shot
@helfer thanks for the help so far. i started looking into redefining use/useAfter in batchedNetworkInterface but ran into typing issues. it looks like in order to overload would it be reasonable to define the signature of batch wares to be also i'm trying to decipher this comment here: apollo-client/src/transport/networkInterface.ts Lines 89 to 90 in 3d9b44d
should i be concerned about that comment? |
I think it's perfectly fine to call it PS: You don't have to worry about that comment, if you want you can actually remove it. |
src/transport/networkInterface.ts
Outdated
throw new Error('Middleware must implement the applyMiddleware function'); | ||
} | ||
}); | ||
public use(middlewares: MiddlewareInterface[]): HTTPNetworkInterface |
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.
@helfer i don't really like what im doing here with overloading + user defined type guards, but this is a public api on network interfaces that im not comfortable changing for the batched network interface. thoughts?
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.
@lewisf could you maybe just define the use
for BatchedRequests on the HTTPBatchedNetworkInterface
? If it's not possible to override the method there, then maybe we can make both the HTTPFetchNetworkInterface
and the batch network interface inherit from a common ancestor and separately define use
. What do you think?
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.
@helfer that sounds reasonable to me.
I like the approach of also making HTTPNetworkInterface
parameterized to type of middleware and type of afterware? that would give us the ability to also parameterize use
and useAfter
. here's a working implementation with what i mean: master...lewisf:lewis/batch-single-run-wares-parameterized. However, doing this might make it difficult to define a queryMiddleware
for HTTPBatchedNetworkInterface
in the future though if that's still on the table.
Alternatively, I can greatly lax the HTTPNetworkInterface by removing use/useAfter
and associated properties, or laxing their types to MiddlewareInterface[] | BatchMiddlewareInterface
and AfterwareInterface[] | BatchAfterwareInterface
.
Lax types on use/useAfter for network interface and create a common extension point to allow for BatchMiddlewareInterface/BatchAfterwareInterface.
…is/batch-single-run-wares
@lewisf Awesome, I think this looks much neater, so I think we can merge it soon! Just one question: what's the rationale for renaming the |
@helfer oh, good really good point, I'll change that back. EDIT: Oh I remember why now, what I labeled as "BaseNetworkInterface" wasn't actually defining the behavior for 'fetch'. Instead, |
Is there any documentation on what 'applyBatchMiddleware' should contain? thanks. [edit] Checking the code it should be part of the network interface, maybe I'm doing something wrong as now I'm getting import ApolloClient, { createBatchingNetworkInterface } from 'apollo-client';
const networkInterface = createBatchingNetworkInterface({uri: url, batchInterval: 50});
networkInterface.use([{
applyBatchMiddleware(req: any, next: any) {
if (!req.options.headers) {
req.options.headers = {}; // Create the header object if needed.
}
const token = localStorage.getItem('jwtToken');
if (token) {
req.options.headers.authorization = token;
}
next();
}
}]);
networkInterface.useAfter([{
applyBatchAfterware(_response: any, next: any) {
next();
} [EDIT] OK. Got it. I had applyAterware in my code. So simply .. it was just renamed. |
A documentation update would indeed be very welcome :) |
@advance512 I have a PR open for a documentation update: https://github.com/apollographql/core-docs/pull/256 :) |
Addresses #1191.