I really love the reactivity DDP provides, and our app profits heavily from it. However, as soon as you go beyond the traditional web-browser, things get pretty muddy.
I had to implement my own DDP protocol for Unity / C#, and am now implementing one for visionOS / Swift. The main reason is that the existing implementations were so buggy that UX suffered a lot. Which is not the fault of the original library maintainers, it just takes quite some understanding how Meteor works to get it right. And I’m not even sure if my implementations are much better.
So I am wondering if there is any alternative to DDP out there, that is more based on standards, e.g. GraphQL or Apollo? The last time I researched on this, there was no proper reactivity support. And most people said: hey, just don’t use reactivity. But we need it
As an alternative, I would really appreciate if Tiny would invest a bit in developing propert DDP protocol implementations for mobile devices. In the early days, there was one from the guy supporting Meteor Cordova, but its development stopped when he left the company. I think Meteor’s reach could benefit from these official ports.
You can get reactivity with ApolloGraphQL. The client subscribes to specified change “channels”. When a GraphQL resolver mutates a table, it publishes the change to that channel. Any clients subscribed to that channel get a notification pushed to them via a subscription resolver that uses an asyncIterator function to iterate over the clients who are subscribed. Apollo caches the results on the client and provides lots of cool ways of interacting with the server. My app uses a lot of reactivity.
Sounds good. Are there any tutorials about how to set this up, maybe even for Meteor? Last time I tried it, there was literally no reactivity support whatsoever, so I gave up on Apollo.
Would reactivity work then, if the table is mutated by something else other than a GraphQL resolver? MongoDB sends events through change streams / Oplog irrespective of whether it is Meteor modifying it or not.
This question is essential with more complex setups, where the database(s) entities may be mutated by multiple independent services.
Great question. GraphQL won’t know about anything unless it happens in a GraphQL resolver. My web app uses PostGres for everything except Meteor accounts. Meteor handles reactivity for accounts of course. But that may not work for the use cases that @waldgeist describes.
Some databases have triggers – I wonder if they could be configured to fire on table mutation, and call a GraphQL resolver?
Well, it kind of did. Indirectly. And only partially. (Sorry for being so enigmatic, but we’re cooking something great and we don’t want to tell everything just yet.)
It’s basically a “piece of code” that you can feed DDP messages. It’ll do the bookkeeping of the local database, i.e., the entire merge box implementation. It does not handle sending anything, though that’s easier and could be added later, to make it a proper DDP implementation.
It’s also important that it does not handle communication, so setting up the WebSocket is up to you. But as soon as you receive a message, just push it, and the local database will be updated.
Now, it may sound like a weird library, but here’s the thing: it’s written in Rust and, as such, could be compiled to WASM and used everywhere. We didn’t plan to open source it, but this thread suggests that there may be a benefit to doing so.
We use a similar approach, whereby MongoDB holds most metadata for what we keep in Postgres - because of the natively reactive Meteor + MongoDB combo. There are services mutating Postgres and then updating MongoDB independently of Meteor, but the Meteor app reacts thanks to watching the change streams, then doing other Meteor things as a consequence.
I have been working with PostgreSQL for best part of my career, even since before Meteor. In my opinion, if people thought Oplog is bad, wait until you get a flood of notifications from Postgres triggers. You may instead opt for LISTEN/NOTIFY, but that requires a direct connection, and when it comes to connections, Postgres may require a transaction aware pooler like pgBouncer to mitigate scaling challenges. But LISTEN/NOTIFY require session pooling, not transaction … so you are back to square one.
The bottom line is, without a database like MongoDB or RethinkDB which has native support for real-time change feeds, you would rely on constructs of various degrees of brittleness. GraphQL is great, but does not offer native reactivity in the way those two databases do. It does help to an extent, if you plan to only rely on GraphQL. Personally, I like my reactivity to be end-to-end, which means it needs to start as close to the database as possible.
I plan to do that. Unfortunately, the original repo already had some licensing issues, since the maintainer re-used an existing repo and put his own copyright notices everywhere. My version is also not really backwards compatible, since I changed some of the method signatures, partly because they had typos, partly because the way they worked did not match Meteor’s typical behavior and I wanted to mimic this a bit better. In its current state, the library is pretty tied to my needs and also integrated in my main app code, as this as easier to adapt. Thus, I’ll have to find some time to revert it into a pod.