Launch and call Ruby HTTP server in the same script

I wonder how I could run a Ruby Rack application (like Sinatra) and call it Net :: HTTP or similar in the same script. I could do something like ...

require 'sinatra/base' require 'net/http' t = Thread.new do class App < Sinatra::Base get '/' do 'Hi!' end end App.run! :host => 'localhost', :port => 1234 end sleep 2 puts Net::HTTP.start('localhost', 1234) { |http| http.get('/') }.body t.join puts 'Bye!' 

... but it does not feel optimal for sleep for two seconds, waiting for the start of Thin. What do I need - is it some kind of callback at server startup or any other suggestions?

+1
multithreading ruby events rack sinatra
source share
3 answers

If you look at the run! method run! in the sinatra source in base.rb, you will see the following:

 def run!(options={}) ... handler.run self, :Host => bind, :Port => port do |server| [:INT, :TERM].each { |sig| trap(sig) { quit!(server, handler_name) } } set :running, true end ... end 

There is no way to connect callbacks. BUT! As you can see, the :running parameter changes after the server shuts down.

So, a simple solution is like viewing the App.settings.running stream in a short polling cycle (every 500 ms or something in this series). Once running true, you can safely do your job.


Edit: An improved version, with a little monkey fix. Adding the after_running callback to Sinatra:

 class Sinatra::Base # Redefine the 'running' setting to support a threaded callback def self.running=(isup) metadef(:running, &Proc.new{isup}) return if !defined?(after_running) return if !isup Thread.new do Thread.pass after_running end end end class App < Sinatra::Base set :after_running, lambda { puts "We're up!" puts Net::HTTP.start('localhost', 1234) { |http| http.get('/') }.body puts "Done" } get '/' do 'Hi!' end end App.run! :host => "localhost", :port => 1234 
+4
source

run! in current versions, Sinatra takes a block that is called when the application starts.

Using this callback you can do this:

 require 'thread' def sinatra_run_wait(app, opts) queue = Queue.new thread = Thread.new do Thread.abort_on_exception = true app.run!(opts) do |server| queue.push("started") end end queue.pop # blocks until the run! callback runs end sinatra_run_wait(TestApp, :port => 3000, :server => 'webrick') 

This seems reliable for WEBrick, but with Thin, the callback is still sometimes called a little before the server accepts the connection.

+4
source

I would use a semaphore (cf. Ruby Semaphores? ) With a capacity of 1 for this task:

Main theme:

  • Get semaphore
  • Create New Topic
  • Get semaphore (will be blocked until the generated thread is released)

Web server thread generated:

  • App.run!
  • Semaphore release
+2
source

All Articles