

Eventual Consistency in Real-time Web Apps - strife25
http://blog.johnryding.com/post/89055480988/eventual-consistency-in-real-time-web-apps

======
dgreensp
It's a lot simpler to just have the socket, with a notification when your PUT
has landed. This is what Meteor does.

I don't see anything I recognize as eventual consistency in the traditional
sense. It sounds like the client is just trying to receive a stream of
updates, which could have been made by a single writer, and the only
consistency issues are caused by the different overlapping mechanisms for
getting updates.

~~~
macspoofing
The complexity depends on what constraints you put on yourself. Here's an
example, suppose you have a UI panel with a number of checkboxes,
radiobuttons, and sliders, and you want to synchronize the state across
several users, without blocking (i.e. if a user changes state, he doesn't need
to wait for server response to change change state again). Global state exists
on a single server. Let's say your users start changing state furiously, what
happens? ...well, the object state will live in several places (and slightly
different for every client):

1) Local: In the view but before event dispatched to the model.

2) Local: In model but before it was synced to the server.

2a) Local: After model sync and in queue waiting to be sent to the server.

3) Remote: In transit to the server.

4) Remote: On the server (i.e. the one true state).

5) Remote: In transit to the clients.

6) Local: Received but before it was synced to the model.

7) Local: In model but before synced to the view.

8) In the initial state sync (e.g. when a new client joins)

So at any given point, every client state is inconsistent with every other
client (maybe even significantly if the latency for one or more of the clients
is bad) since pieces of the eventual state are spread across all these
locations. If now every user stops changing state furiously, every client
should _eventually_ be _consistent_. It's not a hard problem but not
completely trivial. For example, you will need conflict resolution rules on
the server and in your client and traditional distributed issues like
(temporary) network partitioning and latency need to be taken into account.
Message ordering will probably matter.

>It sounds like the client is just trying to receive a stream of updates,
which could have been made by a single writer

Not necessarily. You have the same synchronization issues whether the updates
are coming from a single source, or from multiple sources.

~~~
dgreensp
The EtherPad UI had a bunch of checkboxes and whatnot that were synchronized
live, so I definitely acknowledge the problem. We're working on it at Meteor
now too.

The way I look at it, as long as the server has the final say over the
"official" value at any given time -- which seems to be the case here, and is
true in all real apps I've seen up to the backend datastore's ability to
provide it -- you don't really have a consistency or convergence problem. You
just have a UI problem. It's easy for the client to track both the latest
official value and what the user is doing, and tell the server about the
latter. The only question is what to show the user while their action is still
outstanding, and the answer may be different for different kinds of UI. You
may want to "fake it till you make it" (Meteor's default, aka latency
compensation) or show some kind of loading indicator.

What about conflicts? Well, depending on your app, your options for how the
server handles operations from the client include: they sometimes fail; they
always succeed via "last writer wins" (good for a checkbox, say); they always
succeed via operational transforms; or there is application-level conflict
resolution that ropes in the user (implemented on top of the foregoing).

There's a trend at the moment to view everything as a distributed system, but
if you treat a client as a tool for viewing information and calling APIs, it
seems a lot simpler.

~~~
josephg
We already have this sort of eventual consistency in Derby, built on top of
ShareJS. All documents (JSON objects) can be edited synchronously in the
browser, and changes are automatically replicated to all other clients.

If two people make a change to the same documents at the same time, the
changes are merged in a way that will never conflict. For example if we both
simultaneously insert into a list embedded in some part of the data model,
derby sends a "list insert at position X" operation, which is seamlessly
transformed & merged into the document at all sites. The insertion position is
updated automatically before merging using the same logic that makes
collaborative text editing in etherpad work. Except you can do it over the
JSON structures that power your web app.

------
dahjelle
Are there any "standard" models for treating a realtime web app as just
another distributed database node (with, of course, extra security precautions
and having to do server-side data re-validation)? I'm aware of CouchDB/PouchDB
and Meteor's use of mini-Mongo client-side. Are there others?

~~~
lucian1900
If you have a CRDT implementation you can use on both sides, you can perform
operations on the client and merge with the server correctly.

~~~
dahjelle
That's exactly what I'm planning on doing, as that seems to be simultaneously
correct and relatively easy to program. I'm surprised, though, that I haven't
found a "nicely packaged" version of some CRDTs, a server DB, and a client-
side DB. I suppose it is probably because everyone's use-cases are so
different and that using CRDTs limit the data you can use, to some degree.

~~~
skrebbel
I'm just learning about CRDTs because of this thread.

Which CRDT things _did_ you find, did you experiment with any, which are you
using and why?

~~~
dahjelle
(semi cross-posted from another comment)

