lib/slack/real_time/client.rb in slack-ruby-client-0.4.0 vs lib/slack/real_time/client.rb in slack-ruby-client-0.5.0
- old
+ new
@@ -11,11 +11,11 @@
attr_accessor :web_client
attr_accessor(*Config::ATTRIBUTES)
def initialize(options = {})
- @callbacks = {}
+ @callbacks = Hash.new { |h, k| h[k] = [] }
Slack::RealTime::Config::ATTRIBUTES.each do |key|
send("#{key}=", options[key] || Slack::RealTime.config.send(key))
end
@token ||= Slack.config.token
@web_client = Slack::Web::Client.new(token: token)
@@ -27,38 +27,26 @@
end
end
def on(type, &block)
type = type.to_s
- @callbacks[type] ||= []
- @callbacks[type] << block
+ callbacks[type] << block
end
- def start!
- fail ClientAlreadyStartedError if started?
- EM.run do
- @options = web_client.rtm_start
+ # Start RealTime client and block until it disconnects.
+ # @yieldparam [Websocket::Driver] driver
+ def start!(&block)
+ socket = build_socket
+ socket.start_sync { run_loop(socket, &block) }
+ end
- socket_options = {}
- socket_options[:ping] = websocket_ping if websocket_ping
- socket_options[:proxy] = websocket_proxy if websocket_proxy
- @socket = Slack::RealTime::Socket.new(@options['url'], socket_options)
-
- @socket.connect! do |ws|
- ws.on :open do |event|
- open(event)
- end
-
- ws.on :message do |event|
- dispatch(event)
- end
-
- ws.on :close do |event|
- close(event)
- end
- end
- end
+ # Start RealTime client and return immediately.
+ # The RealTime::Client will run in the background.
+ # @yieldparam [Websocket::Driver] driver
+ def start_async(&block)
+ socket = build_socket
+ socket.start_async { run_loop(socket, &block) }
end
def stop!
fail ClientNotStartedError unless started?
@socket.disconnect! if @socket
@@ -68,38 +56,92 @@
@socket && @socket.connected?
end
class << self
def configure
- block_given? ? yield(Config) : Config
+ block_given? ? yield(config) : config
end
def config
Config
end
end
protected
+ # @return [Slack::RealTime::Socket]
+ def build_socket
+ fail ClientAlreadyStartedError if started?
+ @options = web_client.rtm_start
+
+ socket_class.new(@options.fetch('url'), socket_options)
+ end
+
+ def socket_options
+ socket_options = {}
+ socket_options[:ping] = websocket_ping if websocket_ping
+ socket_options[:proxy] = websocket_proxy if websocket_proxy
+ socket_options
+ end
+
+ def run_loop(socket)
+ @socket = socket
+
+ @socket.connect! do |driver|
+ yield driver if block_given?
+
+ driver.on :open do |event|
+ open(event)
+ callback(event, :open)
+ end
+
+ driver.on :message do |event|
+ dispatch(event)
+ end
+
+ driver.on :close do |event|
+ callback(event, :close)
+ close(event)
+ end
+ end
+ end
+
+ attr_reader :callbacks
+ def socket_class
+ concurrency::Socket
+ end
+
def send_json(data)
fail ClientNotStartedError unless started?
@socket.send_data(data.to_json)
end
def open(_event)
end
def close(_event)
+ socket = @socket
@socket = nil
- EM.stop
+
+ [socket, socket_class].each do |s|
+ s.close if s.respond_to?(:close)
+ end
end
+ def callback(event, type)
+ callbacks = self.callbacks[type.to_s]
+ return false unless callbacks
+ callbacks.each do |c|
+ c.call(event)
+ end
+ end
+
def dispatch(event)
return false unless event.data
data = JSON.parse(event.data)
type = data['type']
return false unless type
- callbacks = @callbacks[type.to_s]
+ callbacks = self.callbacks[type.to_s]
return false unless callbacks
callbacks.each do |c|
c.call(data)
end
true