Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Store websocket connection to redis

I'm using websocket-rack to build a chat application API.

I would like to store the websocket connections (which ends up being an instance of Rack::WebSocket::Handler::Base::Connection) in redis, so that they can be filtered and referenced from other processes.

I realize I can store the connections in an class variable, but this does not work cross process.

The object itself cannot be stored in redis obviously, however can I store the websocket_key and some other information and somehow rebuild the connection object when I want to send a message to it?

like image 483
fridgerator Avatar asked May 23 '15 18:05

fridgerator


2 Answers

somehow rebuild the connection object when I want to send a message to it?

You cannot rebuild it, you will need to keep it alive, otherwise you disconnect your client.

The process that maintains your WebSocket connections (alive) will also need to provide an API so that other processes can tell it to send a message on their behalf.

For example this could be a simple private (only accepts connections from localhost) HTTP API where you send a POST message with two parameters:

  1. The message you want to send
  2. Who you want to send the message to
like image 119
14 revs, 12 users 16% Avatar answered Oct 13 '22 08:10

14 revs, 12 users 16%


I would recommend using a Websockets framework, such as the Plezi web-app framework, which would handle both the websocket connection IO and help you broadcast data* across multiple processes through a Redis server.

(* notice that although Redis can store data, it cannot store objects and it definitely cannot store live sockets)

For example: Plezi would let you fork your server and it will automatically use Redis to broadcast/unicast data between the websockets on different processes or on different machines:

require 'plezi'
ENV['PL_REDIS_URL'] = "redis://username:[email protected]:6379"
# fork to 4 processes, each will have at least 2 Redis connections
GR::Settings.set_forking 4
# ... plezi code
Plezi.start # now it will fork.

A working chat server using the Plezi framework would look something like this*:

* this is just a draft to run in the irb terminal. A Plezi app set up with the plezi new app_name command would look way more organized.

require 'plezi'

# # optional Redis URL: automatic broadcasting across processes:
# ENV['PL_REDIS_URL'] = "redis://username:[email protected]:6379"

class ChatController
    def index
        %q{        This is a Plezi chat demo app using websockets.
        To test this app, go to: http://www.websocket.org/echo.html
        In the Location URL fill in the following url: ws://localhost:3000/nickname
        Click Connect. No the app will act as a chat demo server with your browser as the client.

        Try running the demo from two different browser windows to see chat messages between windows.
        remember to set the correct Location URL in each window.}
    end
    def on_message data
        msg = "#{params[:id] ? params[:id].to_s : 'unknown'}: #{data}"
        broadcast :_send, msg
        _send msg
        true
    end
    def _send message
        response << message
    end
end

# starts listening with default settings, on port 3000
listen

# this is automatically converted to the RESTful route: '/(:id)'
route '/', ChatController

# exit terminal to start server
exit
like image 23
Myst Avatar answered Oct 13 '22 07:10

Myst