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?
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:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With