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

Apollo Client query deduplication incorrectly deduplicates similar GraphQL operations with different files in variables #351

Open
jerbob92 opened this issue May 22, 2024 · 1 comment

Comments

@jerbob92
Copy link

When executing the same mutation with the same variables but with a different file in parallel, Apollo thinks that the request is the same, and will just wait for the first one to complete and returns that a response for all of them.

I have found out that setting queryDeduplication to false in Apollo (default is true), will fix this behavior. The reason for this is because with apollo-upload-client, the variables that go into Apollo are indeed exactly the same, so it thinks they are the same.

Is there anything that can be done about this? Perhaps adding a random dummy string (or a file hash) in place where the file will be mapped?

If not, it might be good to add information about this in the docs.

@jaydenseric
Copy link
Owner

jaydenseric commented Jul 17, 2024

with apollo-upload-client, the variables that go into Apollo are indeed exactly the same

I'm a bit rusty about how all this fits together, but doesn't Apollo Client receive the GraphQL operation variables before it gets to the terminating link created via createUploadLink, that makes the final fetch request? The variables Apollo Client process here for deduplication should contain the Blob, File, or FileList instances (or whatever special values you have custom defined "files" to upload as being):

https://github.com/apollographql/apollo-client/blob/3f6d023db2d7d6bf977060dd5db6291fd64e85e6/src/core/QueryManager.ts#L1113-L1133

I think the underlying problem is that when Apollo Client processes the GraphQL operation variables to check if they are the same as a currently active request, it JSON stringifies them with this function, which results in any File instances becoming {}, looking the same even if they have different contents:

https://github.com/apollographql/apollo-client/blob/3f6d023db2d7d6bf977060dd5db6291fd64e85e6/src/utilities/common/canonicalStringify.ts#L59-L62

Apollo Client is making a flawed assumption that all terminating links that make the final request do a basic JSON stringify on variables, but that is not the case for apollo-upload-client and most likely other community terminating links. To fix this, Apollo could try to detect things like File instances in the JSON stringify replacer when generating a key for cache comparison, and replace the File instance with something that uniquely identifies that specific file value (perhaps a string hash of the file's contents).

A more robust approach is to probably compare the request variables with active request variables using the unmodified request variables objects, by recursing into them and deep comparing the values so that two instances of a particular class would be identified as seperate values.

I don't have the availability to report this Apollo Client bug or pursue a fix, @jerbob92 would you like to take that up? If Apollo accepts the issue as a bug in Apollo Client to fix, we can close this issue here. If they don't, then really all we can do is document that people should turn off Apollo Client query deduplication, either for all requests (lazy approach), or via a custom Apollo Link that only turns it off if the variables contain files.

@jaydenseric jaydenseric changed the title Apollo thinks the file upload requests are the same when uploaded in parallel Apollo Client query deduplication incorrectly deduplicates similar GraphQL operations with different files in variables Jul 17, 2024
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

2 participants