Open n1ru4l opened 4 years ago
Hey @marcus-sa, thanks for your comment and showing interest 😊
Since subscriptions for several pub sub system already exist you could leverage the technical perspective of that. For example in NestJS you can have programmatically object type defined fields as "ID"s. If you took leverage of that and mapped in at server startup it would somehow solve it.
Do you mean traversing and gathering the information about the schema?
At client-side you've got GraphQL generator that could easily be modified to detect such custom directives and generate "live" queries.
I would like to not rely on a compiler on client-side to it accessible for more people.
I would like to work at this, since I've been thinking about this approach for some time.
I would love it if you could experiment with gathering resource identifiers or even better come up with a solution that works better than the current InMemoryLiveQueryStore
👍
I also just opened a PR for supporting fragments in the current implementation: https://github.com/n1ru4l/graphql-live-queries/pull/82
Maybe it could be possible to abstract the method for gathering the resource identifiers into an API so different use-cases can use different ways of gathering the resource identifiers? Does that make sense?
I got too excited https://github.com/n1ru4l/graphql-live-queries/pull/94
Resource identifier collection is now implemented as part of https://github.com/n1ru4l/graphql-live-queries/pull/94
I wrote an article about the functionality https://dev.to/n1ru4l/collecting-graphql-live-query-resource-identifier-with-graphql-tools-5fm5
Thanks for this great toolset! I've got a suggestion...and also a question.
Suggestion
Following packages:
Are each including functions targetting both client and server. Unless there is something I misunderstood, the patch creation needs to be done on server side while it's the client which needs to apply the patch.
It's resulting to adding useless functions/code on the client and the server. My suggestion is to split each of those packages in two: one to "generate patches" and the other one to "apply patches".
For example, I don't need the applyPatch function (because my client is not written in JS - see bellow question) but I'm compelled to import it server side.
Question
I'm trying to port the client part of "graphql-live-query-patch" into Dart - because I've got a Flutter client. I'm wondering about your implementation: why are you creating a new AsyncIterable through "repeater" instead of mapping the source result with the result of the "applyPatch" function?
EDIT: sorry for the stupid question, I just realized that AsyncIterableIterator is not mappable :/
It's resulting to adding useless functions/code on the client and the server. My suggestion is to split each of those packages in two: one to "generate patches" and the other one to "apply patches".
This can be solved by doing modular imports, bundling, and dead-code elimination. I don't plan to split the logic into a client and server package.
Repeater.js is used because it is too easy ending up with memory leaks while fiddling with AsyncGenerators/AsyncIterables. There been a few memory leak within this library before, all related to that.
This can be solved by doing modular imports, bundling, and dead-code elimination. I don't plan to split the logic into a client and server package.
As you wish, but I think you miss my point by answering with modular imports/bundling solutions. Don't you think it would be great to see multiple client implementations? If so, let's say I will make a Pull Request to implement patching on Flutter. It would make sense to duplicate existing interfaces, but it doesn't make any sense to implements patch generation on Flutter as it's a client framework (you always could argue that it's possible to use dart server side, but I think you get the point).
The approach of calling
liveQueryStore.triggerUpdate("Query.users")
might not scale that well. It could return different results for different users. It does not address the unique field argument combinations.Resource-Based Updates
If a user with id
fgahex
changes we ideally only want to update queries that select the given user.Object types that have an id field could be automatically collected during query execution (and updated during re-execution).
Query
Execution result:
Will result in the following entry for the selected resources of that query:
User.fgahex
. An update for all the live queries that select the given user could be scheduled vialiveQueryStore.triggerUpdate("User.fgahex")
.Things to figure out:
What is the best way of collecting resources?
This would require sth. like a middleware for each resolver that gathers the ids and attaches them to the result (as extensions?) that the liveQueryStore can pick up (maybe this?).
Another solution would be to push this to the user so he has to register it manually, by calling some function that is passed along the context object?
The information could also be extracted from the query response. However, that would have the implications that it needs at least the
id
extracted for each record (or evenid
+__typename
for GraphQL servers that do not expose unique ids across object types). Since most client-side frameworks encourage using unique ids for identifying Objects anyways that shouldn't be that big of a limitation. An additional drawback would be that the whole result tree must be traversed.Pros:
triggerUpdate
for the previous resource).Cons:
id
property.