hasura / graphql-engine

Blazing fast, instant realtime GraphQL APIs on your DB with fine grained access control, also trigger webhooks on database events.
https://hasura.io
Apache License 2.0
31.16k stars 2.76k forks source link

Send only a diff for live queries #3399

Open mitar opened 4 years ago

mitar commented 4 years ago

Currently, live queries re-send whole state every time. Even for mid-sized queries with few KBs of data, this can mean quite some traffic.

Would it be possible to provide some way to enable diffing and sending only changes? Maybe computing a JSON patch against a previous version and send that over? That would probably require storing query results on the server though, to do such diffing, so it should be configurable if you want that.

(Alternatively, Hasura could store just some merkle-like-hash-over-json-structure on the server, instead of whole state, to compute parts of the state which changed, without having to store whole state, and then send patches only for that.)

D1plo1d commented 4 years ago

I implemented JSON patch diffs for Apollo Server over at graphql-live-subscriptions perhaps this schema could serve as a starting point for a JSON patches in Hasura discussion.

I wouldn't bother looking at how I generated those JSON patches though it sounds like y'all already have a much better system for that with SQL polling :)

esseswann commented 4 years ago

This is actually more important than just saving traffic, please check out this issue https://github.com/apollographql/apollo-client/issues/6127

mitar commented 4 years ago

I do not think diffing would help with the issue you linked to. This is just disconnect between how subscriptions are applied win apollo client. What happens if you have local change + change for that particular field comes through diff? So diffing would just make the problem less obvious. The solution is that apollo client would have to know which change from the server relates to the optimistic change on the client and know when that optimistic change has been confirmed (when the value is the same is good heuristic, but not perfect) and when overrode by the server.

GavinRay97 commented 4 years ago

The developer behind RxDB released a library a few days ago targeting this exact problem. This is not a viable solution because it's in Javascript, but from an architectural perspective it could offer up some ideas for a later implementation or anyone looking to do this on the client-side or as a middleware-server method:

https://github.com/pubkey/event-reduce

image

esseswann commented 4 years ago

I do not think diffing would help with the issue you linked to. This is just disconnect between how subscriptions are applied win apollo client. What happens if you have local change + change for that particular field comes through diff? So diffing would just make the problem less obvious. The solution is that apollo client would have to know which change from the server relates to the optimistic change on the client and know when that optimistic change has been confirmed (when the value is the same is good heuristic, but not perfect) and when overrode by the server.

I saw this scenario like this: 1) How we have now, problematic:

2) How it should be with diff:

Yes there is this case when both times we've updated the same item, then the interface will jump anyway. But it's much easier to control than lock the whole interface while single item is waiting for the server confirmation

switz commented 2 years ago

Checking in on this – any movement?

slaesh commented 2 years ago

maybe this https://github.com/hasura/graphql-engine/pull/7946 will fix it? or at least a step into that direction..

TiagoJacobs commented 1 year ago

maybe this https://github.com/hasura/graphql-engine/pull/7946 will fix it? or at least a step into that direction..

Streaming is great for some scenarios, like when you have events organized by timestamps, and you want all events.

However, a live query diff patch would be for other scenarios, like a filtered, sorted and paginated resultset (it's not possible to do with streaming, because it supposes you want to receive all data - when what you want in this scenario is to have a "reactive slice" of the data, produced by a subscription).

IMHO, adding something like a @diff extension would be a great improvement. The "cost" of using it would be storing in the server the last result sent to each query (to run the json diff), which would be perfectly acceptable for our use case.

Also, I think that we could state that using the @diff extension is not encouraged when doing optimistic updates, so we (the server) don't need to worry about it.