josephsavona
These are good questions: why does Relay Modern have garbage collection? Is that just a fancy name for cache eviction?
Let's put aside naming for a moment. Relay stores GraphQL data in normalized form, as a map of global identifiers to records. Each record has an identifier, type, and map of fields to values. Relationships between objects are expressed as fields that "link" to other records. These links are expressed as data structures - an object such as `{__ref: <id>}` - as opposed to direct references to the objects.
Using object references would mean that Relay could in theory let the JS runtime do garbage collection: except that the runtime would only see a cyclic graph of objects for which (typically) at least one root object had a persistent reference (the record corresponding to the root of the graph). In other words, it would do its job and retain all records in memory since they would all be (in)directly referenced from the root object, which would have to be referenced by Relay in order to access the data.
Relay, however, has more knowledge than the JS runtime does about how this data can be accessed: it can analyze the currently active queries against the object graph to determine which records are required to fulfill those queries. This is what the garbage collection feature does: remove records that may not be referenced by any active query.
Note that this has some aspects in common with standard garbage collection in programming language runtimes. There is a mapping of identifiers (memory addresses) to values. Each value may contain links (pointers) to other records (blocks of memory). Because the graph has cyclic references, standard cache eviction strategies - LIFO, LRU, etc - don't necessarily apply as they might evict data that is still referenced.
I hope this helps shed some light on this feature. Questions and suggestions (PRs) welcome!
> but there's no mention of subscriptions or client-side state control
The blog post didn't cover all the new features, but both of these use-cases are supported in Relay Modern - https://facebook.github.io/relay/docs/new-in-relay-modern.ht...
GraphQL Subscriptions are supported: applications must inject a network layer that provides support for connecting to the server and receiving subscription updates. Local state is supported via client-only extensions to the schema, combined with an imperative update API. More docs coming soon :-)
Good questions! It isn't quite as straightforward as you might expect - the interconnected nature of graph-like data means that strategies that work for HTTP don't necessarily apply.
For example, storing per-field expiration times could incur additional memory overhead (you might end up with an object per field instead of per record). Storing per-record expiration times is tricky since the same record can have different fields fetched at different times. And a simple max cache size + LIFO/LRU/etc evication strategy means that the cache might evict a record that is still referenced by a view.
This type of TTL/expiration is something that we're continuing to explore.
> 2. Relay doesn't have as many facilities for updating the store and working with mutation results.
Apollo and Relay Modern are about equal in this regard. Relay supports arbitrary writes to the store (either via an imperative API, via a fragment + payload, or a mix of the two), plus similar APIs for updating the store after a mutation or subscription update. This includes the ability to update client-only state.
> 3. The Apollo Store is a plain JavaScript object,
The Relay Modern store is also a plain object. There aren't currently any convenience functions for serializing/deserializing it, but this is something we're open to adding.
Overall I'd say the main differences is that Apollo has focused very much on easier onboarding and covering a wide variety of use cases (many view layer integrations, developer tooling etc), where Relay is more focused on performance and scalability (hence features such as ahead-of-time optimization, garbage collection, etc).
Either are appropriate depending on your specific needs. I'm excited to see so much iteration in this space!
Relay Modern (as with previous versions) supports an injectable network layer. This allows each application to customize how to communicate with its GraphQL server using whatever transport protocol is most appropriate (for example you might use HTTP for queries/mutations and WebSockets for subscriptions).