rack-stream
rack-stream copied to clipboard
How to pass arguments to the Handlers?
How can I pass arguments to the Handlers? I want to pass the timeout options to the EventSource and WebSockets instantiate but I can't figure out how to get them there. Could you offer some advice?
Sorry, I don't understand what you're trying to accomplish. Do you have example code?
OK sorry, a bit of background.
I am using this with grape, following the recommended way from the examples. I am pushing messages out from redis subscribe. It works great, but it will timeout after a while when there are no messages, and the javascript client will close the connection.
Looking over the EventSource and WebSockets Readme I found that you can pass in an option to make the server ping the client at a specified interval:
es = Faye::EventSource.new(es,
:headers => {'Access-Control-Allow-Origin' => '*'},
:ping => 15,
:retry => 10
)
ws = Faye::WebSocket.new(env, nil, {ping: 15})
Sooo I was looking through the handlers code in this repo, and for the websockets handler I see you do this:
module Rack
class Stream
module Handlers
# This handler uses delegates WebSocket requests to faye-websocket
class WebSocket < AbstractHandler
#...snip...
def open
@ws = ::Faye::WebSocket.new(@app.env) # object init
@ws.onopen = lambda do |event|
@body.each {|c| @ws.send(c)}
end
end
So... what I want to be able to do is pass the extra options into the open
method to give to the object instantiation:
def open
@ws = ::Faye::WebSocket.new(@app.env, nil, @options) # pass in the options hash from somewhere
@ws.onopen = lambda do |event|
@body.each {|c| @ws.send(c)}
end
end
While I could add the options argument to AbstractHandler#initialize
I got lost trying to find where the handlers are initialized and how to pass options from Grape (or rack use/builder/handler) to a handlers new method. Could you point me in the right direction?.
Or maybe I should just fork, and hard code the ping intervals in each handler. I could do a pull request if I figure out the above but I would have no idea how to quantify the changes in a spec.
Cheers
While I could add the options argument to AbstractHandler#initialize
@penguinpowernz you were on the right track. The concrete subclasses do not implement their own initialize
method, instead using AbstractHandler#initialize. A new @options
instance variable there will be made available to all subclasses.
def initialize(app, options = {})
@app = app
@options = options
@body = DeferrableBody.new
end
The specific Handler
is detected at runtime in Rack::Stream::App#open! with the Handler.find
method. I didn't expect options, so Rack::Stream::App#initialize takes an options
hash, but does not save it. The same is true for Rack::Stream#initialize. You would need to save the options hash in these places to make it work.
Does that give you enough context to try a pull request? I'm happy to review or give more tips.