Class: Firehose::Rack::Consumer::HttpLongPoll

Inherits:
Object
  • Object
show all
Includes:
Helpers
Defined in:
lib/firehose/rack/consumer.rb

Constant Summary collapse

TIMEOUT =

How long should we wait before closing out the consuming clients web connection for long polling? Most browsers timeout after a connection has been idle for 30s.

20

Instance Method Summary collapse

Methods included from Helpers

#response

Instance Method Details

#call(env) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/firehose/rack/consumer.rb', line 34

def call(env)
  req     = env['parsed_request'] ||= ::Rack::Request.new(env)
  path    = req.path
  method  = req.request_method
  # Get the Last Message Sequence from the query string.
  # Ideally we'd use an HTTP header, but android devices don't let us
  # set any HTTP headers for CORS requests.
  last_sequence = req.params['last_message_sequence'].to_i

  case method
  # GET is how clients subscribe to the queue. When a messages comes in, we flush out a response,
  # close down the requeust, and the client then reconnects.
  when 'GET'
    Firehose.logger.debug "HTTP GET with last_sequence #{last_sequence} for path #{path} with query #{env["QUERY_STRING"].inspect} and params #{req.params.inspect}"
    EM.next_tick do

      if last_sequence < 0
        env['async.callback'].call response(400, "The last_message_sequence parameter may not be less than zero", response_headers(env))
      else
        Server::Channel.new(path).next_message(last_sequence, :timeout => TIMEOUT).callback do |message, sequence|
          env['async.callback'].call response(200, wrap_frame(message, sequence), response_headers(env))
        end.errback do |e|
          if e == :timeout
            env['async.callback'].call response(204, '', response_headers(env))
          else
            Firehose.logger.error "Unexpected error when trying to GET last_sequence #{last_sequence} for path #{path}: #{e.inspect}"
            env['async.callback'].call response(500, 'Unexpected error', response_headers(env))
          end
        end
      end

    end

    # Tell the web server that this will be an async response.
    ASYNC_RESPONSE

  else
    Firehose.logger.debug "HTTP #{method} not supported"
    response(501, "#{method} not supported.")
  end
end