Fork me on GitHub
#reagent
<
2021-08-25
>
Pepijn de Vos04:08:38

I want to synchronise a piece of state for real time collaboration and such. Is that something people have written neat libraries for, or something you'd have to hack together with websockets?

p-himik04:08:39

It's something immensely complicated, given the need for conflict resolution in a distributed environment. I'd be very surprised if there was a Clojure[Script]-specific library for it, let alone Reagent-specific. WebSocket is just a communication protocol - it's completely orthogonal to the task. You can achieve the same result with e.g. long polling or SSR. This might be a decent place to start if you want to get into the details of why it's complicated: https://www.reaktor.com/blog/why-csp-matters-i-keeping-things-in-sync/

p-himik05:08:19

This is likely to be of use as well: https://github.com/aredington/schism But it's far from a complete solution - it's just an important building block.

Pepijn de Vos06:08:07

I was thinking about something like pouchdb

Pepijn de Vos06:08:54

In games they don't do any distributed stuff perse, the server is always right. You just locally predict the server state.

Pepijn de Vos06:08:14

Hm reagent doesn't have pluggable storage right, so you can't just plug in a couchdb atom https://github.com/pepijndevos/couch-atom (or rather a to be written pouchdb atom)

p-himik07:08:38

Even with the approach you describe, it is still not simple at all. "The server is always right" simply means that a client doesn't have to think about conflict resolution - the duty is shifted, not removed. Unless you're fine with conflicts, of course.

p-himik07:08:32

So it's easy to make something that syncs the state but in a broken way. You may not notice it during testing, but it can easily be fundamentally broken.

Pepijn de Vos07:08:18

Well there is the "game" approach where you just send the inputs and the server computes the new state, the way a clojure agent works basically. Can't have conflicts that way. The couchdb way seems to be to shift the responsibility of conflict resolution to the application (or live with arbitrary resolution) https://guide.couchdb.org/draft/conflicts.html

Pepijn de Vos07:08:43

Problem with the game method is it only works well with stable low latency networks. The couchdb way allows offline use, but you have to resolve conflicts eventually.

Pepijn de Vos08:08:45

Not exactly sure where CRDTs come in, seems like they are datastructures with built-in conflict resolution, kinda... but from what you're saying it's not as simple as yeeting CRDTs over a websocket.

Pepijn de Vos09:08:23

Also, stuff like Meteor does reactive data synchronization. Not sure how they deal with distributed issues.

Pepijn de Vos09:08:47

https://react-tutorial.meteor.com/simple-todos/ I don't see any special handling for conflicts or whatever.

alexdavis09:08:41

Theres https://github.com/homebaseio/homebase-react#clojurescript--reagent which has a reagent library, though it looks like they’re going for a mongo realm style SAAS product for persistence and sync. Theres also https://replicache.dev and https://rxdb.info and https://github.com/yjs/yjs, they’re all for different use cases really but all will make it much easier to build a real time app.

alexdavis09:08:20

Its still not an easy thing to do though

Pepijn de Vos10:08:39

I saw rxdb but wasn't really sure what it offers over pouchdb that I need, so I was thinking about making a cljs wrapper for pouchdb.

Pepijn de Vos10:08:40

yjs seems magic but for cljs probably tacking some sync things on schism would produce a more clojurific result.

Pepijn de Vos10:08:46

homebased seems equally magic and the fact they have a reagent library is great, but if they are pivoting to a SaaS thing that's not great.

alexdavis13:08:47

I imagine it will be like supabase, the core parts are open source and you can setup hosting yourself but they'll offer a managed setup too. Just a guess though

Pepijn de Vos19:08:10

Is it possible to use a custom atom-like type with Reagent? Seems like it's basically just an atom that calls notify-deref-watcher! on deref, which is a private function.

p-himik19:08:41

Should be possible but it's not documented. Any such implementation would absolutely have to use some gritty Reagent internals that are very likely to break in some future version.