-
-
Notifications
You must be signed in to change notification settings - Fork 676
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
Race condition causes resolver method injections to be undefined #869
Comments
Modifying not exposed and not documented private parts is always done on your own responsibility.
Why do you need that? We use serverless with TypeGraphQL and even subscriptions without any issues 🤔 |
@MichalLytek this does not quite modify any internals of TypeGraphQL. There are only two things being done and one of them was recommended by you
Running into similar issues those mentioned in the links above. You may not be running into the same issue, as mentioned, this happens when there are two concurrent queries that use the same schema metadata types and one resolves before the other. If this does not happen then you probably won't encounter this |
But why do you clear the metadata storage? It's prohibited to use that on your own, it's not a part of a public API and it's never mentioned in the docs. It's exposed only for my internal usage in the tests.
You should have a single schema build once, stored in the I never suggested anyone cleaning the metadata storage. It's against the TypeGraphQL architecture and can be changed even in a patch release. |
@MichalLytek It's kind of the reverse of the same issue, I will try to break it down to the best of my knowledge. To ensure you have a single store with
However,
So the decorator does a push into the related store cache. (So each query will push the same metadata but for it's own invocation into the store) However, type-graphql/src/metadata/metadata-storage.ts Line 201 in 3733b1e
is subsequently invoked. What this does is iterate through the values currently in the cache and mutate them such that if the current target is not referentially equal to the value in the cache, it will remove it through this filter operation: type-graphql/src/metadata/metadata-storage.ts Line 208 in 3733b1e
Hope that sounds fair so far The import of this, is as mentioned previously, if a I want to emphasize that this happens when a client makes two concurrent queries that depend the same metadata types (e.g. @Args() decorators), that resolve out of order. If you have one query at a time, you won't run into this issue. Probably also mutations do not have this issue since they are always handled serially. Hope that explains the issue? |
TypeGraphQL was never designed to support paralel schema building, mostly because of the You can't just expect me to fix that because it's not a bug - it doesn't happen until you break the internals by clearing the metadata storage. You need to figure out a way to not reevaluate the decorators by |
Thanks @MichalLytek I was more looking for your input on addressing it, and hopefully contributing a PR to resolve it here or in serverless-offline as appropriate, maybe I shouldn't have called it a bug 😓 But the issue in my last comment happens without clearing the metadata storage, this happens when using the solution you recommended to retain the same metadata storage, and if there are concurrent queries that resolve out of order.
That's why the 2nd "fix" was then attempted, so without that the 1st issue: ("filtering out targets that are not current"), still presents itself. I guess what you're saying is that all queries should be done in a way that they don't happen concurrently using the same metadata |
It seems using |
Is there a chance there is some public documentation around this for |
@theseyi |
Sounds good I can comment here, or does creating a PR to add it to the FAQ work? |
Describe the Bug
TypeGraphQL has been fantastic so far, however, using
serverless-offline
orserverless
in general with TypeGraphQL is known to have various limitations and workarounds have been prescribed for some of these issuesThis is a bug that happens when using a workaround to clear the global metadata storage on every incoming query when running
serverless-offline
before any imports:global.TypeGraphQLMetadataStorage = undefined
.This bug presents itself when there are two concurrent queries / requests being handled asynchronously,
query A
andquery B
and they happen to use the same metadata types.Sequence:
query A
comes in and get's a brand newglobal.TypeGraphQLMetadataStorage
(storeA)storeA
including FieldResolver decorators and Args()query A
query B
comes in and get's a brand newglobal.TypeGraphQLMetadataStorage
(storeB)store A
is no longer reachable, since theglobal
reference will be set toundefined
and replaced withstore B
store B
, with their own runtime instancesquery B
completes and resolves fine since the store was built with it's own type instancesquery A
subsequently asynchronously resumes, but now requests to the store,store B
, will be invalid because the instances no longer pass referential equality checks. For exampleconvertArgsToInstance
which callsgetArgsType
that does a strict equals comparison to find the matching target inargumentTypes
on the global store.The problem is that shared global state is mutable and therefore presents invalid values to callers when they are processed out of order.
Expected Behavior
That TypeGraphQL is able to inject the correct params for query resolvers
Shared immutable global state, but this isn't quite feasible with serverless architectures given how TypeGraphQL is implemented, and leads to the other problems linked above
Or, more expensive and wasteful, each request receives its own private TypeGraphQLMetadataStorage
Logs
Environment (please complete the following information):
Additional Context
Add any other context about the problem here.
The text was updated successfully, but these errors were encountered: