Running Sinatra app inside Thread doesn't work - ruby

I'm trying to run a Sinatra app in a new Thread in order to also run some other thing inside my script but when I do:
require 'sinatra/base'
class App < Sinatra::Base
...some routes...
end
Thread.new do
App.run!
end
Nothing happens and Sinatra server is not started. Is there anything I'm missing in order to achieve this?

Finally I run the other ruby process in a Thread but from Sinatra application and it works just fine.
class App < Sinatra::Base
threads = []
threads <<
Thread.new do
Some::Other::Thing
rescue StandardError => e
$stderr << e.message
$stderr << e.backtrace.join("\n")
end
trap('INT') do
puts 'trapping'
threads.each do |t|
puts 'killing'
Thread.kill t
end
end
run!
end
And I added a control when Sinatra app is exited also kill the open thread.

Related

How to start Drb service concurrently with other methods in Windows

I want to run the startdrb method concurrently with the printstuff method on a Windows system. I messed around with Thread.new but the service starts and terminates after the thread completes.
How would this be written?
require 'drb'
require 'drb/ssl'
class TestDRB
def dostuff
...
end
def startdrb
begin
config = {SSLCertName: [["CN","DRuby"]]}
DRb.start_service("drbssl://127.0.0.1:9911", BHRBeacon.new, config)
rescue Exception => e
puts e.full_message
end
def printstuff
begin
puts "this will run while Drb service is also running"
end
TestDRB.new.startdrb
TestDRB.new.printstuff

Rspec tests failing for Ruby Thread

I have a worker method which looks like this
class ScoreWorker
include Sidekiq::Worker
sidekiq_options queue: 'score_worker'
def perform(scores, notification, devices)
threads = []
scores.each do |gg|
threads << Thread.new { PushNotificationService.new(notification, devices).deliver }
end
threads.each { |thr| thr.join }
end
I am writing an rspec test for my worker
describe ScoreWorker do
self.use_transactional_fixtures
before(:all) do
Rails.cache.clear
end
describe '.perform' do
self.use_transactional_fixtures
context 'create' do
it 'creates notification' do
job = create(:job)
notification = create(:notification)
devices = create(:device)
scores = ScoringService.new(job, 25).score
worker = ScoreWorker.new
expect do
worker.perform(scores, notification, devices)
end.to change(Notification, :count).by(1)
end
end
end
end
But whenever i run my tests, it keeps failing as rspec doesnt seem to support threading. So my job, notification and devices object are all empty.
How can i run my tests when using ruby threads in rspec

Is there a way to know when actually a server is stopped at EventMachine?

Using EM::stop_server schedules the server to be stopped. How can I know when the server is actually stopped?
require 'eventmachine'
class TestServer < EM::Connection
def post_init
send_data "Welcome\r\n"
end
end
class TestClient < EM::Connection
def receive_data(data)
puts data
end
end
Thread.new do
EM.run { }
end
while !EM.reactor_running? ; end
g = EM::start_server('127.0.0.1', 6667, TestServer)
EM::stop_server(g)
#sleep(1)
EM::connect('127.0.0.1', 6667, TestClient)
sleep
Running the above outputs Welcome. However if I uncomment sleep(1), nothing is printed.
Is there a way to achieve something similar without using sleep? Like using EM.reactor_running? to check if EM reactor's has started but to check if a server has been stopped.

Ctrl+C not killing Sinatra + EM::WebSocket servers

I'm building a Ruby app that runs both an EM::WebSocket server as well as a Sinatra server. Individually, I believe both of these are equipped to handle a SIGINT. However, when running both in the same app, the app continues when I press Ctrl+C. My assumption is that one of them is capturing the SIGINT, preventing the other from capturing it as well. I'm not sure how to go about fixing it, though.
Here's the code in a nutshell:
require 'thin'
require 'sinatra/base'
require 'em-websocket'
EventMachine.run do
class Web::Server < Sinatra::Base
get('/') { erb :index }
run!(port: 3000)
end
EM::WebSocket.start(port: 3001) do |ws|
# connect/disconnect handlers
end
end
I had the same issue. The key for me seemed to be to start Thin in the reactor loop with signals: false:
Thin::Server.start(
App, '0.0.0.0', 3000,
signals: false
)
This is complete code for a simple chat server:
require 'thin'
require 'sinatra/base'
require 'em-websocket'
class App < Sinatra::Base
# threaded - False: Will take requests on the reactor thread
# True: Will queue request for background thread
configure do
set :threaded, false
end
get '/' do
erb :index
end
end
EventMachine.run do
# hit Control + C to stop
Signal.trap("INT") {
puts "Shutting down"
EventMachine.stop
}
Signal.trap("TERM") {
puts "Shutting down"
EventMachine.stop
}
#clients = []
EM::WebSocket.start(:host => '0.0.0.0', :port => '3001') do |ws|
ws.onopen do |handshake|
#clients << ws
ws.send "Connected to #{handshake.path}."
end
ws.onclose do
ws.send "Closed."
#clients.delete ws
end
ws.onmessage do |msg|
puts "Received message: #{msg}"
#clients.each do |socket|
socket.send msg
end
end
end
Thin::Server.start(
App, '0.0.0.0', 3000,
signals: false
)
end
I downgrade thin to version 1.5.1 and it just works. Wired.

Embed webserver in desktop app: wxRuby and Sinatra

I would love to give my windows based desktop applications a web interface and vice versa. My desktop application is written in wxRuby and the webserver is Sinatra (using webrick). The simplest idea was just to mash them together, this does not work.
This code does not work. The webserver and gui app do not run simultaneously. The desktop application runs first, and then after it is closed; sinatra starts.
require 'wx'
require 'sinatra'
configure do set :server, 'webrick' end
get '/' do
"Sinatra says hello"
end
class MyApp < Wx::App
def on_init
#frame = Wx::Frame.new( nil, -1, "Application" )
#frame.show
end
end
app = MyApp.new
app.main_loop
So I thought about changing the last two lines to
Thread.new do
app = MyApp.new
app.main_loop
end
Again. Desktop App runs until closed, then webserver starts. So I tried starting Sinatra in a Thread.
Thread.new do
require 'sinatra'
configure do set :server, 'webrick' end
get '/' do
"Sinatra says hello"
end
end
require 'wx'
class MyApp < Wx::App
def on_init
#frame = Wx::Frame.new( nil, -1, "Application" )
#frame.show
end
end
app = MyApp.new
app.main_loop
Again. Desktop App runs until closed, then webserver starts.
Please advise, but keep in mind that I would really like to just have one process. If your solution is two processes; I would like strong inter-process communication that does not require polling.
Thanks!
Jeff
This at least starts up, not sure if this breaks some threading rules.
require 'win32/process'
require 'sinatra/base'
class MyWebServer < Sinatra::Base
get '/' do
'Hello world!'
end
end
Thread.new do
MyWebServer.run! :host => 'localhost', :port => 4567
end
require 'wx'
class MyGui < Wx::App
def on_init
t = Wx::Timer.new(self, 55)
evt_timer(55) { Thread.pass }
t.start(1)
evt_idle { Thread.pass }
#frame = Wx::Frame.new( nil, -1, "Application" )
#frame.show
true
end
end
app = MyGui.new
app.main_loop
you can use bowline, but i'm not yet using it.

Resources