Can Apollo/GraphQL be reactive?

Current Apollo docs mention that reactivity is not the immediate goal, and to get reactive data we should still use pub/sub.

But reactivity is still in the product design goals and roadmap. I’m wondering if/how this is achievable. As far as I can tell GraphQL has no provisions/hooks for anything like this. GraphQL’s resolve, which is the key, is purely one way.

The troubling language is the claim in Apollo that ‘most apps do not need Meteor reactivity and can work will with polling/refetching’ (not exact quote). To me, full stack reactivity and DDP are the core of what makes Meteor special.

I hope the plan isn’t to deprecating that just because it can cause update issues and because reactivity doesn’t have fine grain control.

5 Likes

Here is my simplistic impression of the state of Apollo reactivity:

  • Currently, the only way to get ‘reactive’ data through the Apollo pipeline is to use polling. Every 0.5s, run this query.

  • Mutations, or changes made on the client, are of course, as instantaneous as you like. There are patterns for implementing optimistic UI with Apollo Client, so you can create a facade of the Meteor magic.

  • In the future, a process that doesn’t exist currently will be available to aid in creating the illusion of reactivity. This is the ‘invalidation server’. That invalidation server, at a high level, will determine every time the client polls whether the query needs to be rerun. It will achieve this by watching mutations and tracking the dependencies thereof.

Summarily, you’re right in your sense that Meteor Mongo reactivity is not the goal. Whether that’s ideal or not certainly varies by application. To get a better (and fully factual!) understanding of the roadmap, read this.

4 Likes

You can track this issue, and Sashko gives some ways there to get reactive features.

@amandajliu is actually working on adding GraphQL subscriptions to Apollo as we speak! Subscriptions will be the first way we implement to get some reactivity to GraphQL without polling.

In the longer term we’re planning to implement the full plan laid out in the roadmap, with granular and configurable reactivity and all. The GraphQL reference implementation doesn’t yet have any provisions for fine-grained reactivity, but the GraphQL spec does (the @live directive), and that’s what we’ll be basing our work on.

7 Likes

That’s good to hear. I have a related question - in the past there was some discussion on having a more fine grained Tracker implementation similar to MobX (or even using replacing Tracker with it). Does Apollo have any kind of dependency tracker? Or is this something not in the scope of a data framework.

I was thinking getting notified of data changes/mutations would be equivalent to a subscription and could be baked it an a deeper level allowing for more fine grained control.

@helfer, thanks for your reply.

So conceivably, if we used RethinkDB instead of Mongo Oplog training, we can get realtime reactivity.
If we implemented a RethinkDB ‘driver’ for Apollo, would we get real reactivity or based on polling?

4 Likes

GraphQL itself doesn’t have any hooks for reactivity but all you have to do is keep asking the server for the query result. The client can also diff and cancel the re-render if the data hasn’t changed. In Apollo Client you can use watchQuery to do this for you. Depending on the needs you can adjust it from a half second to several minutes depending on the app!

also worth noting … reactivity to me is having the UI update once the data has changed… not specifically updating the UI when the database changes (though it can be of course). GraphQL and Apollo Client with the React bindings gives you this. For example:

  • user profile has name of “James”
  • UI queries “user” and includes the name key and userId of “u1”
  • send mutation to update user document “u1” with name of “Jim”
  • mutation returns a response with a “user” object (that includes name and id keys)
  • apollo-client looks for any users with that ID in the cache, and merges the new response data
  • cache now has user “u1” with new data with name of “Jim”
  • apollo-client-react now sends a re-render to any piece of UI that queries “user” with ID of “u1”
  • browser UI updates with new data throughout the app, reactively.

The troubling language is the claim in Apollo that ‘most apps do not need Meteor reactivity and can work will with polling/refetching’ (not exact quote). To me, full stack reactivity and DDP are the core of what makes Meteor special.

I believe this to be true as well. There’s a difference between the app having to have realtime for it to work (stock ticker, chat app, etc…) and using realtime to make it easier on the developer (not having to think about when to re-fetch).

