Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebSocket pushing database updates

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.

like image 381
Mik378 Avatar asked Oct 20 '22 09:10

Mik378


1 Answers

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.

like image 130
Yuval Adam Avatar answered Oct 28 '22 19:10

Yuval Adam