Question

Most of the articles on the web dealing with WebSockets are about in-memory Chat.
I'm interested in kind of less instant Chat, that is persistent, like a blog's post's comments.

I have a cluster of two servers handling client requests.
I wonder what could be the best strategy to handle pushing of database update to corresponding clients.

As I'm using Heroku to handle this cluster (of 2 web dynos), I obviously read this tutorial aiming to build a Chat Room shared between all clients.

It uses Redis in order to centralize coming messages; each server listening for new messages to propagate to web clients through websocket connections.

My use case differs in that I've got a Neo4j database, persisting into it each message written by any client.
My goal is to notify each client from a specific room that a new message/comment has just been persisted by a client.

With an architecture similar to the tutorial linked above, how could I filter only new messages to propagate to user? Is there an easy and efficient way to tell Redis:

"(WebSocket saying) When my client initiates the websocket connection, I take care to make a query for all persisted messages and sent them to client, however I want you (Redis) to feed me with all NEW messages, that I didn't send to client, so that I will be able to provide them."

How to prevent Redis from publishing the whole conversation each time a websocket connection is made? It would lead to duplications since the database query already provided the existing contents at the moment.

Was it helpful?

Solution

This is actually a pretty common scenario, where you have three components:

  1. A cluster of stateless web servers that maintain open connections with all clients (load balanced across the cluster, obviously)
  2. A persistent main data storage - Neo4j in your case
  3. A messaging/queueing backend for broadcasting messages across channels (thus across the server cluster) - Redis

Your requirement is for new clients to receive an initial feed of the recent messages, and any consequent messages in real-time. All of this is implemented in your connection handlers.

Essentially, this is what your (pseudo-)code should look like:

class ConnectionHandler:

    redis = redis.get_connection()

    def on_init():
        self.send("hello, here are all the recent messages")
        recent_msgs = fetch_msgs_from_neo4j()
        self.send(recent_msgs)
        redis.add_listener(on_msg)
        self.send("now listening on new messages")

    def on_msg(msg):
        self.send("new message: ")
        self.send(msg)

The exact implementation really depends on your environment, but this is the general flow of things.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top