

RESTful Realtime - jconley
http://code.realcrowd.com/restful-realtime/

======
Codhisattva
Screw long polling. Use websockets.

~~~
jwarkentin
That's basically what I was going to say. I've developed a realtime system for
my company that uses a REST API on the backend, but we use websockets to push
updates to the clients in realtime. It's so much faster (no polling and no
overhead of establishing new connections). When there's an update we hit the
API once to fetch the new data and then push it out to all clients subscribed
to the given data set which massively reduces load on the server.

~~~
jconley
In this approach we aren't re-establishing connections every time since the
server side supports keep-alive and the clients are web browsers, which also
support keep-alive.

We also hit the API once to push out changes to the subscribed clients through
the connection proxy. And the next poll has relatively minimal overhead
(obviously not as small as 0) to be queued back up.

In the end, though, this obviously isn't an implementation aimed at extreme
efficiency. If that were the goal we'd take a much different approach.

It is about simplicity and semantic elegance.

------
hcarvalhoalves
That's an interesting approach, but it's still pooling, although I wouldn't
know better.

Does anyone know what the alternatives are? Can you avoid pooling and still
speak HTTP?

~~~
jconley
Yes, it's definitely still polling. It is polling about once per minute.
However, at least it's only polling at the application protocol level, not the
connection level. Browsers and the GRIP proxy support keep-alive so the same
TCP connection is very likely to be re-used for quite a while.

HTTP by nature is request/response. To speak pure HTTP, there isn't a way
around polling that I know of. Avoiding polling means implementing your own
protocol over HTTP, or using WebSockets (see Comet or implementations in
Socket.IO, Firebase, SignalR, etc).

~~~
bobfunk
There is actually a way to do streaming over HTTP without doing WebSockets.
It's called "Server Sent Events" and is implemented in the EventSource API in
Chrome, Firefox and Safari.

It's quite easy to fall back to long polling in older browsers and it's a very
simple and straight forward format.

~~~
jconley
Yes you can certainly stream and do message passing within HTTP (for some
browsers) but you can't, for instance, return headers more than once without
your own application protocol.

The most interesting bit about this architecture for me is the 1:1 mapping
with a pure HTTP resource. It's a bit like an implicit subscription to a pub-
sub enabled resource. In this implementation we are simply calling our API
like we normally would (except on the stream domain) and waiting for an
update.

------
mmerickel
As far as a REST API supporting etags and if-none-match headers, it's pretty
unexpected that if I supply an if-none-match to the request, the server may
keep the connection open for an arbitrary amount of time. I'd expect that
behavior to be a side-channel of the normal 304 response. For example, it
should only keep the connection open if I supply ?timeout=60 resource option
or X-Modification-Timeout: 60 header.

------
ctide
Your code samples are incredibly hard to read, you should use a different
library to generate those. I don't know if it's just a Chrome thing, but they
look like this to me:

[http://imageshar.es/52cf03f8f629007c1400043e](http://imageshar.es/52cf03f8f629007c1400043e)

~~~
alptrv
This is a Chrome bug
[https://code.google.com/p/chromium/issues/detail?id=236298](https://code.google.com/p/chromium/issues/detail?id=236298)

------
tucaz
I'm curious if you guys did consider SignalR. Did you? If yes, yeah not use
it?

~~~
jconley
We did consider SignalR with the Service Bus backplane (we run on Azure). We
also considered node.js with Socket.IO/Redis, Firebase, and a number of other
realtime systems. But when we looked into it we realized we would be
duplicating a lot of code on the realtime side that was already there on the
RESTful API side. With this approach we're able to do realtime with minimal
modifications to our server and client side implementations that deal with our
simple use case of keeping a resource up to date. Because we use AngularJS,
simply updating the resource on the client side re-binds everything.

~~~
jwarkentin
In the realtime stuff I've built I publish update notifications on different
channels to Redis whenever data is saved from a model. Then I have a Node.js
server that listens for those update notifications, fetches the new update
once, and then pushes it out to all connected clients. This reduces a LOT of
load on the server because if we have 300 clients connected, it still results
in only one request to the server to fetch the new data and update all
clients.

Even if you don't want to use a pub/sub and publish instant notifications when
data is updated you could implement polling in a Node.js server and just have
all the clients connect to it with Socket.io. Then when the Node.js server
sees an update in the data it can push it out to all the clients.

This strategy also has the advantage that you don't have to change anything on
the client if you decide to switch to a pub/sub in the future for more real
time updates.

~~~
jconley
I've definitely done the separate channel thing in the past for update
notifications and it does perform very well.

Our setup is a pub/sub system, where the "sub" happens implicitly with the
request for a resource via the GRIP proxy and protocol and the "pub" happens
when we update our models as well. The proxy acts a lot like node.js and
Socket.IO would, but simply speaks pure HTTP on our RESTful resources instead
of the Socket.IO protocol over their transports.

------
mietek
Have you looked into accepting Server Sent Events instead of long polling?

~~~
jconley
We didn't see much of a need to expand beyond long polling, if for nothing
more than simplicity's sake. Realtime is a small feature in small parts of the
application right now. Keeping it very simple and coupled with our RESTful API
let us roll it out quickly.

~~~
Codhisattva
Main reason to avoid long polling is the awful scalability (compared to plain
old socket programming).

~~~
jconley
Processing the poll request certainly has a bit of a CPU/memory/network
overhead. Though any sort of keep-alive would require something similar. I'm
sure we'll get fancier with WebSockets when we have to rent too many new
servers because of this stuff. The simplicity and elegance of overloading the
RESTful HTTP system was the most appealing bit for me with this architectural
experiment.

~~~
mietek
As I understand, Server Sent Events are plain old HTTP, unlike Web Sockets.