I think part of what made Meteor is to use is that you don’t have to think about when to fetch data… eventually it’s just there. Apollo client handles the forget about thinking about refetching and the react bindings for apollo-client let you just declare what your UI wants and then you forget about it… eventually it’ll show up.

Apollo won’t have a driver as the whole platform is database agnostic.

If you use RethinkDB instead of Mongo today you’re going to have to use another library to stream changes down to the client. However, subscriptions are coming soon so that should have a hook to flush changes down to the client with RethinkDBs changefeed function (passing new data when that function is called).

I’ve done this with RethinkDB and another language/framework but if you need streaming today with RethinkDB I would prob run Horizon as a temp. crutch until GraphQL subscriptions are out.

Though I would recommend long polling with Apollo (via watchQuery) and later on swapping out with GraphQL subscriptions/Rethink changefeeds.

1 Like

Thanks @SkinnyGeek1010, Apollo seems to be a ways off still, so I was thinking of using Slava’s RethinkDB lib:

– and make my own useraccounts package where we use RethinkDB instead of Mongo (doesn’t look too hard). In theory it all sounds great … :slight_smile: practice … not sure yet.

Yeah I wouldn’t do that. There be dragons. Apollo is leaps and bounds ahead of that Rethink project. It’s outdated and has a security hole if you use the clientside bit.

I would use Mongo for your users and then rethink for everything else. If you need reactive user data then perhaps just have the profile in rethink or just the id and auth stuff in the mongo doc.

1 Like

Thanks – that means two dbs :frowning:

Agreed on the security hole, we were going to implement allow/deny ourselves.

Right now we only do polling in Apollo Client, but we’re working on subscriptions which would push realtime updates to clients over a websocket.

6 Likes

This is good news – I just hope it comes to fruition. When\if it does, then I can plan out the migration to Apollo.

1 Like

@helfer

Is the primary reason behind the data split between mongodb for user data and rethink for everything else is because meteor using mongodb as its primary data store? Or is there another advantage that I’m not aware of?

1 Like

It’s mainly because all of the authentication packages (UI and backend) all depend on the core auth packages and those are tied to Mongo (currently). Really all you would need is to store the _id key and the normal keys that Meteor users for password/oauth/etc… authentication packages. Then database X could have a key like userId or ownerId that points to the user ID in Mongo.

With GraphQL this ID will come in on every request (much like this.userId in a Meteor method) so you wouldn’t need to manually query the mongo database to query the doc.

However, if you don’t want profile data split on database X and the user ID on Mongo, you don’t have to, you can just keep it in the Mongo user document.

1 Like

I think you’re referring to a particular architecture that someone else set up, not something anyone from MDG has said.

While Meteor only works with MongoDB so far, Apollo places no restriction on what type of backends your app uses. It can be any combination of SQL, Mongo, Rethink, Kafka, Cassandra, S3, memcached, and whatever else you can think of.

Our server tutorial includes an example with SQL, Mongo and a third-party REST API. You should really check out GraphQL, I think you will like it.

2 Likes

So it seems we figured it out and got RethinkDB working properly.

We added two checks to close the security hole:

  1. You can only update client side via id only (like it’s done with minimongo)
  2. We added an allow feature that receives the id and based on it decides if the current user is allowed to make changes

So far stable, the only concern is that the client-side library (reqlite) is developed by a single developer as a hobby (and frankly, issues are getting closed with very few left, so he is doing a great job). While it is working and he is dedicated to it, we may need to help finance it to keep it going if we chose this way :slight_smile:

Also, the code is not clean, when you name your file ‘money-patching.js’ … it speaks volumes :smile:

1 Like

@SkinnyGeek1010 @helfer
Gotcha yeah that’s what I thought with meteor having the mongo requirement. Yeah built another system that worked on a similar flow, not always the most effcient but can work well. Espeically with graphql in the mix.

Thanks for the link @helfer, checking it out, super psyched to dive into some graphql.

1 Like