Aral Balkan gave a talk on a CRDT called WOOT for text editing[1] that I found
really helpful to get the general idea of the concept. (Really only the last 8
or 9 minutes of his talk.)

If you want more of the nitty-gritty on some of the different types of CRDT,
there's fairly readable paper on the topic[2].

From there, you can start using Google Scholar to find the other papers that
have been written.

[1]
[https://www.youtube.com/watch?v=NSTZ4mIv_wk](https://www.youtube.com/watch?v=NSTZ4mIv_wk)
[2]
[http://hal.upmc.fr/docs/00/55/55/88/PDF/techreport.pdf](http://hal.upmc.fr/docs/00/55/55/88/PDF/techreport.pdf)

------
aidos
I hadn't seen the merge / fill idea before. Worth reading to get more ideas on
this subject.

OT but seems like a good time to ask, does anyone have any experience with
Operational Transformations for dealing with syncing in web apps? I've started
throwing the idea around for a web app I'm building and it seems like a really
interesting pattern. The only real implementation I can find is in sharejs
[1]. I work with python on the backend and I can't really find an
implementation of it (though for my constrained use-case I can generate good
enough code to do it myself).

It seems like a good approach but there's very little in the way of libraries
implementing it, so I was wondering if it's somehow problematic.

[1] [http://sharejs.org/](http://sharejs.org/)

~~~
dahjelle
In general, I've read that OT tends to be very complicated to get right, which
is why only a few libraries implement it. If you can use what's called a CRDT,
your life will be easier, but there are fewer data structures that are
supported.

Aral Balkan gave a talk on OT vs a CRDT called WOOT for text editing[1] that I
found really helpful.

If you want more of the nitty-gritty on some of the different types of CRDT,
there's fairly readable paper on the topic[2].

[1]
[https://www.youtube.com/watch?v=NSTZ4mIv_wk](https://www.youtube.com/watch?v=NSTZ4mIv_wk)
[2]
[http://hal.upmc.fr/docs/00/55/55/88/PDF/techreport.pdf](http://hal.upmc.fr/docs/00/55/55/88/PDF/techreport.pdf)

~~~
aidos
That's great information, thank you. The paper looks really interesting -
going to take a little while to get through, might start with the video :)

I'd also read that it's hard to get right (I think that was in a comment on HN
by one of the people who worked on wave/sharejs). In my case I've limited
myself to two different flavours of small object with a limited set of fields
(instead of a totally generalised system). Most of the algorithms I've seen
focus on the text element of the syncing but I'm much more interested in the
object / list / field part for my use case.

Sharejs actually have a generic system of handling the OT on arbitrary json
structures, but I'm not sure how well it works.

~~~
dahjelle
I've not tried it, but you might also be interested in an approach called
differential synchronization[1]. Basically, it's just a specific way of
passing diffs around to guarantee convergence, though (as far as I can tell)
it doesn't guarantee much else (as in do you lose data if a patch can't be
applied?). The really nice bits, though, are that it is a simple algorithm and
that it can be applied to anything that you have diff/patch algorithms for.

[1]
[https://www.youtube.com/watch?v=S2Hp_1jqpY8](https://www.youtube.com/watch?v=S2Hp_1jqpY8)

~~~
aidos
I already watched that video the other day! Didn't quite get to the end of it
but I thought the general idea was interesting.

My use case is a little different, and one that OT seems to suit.

I have multiple users working on the same documents but they don't want/need
to see each other's changes straight away. They perform a number of operations
and then eventually save. When they save I'd like to propagate that that
history to the other user(s) that haven't saved yet. It feels like OT works
there - you have two threads of history and you need to rebase the uncommitted
one on top of committed one.

Maybe I'm coming at the problem wrong, but it feels like something that could
work quite well as a pattern in general.

------
deoxxa
I've had a lot of success with embedding initial content for a page as JSON in
a script tag with a specific ID and a type of "application/json". This way you
can rely on the content being there and sidestep the whole timing issue
completely. You can potentially speed up your loading time as well, if you
have a bunch of things you'd usually fire additional requests off for.

I believe I got this idea from Backbone's documentation [1] originally, but
I've seen it mentioned in other places as well.

[1]: [http://backbonejs.org/#FAQ-bootstrap](http://backbonejs.org/#FAQ-
bootstrap)

------
cromwellian
The Errai J2EE framework for GWT has an 'Operational Transform Eventually
Consistent" Web Socket bus implementation for those curious.
([https://github.com/errai/errai/tree/master/errai-
otec](https://github.com/errai/errai/tree/master/errai-otec)) Demo video:
[https://www.youtube.com/watch?v=ChCasRr0cZc](https://www.youtube.com/watch?v=ChCasRr0cZc)

