class Jebanni::Server

Public Class Methods

new(ip = '127.0.0.1', port = 63310) click to toggle source
Calls superclass method
# File lib/jebanni/server.rb, line 11
def initialize(ip = '127.0.0.1', port = 63310)
  @channels = {}
  super(ip, port, &method(:on_connection))
  async.ping
end

Public Instance Methods

all_connections() click to toggle source
# File lib/jebanni/server.rb, line 28
def all_connections
  @channels.map{|(_, channel)| channel.connections}.flatten
end
broadcast_to(channel, data, event, id) click to toggle source
# File lib/jebanni/server.rb, line 17
def broadcast_to(channel, data, event, id)
  channel.connections.each do |socket|
    async.send_sse(socket, data, event, id)
  end
  true
end
channels() click to toggle source
# File lib/jebanni/server.rb, line 24
def channels
  @channels
end

Private Instance Methods

event_stream(request, response) click to toggle source
# File lib/jebanni/server.rb, line 88
def event_stream(request, response)
  Reel::EventStream.new do |socket|
    channel = response.channel
    channel.join socket
    socket.retry 5000
    #after a Connection reset resend newer Messages to the Client, query['lastEventId'] is needed for https://github.com/Yaffle/EventSource
    query = Hash[URI.decode_www_form(request.query_string || "")]
    id = (request.headers['Last-Event-ID'] || query['lastEventId'])
    socket << "id\n\n"
    if id && id.to_i > 0
      channel.refrain(id.to_i)
    end
  end
end
handle_request(request) click to toggle source
# File lib/jebanni/server.rb, line 71
def handle_request(request)
  response = RequestHandler.new(request, self).route!
  return request.respond 204 if response.finished?

  request.respond Reel::StreamResponse.new(:ok, response_headers, event_stream(request, response))
end
leave_channel(socket) click to toggle source
# File lib/jebanni/server.rb, line 45
def leave_channel(socket)
  @channels.each do |id, ch|
    next unless ch.connections.include?(socket)
    debug("Disconnect from channel:#{id}")
    ch.leave(socket)
  end
end
on_connection(connection) click to toggle source
# File lib/jebanni/server.rb, line 103
def on_connection(connection)
  connection.each_request do |request|
    handle_request(request)
  end
end
ping() click to toggle source

apache 2.2 closes connections after five seconds when nothing is send, see this as a poor mans Keep-Alive

# File lib/jebanni/server.rb, line 65
def ping
  every(5) do
    send_ping
  end
end
response_headers() click to toggle source
# File lib/jebanni/server.rb, line 78
def response_headers
  #X-Accel-Buffering is nginx(?) specific. Setting this to "no" will allow unbuffered responses suitable for Comet and HTTP streaming applications
  {
    'Content-Type' => 'text/event-stream; charset=utf-8',
    'Cache-Control' => 'no-cache',
    'X-Accel-Buffering' => 'no',
    'Access-Control-Allow-Origin' => '*',
  }
end
send_ping() click to toggle source

Lines that start with a Colon are Comments and will be ignored

# File lib/jebanni/server.rb, line 54
def send_ping
  all_connections.each do |socket|
    begin
      socket << ": ping\n"
    rescue Reel::SocketError
      leave_channel(socket)
    end
  end
end
send_sse(socket, data, event = nil, id = nil) click to toggle source

event and id are optional, Eventsource only needs data

# File lib/jebanni/server.rb, line 34
def send_sse(socket, data, event = nil, id = nil)
  unless data.is_a? String
    data = JSON.dump(data)
  end
  socket.id id if id
  socket.event event if event
  socket.data data
rescue Reel::SocketError
  leave_channel(socket)
end