$LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__) require 'message_bus' require 'sinatra' require 'sinatra/base' require 'set' require 'json' $online = Hash.new MessageBus.subscribe "/presence" do |msg| if user = msg.data["enter"] $online[user] = Time.now end if user = msg.data["leave"] $online.delete user end end MessageBus.user_id_lookup do |env| MessageBus.logger = env['rack.logger'] name = env["HTTP_X_NAME"] if name unless $online[name] MessageBus.publish "/presence", {enter: name} end $online[name] = Time.now end name end def expire_old_sessions $online.each do |name,time| if (Time.now - (5*60)) > time puts "forcing leave for #{name} session timed out" MessageBus.publish "/presence", {leave: name} end end rescue => e # need to make $online thread safe p e end Thread.new do while true expire_old_sessions sleep 1 end end class Chat < Sinatra::Base set :public_folder, File.expand_path('../../../assets',__FILE__) use MessageBus::Rack::Middleware post '/enter' do name = params["name"] i = 1 while $online.include? name name = "#{params["name"]}#{i}" i += 1 end MessageBus.publish '/presence', {enter: name} {users: $online.keys, name: name}.to_json end post '/leave' do #puts "Got leave for #{params["name"]}" MessageBus.publish '/presence', {leave: params["name"]} end post '/message' do msg = {data: params["data"][0..500], name: params["name"][0..100]} MessageBus.publish '/message', msg "OK" end get '/' do <
This is a trivial chat demo... It is implemented as a Sinatra app. The message_bus can easily be added to any Rails/Rack app. This app can be deployed with Discourse Docker using this template.