creating a class over faye-websocket in ruby - ruby

I am not experienced with event driven programming and I am struggling to get my head around how I would write a class on top of faye-websocket to hide the complexity of what I am doing. Here is the idea of what I want to do:
require 'faye/websocket'
require 'eventmachine'
require 'pp'
class Rubix
def initialize(url, options)
#response = {}
EM.run {
ws = Faye::WebSocket::Client.new(url, nil, options)
ws.on :open do |event|
...
end
ws.on :error do |event|
p [:error]
end
ws.on :message do |event|
resp = JSON.parse(event.data)
rid = resp['id']
response[rid] = resp
end
ws.on :close do |event|
p [:close, event.code, event.reason]
ws = nil
end
}
end
def call_qes(json_rpc, id)
ws.send(json_rpc)
while #response[id].nil?
sleep(1)
end
resp = #response.delete(id)
return resp
end
end
Is this a valid approach? If not how should I put a layer of abstraction around this?
Thanks.

Related

How can i implement secure websocket client in ruby?

How can i create WSS client connection in JRuby framework?
i am using faye/websocket-driver-ruby gem for connecting and publishing message, can anyone provide the imformation about this.
Getting error,
IOError: Connection reset by peer
sysread at org/jruby/ext/openssl/SSLSocket.java:857,
Please let me know what i am doing wrong.
require 'bundler/setup'
require 'eventmachine'
require 'websocket/driver'
require 'permessage_deflate'
require 'socket'
require 'uri'
require "openssl"
class WSSClient
DEFAULT_PORTS = { 'ws' => 80, 'wss' => 443 }
attr_reader :url, :thread
def initialize
#url = "wss://localhost:433/wss"
#uri = URI.parse(#url)
#port = #uri.port || DEFAULT_PORTS[#uri.scheme]
ssl_context = OpenSSL::SSL::SSLContext.new
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
#socket = TCPSocket.new(#uri.host, #port)
ssl_context.ssl_version = :TLSv1_2_client
ssl_socket = OpenSSL::SSL::SSLSocket.new(#socket, ssl_context)
ssl_socket.sync_close = true
ssl_socket.connect
#driver = WebSocket::Driver.client(self)
#driver.add_extension(PermessageDeflate)
str = "Hello server!"
str = str + "\n"
#dead = false
#driver.on(:open) { |event| write str }
#driver.on(:message) { |event| p [:message, event.data] }
#driver.on(:close) { |event| finalize(event) }
#thread = Thread.new do
#driver.parse(ssl_socket.read(1)) until #dead
end
#driver.start
end
def send(message)
#driver.text(message)
end
def write(data)
ssl_socket.write(data)
end
def close
#driver.close
end
def finalize(event)
p [:close, event.code, event.reason]
#dead = true
#thread.kill
end
end
Or any other way (algorithm) to create WSS client.

How write Rspec test cases in ruby for Faye websocket

I want write Rspec for this code. Plz help me.
def run_server(credentials, token)
wskey = get_websocket_key(token)
EM.run do
ws = Faye::WebSocket::Client.new('url'+wskey)
puts "ws.comm_inactivity_timeout"
ws.on :open do
puts "Connected"
end
end

API integration error HTTParty

I'm learning how to work with HTTParty and API and I'm having an issue with my code.
Users/admin/.rbenv/versions/2.0.0-p481/lib/ruby/2.0.0/uri/generic.rb:214:in `initialize': the scheme http does not accept registry part: :80 (or bad hostname?)
I've tried using debug_output STDOUT both as an argument to my method and after including HTTParty to have a clue but with no success. Nothing gets displayed:
require 'httparty'
class LolObserver
include HTTParty
default_timeout(1) #timeout after 1 second
attr_reader :api_key, :playerid
attr_accessor :region
def initialize(region,playerid,apikey)
#region = region_server(region)
#playerid = playerid
#api_key = apikey
end
def region_server(region)
case region
when "euw"
self.class.base_uri "https://euw.api.pvp.net"
self.region = "EUW1"
when "na"
self.class.base_uri "https://na.api.pvp.net"
self.region = "NA1"
end
end
def handle_timeouts
begin
yield
#Timeout::Error, is raised if a chunk of the response cannot be read within the read_timeout.
#Timeout::Error, is raised if a connection cannot be created within the open_timeout.
rescue Net::OpenTimeout, Net::ReadTimeout
#todo
end
end
def base_path
"/observer-mode/rest/consumer/getSpectatorGameInfo"
end
def current_game_info
handle_timeouts do
url = "#{ base_path }/#{region}/#{playerid}?api_key=#{api_key}"
puts '------------------------------'
puts url
HTTParty.get(url,:debug_output => $stdout)
end
end
end
I verified my URL which is fine so I'm lost as to where the problem is coming from.
I tested with a static base_uri and it doesn't change anything.
The odd thing is when I do:
HTTParty.get("https://euw.api.pvp.net/observer-mode/rest/consumer/getSpectatorGameInfo/EUW1/randomid?api_key=myapikey")
Everything is working fine and I'm getting a response.
HTTParty doesn't seem to like the way you set your base_uri.
Unless you need it to be like that just add another attr_reader called domain and it will work.
require 'httparty'
class LolObserver
include HTTParty
default_timeout(1) #timeout after 1 second
attr_reader :api_key, :playerid, :domain
attr_accessor :region
def initialize(region,playerid,apikey)
#region = region_server(region)
#playerid = playerid
#api_key = apikey
end
def region_server(region)
case region
when "euw"
#domain = "https://euw.api.pvp.net"
self.region = "EUW1"
when "na"
#domain = "https://na.api.pvp.net"
self.region = "NA1"
end
end
def handle_timeouts
begin
yield
#Timeout::Error, is raised if a chunk of the response cannot be read within the read_timeout.
#Timeout::Error, is raised if a connection cannot be created within the open_timeout.
rescue Net::OpenTimeout, Net::ReadTimeout
#todo
end
end
def base_path
"/observer-mode/rest/consumer/getSpectatorGameInfo"
end
def current_game_info
handle_timeouts do
url = "#{domain}/#{ base_path }/#{region}/#{playerid}?api_key=#{api_key}"
puts '------------------------------'
puts url
HTTParty.get(url,:debug_output => $stdout)
end
end
end

EM::WebSocket.run as well as INotify file-watching

This is the code I currently have:
#!/usr/bin/ruby
require 'em-websocket'
$cs = []
EM.run do
EM::WebSocket.run(:host => "::", :port => 8085) do |ws|
ws.onopen do |handshake|
$cs << ws
end
ws.onclose do
$cs.delete ws
end
end
end
I would like to watch a file with rb-inotify and send a message to all connected clients ($cs.each {|c| c.send "File changed"}) when a file changes. The problem is, I do not understand EventMachine, and I can't seem to find a good tutorial.
So if anyone could explain to me where to put the rb-inotify-related code, I would really appreciate it.
Of course! As soon as I post the question, I figure it out!
#!/usr/bin/ruby
require 'em-websocket'
$cs = []
module Handler
def file_modified
$cs.each {|c| c.send "File was modified!" }
end
end
EM.run do
EM.watch_file("/tmp/foo", Handler)
EM::WebSocket.run(:host => "::", :port => 8085) do |ws|
ws.onopen do |handshake|
$cs << ws
end
ws.onclose do
$cs.delete ws
end
end
end

Ruby and Redis, threads not processing commands

I'm working with redis and ruby and attempting to issue a blpop within a thread, so that I can wait for an incoming item on a list.
The problem is that the code within the block for blpop never seems to get called. Here's the sample code that I'm running (ruby 1.9.3):
require 'rubygems'
require 'redis'
def start_thread
#thread = Thread.new do
r = Redis.new
r.blpop("test", 0) do |key, message|
process_message(key, message)
end
end
redis = Redis.new
redis.rpush "test", "hello world"
end
def process_message(key, message)
#message = "#{key} was sent #{message}"
end
start_thread
#thread.join
p #message
Any help is greatly appreciated!
require 'rubygems'
require 'redis'
def start_thread
#thread = Thread.new do
r = Redis.new
key, message = r.blpop(:test, 0)
process_message(key, message)
end
redis = Redis.new
redis.rpush :test, "hello world"
end
def process_message(key, message)
#message = "#{key} was sent #{message}"
end
start_thread
#thread.join
p #message

Resources