The data module invent a DSL for querying complex JavasScript Object graph both from server and on the client, along with the associated data structures for caching queried objects.
TroopJS query is built on an object graph implemented by
data/cache/component, are essentially weakly referenced standalone objects living in a big cache pool, referencing others only by an unique id,
Two objects, both have an unique id that is consisted of a resource type and an identifier, e.g.
user object is referencing it's profile by a collapsed object with the profile id, when querying for the user object, say, from server, it is possible that user is only interested in user's "email"
rather than the profile, making the
profile property optionally expandable, in this way payload on the wire is significantly reduced, eventually allowing the client to re-assemble properties on demand:
With object graph defined above, a tiny DSL is invented to pull objects out of the graph, like
user!troopjs.repos.troopjs-core.pulls,.followers@2:3, which syntax is consist of the following components:
Then query API is a hub service provided by under the
query topic which is implemented by
data/query/component, returning a promise that resolves to a list of the queried values:
When performing a query, what TroopJS does is much more than simply sending the query to the server, instead it tries best to reduce the query from what we have on the client:
In the above example, if you have queried for
user!troopjs.repos moments ago, this object will be returned immediately served from cache, eliminating the need for querying the server again, a significant benefit coming from the
fact that since cache reducing is transparent for the query service, mock server communication is as simple as populating the cache:
The GC is an optional optimization service provided by
data/cache/service that take cares of de-referencing any expired objects from cache to free out memories, it implements a generation-based algorithms for efficiently determinate
expired objects, each GC run should have very little impact on performance. The GC will be running automatically as soon as the service is started.
The built-in cache component is memory-based, but it's fairly easy to implement a cache component powered by persisted storage, as an example for landing cache in local storage, checkout
contrib-browser/contrib-browser/store/adapter/local for details.
Find an error? Let us know →