• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

n1ru4l/graphql-live-query: Realtime GraphQL Live Queries with JavaScript

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

n1ru4l/graphql-live-query

开源软件地址(OpenSource Url):

https://github.com/n1ru4l/graphql-live-query

开源编程语言(OpenSource Language):

TypeScript 95.5%

开源软件介绍(OpenSource Introduction):

GraphQL Live Query

Real-Time with any schema or transport.

Why Live Queries? - Read the introduction Post - Learn how Live Query Tracking works



Packages in this Repository

Package Description Stats
@n1ru4l/in-memory-live-query-store Live query implementation. npm version npm downloads
@n1ru4l/graphql-live-query Utilities for live query implementations. npm version npm downloads
@n1ru4l/graphql-live-query-patch-json-patch Reduce live query payload size with JSON patches npm version npm downloads
@n1ru4l/graphql-live-query-patch-jsondiffpatch Reduce live query payload size with @n1ru4l/json-patch-plus npm version npm downloads
@n1ru4l/socket-io-graphql-server GraphQL over Socket.io - Server Middleware npm version npm downloads
@n1ru4l/socket-io-graphql-client GraphQL over Socket.io - Client npm version npm downloads
todo-example-app Todo App with state sync across clients. -

Motivation

There is no mature live query implementation that is not tied to any specific database or SaaS product. This implementation should serve as an example for showcasing how live queries can be added to any GraphQL.js schema with (almost) any GraphQL transport.

GraphQL already has a solution for real-time: Subscriptions. Those are the right tool for responding to events. E.g. triggering a sound or showing a toast message because someone poked you on Facebook. Subscriptions are also often used for updating existing query results on a client that consumes data from the same GraphQL API. Depending on the complexity of that data, cache update code for applying the subscription result can eventually become pretty bloated (!!! especially, for adding and removing list items). Often for developers it is more straight-forward to simply refetch the query once a subscription event is received instead of doing cache voodoo magic.

In contrast to manual cache updates using subscriptions, live queries should feel magical and update the UI with the latest data from the server without having to write any cache update wizardry code on the client.

Concept

A live query is a query operation that is annotated with a @live directive.

query users @live {
  users(first: 10) {
    id
    login
  }
}

A live query is sent to the server (via a transport that supports delivering partial execution results) and registered. The client receives a immediate execution result and furthermore receives additional (partial) execution results once the live query operation was invalidated and therefore the client data became stale.

The client can inform the server that it is no longer interested in the query (unsubscribe the live query operation).

On the server we have a live query invalidation mechanism that is used for determining which queries have become stale, and thus need to be rescheduled for execution.

Instead of sending the whole execution result, the server can diff the previous and the current execution result and only send a delta instruction to the client instead of the whole operation, resulting in less network overhead!

In a future implementation the server might only need to re-execute partial subtrees of a query operation instead of the whole operation.

How does the server know the underlying data of a query operation has changed?

The reference InMemoryLiveQueryStore implementation uses an ad hoc resource tracker, where an operation subscribes to the specific topics computed out of the query and resolved resources during the latest query execution.

A resource (in terms of the reference implementation) is described by a root query field schema coordinate (such as Query.viewer or Query.users), a root query field with id argument (Query.user(id:"1")) or a resource identifier (such as User:1). The latter is by default composed out of the resource typename and the non nullable id field of the given GraphQL type.

For the following type:

type User {
  id: ID!
  name: String!
}

Legitimate resource identifiers could be User:1, User:2, User:dfsg12. Where the string after the first colon describes the id of the resource.

In case a resource has become stale it can be invalidated using the InMemoryLiveQueryStore.invalidate method, which results in all operations that select a given resource to be scheduled for re-execution.

Practical example:

// somewhere inside a userChangeLogin mutation resolver
user.login = "n1ru4l";
user.save();
liveQueryStore.invalidate([
  // Invalidate all operations whose latest execution result contains the given user
  `User:${user.id}`,
  // Invalidate query operations that select the Query,user field with the id argument
  `Query.user(id:"${user.id}")`,
  // invalidate a list of all users (redundant with previous invalidations)
  `Query.users`,
]);

Those invalidation calls could be done manually in the mutation resolvers or on more global reactive level e.g. as a listener on a database write log. The possibilities are infinite.


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap