Skip to content

Commit

Permalink
Support :ready and :timeout options.
Browse files Browse the repository at this point in the history
  • Loading branch information
martinemde committed Dec 6, 2012
1 parent f705928 commit c861772
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 27 deletions.
13 changes: 5 additions & 8 deletions lib/realweb.rb
@@ -1,9 +1,10 @@
require 'rack'
require 'stringio'
require 'logger'
require 'open-uri'
require 'realweb/server'
require 'realweb/thread_server'
require 'realweb/forking_server'

module RealWeb
ServerUnreachable = Class.new(RuntimeError)

class << self
def start_server_in_thread(*args)
ThreadServer.new(*args) { |server| server.start }
Expand All @@ -24,7 +25,3 @@ def with_server_in_fork(*args, &block)
alias with_server with_server_in_fork
end
end

require 'realweb/server'
require 'realweb/thread_server'
require 'realweb/forking_server'
2 changes: 2 additions & 0 deletions lib/realweb/forking_server.rb
@@ -1,3 +1,5 @@
require 'realweb/server'

module RealWeb
class ForkingServer < Server

Expand Down
50 changes: 42 additions & 8 deletions lib/realweb/server.rb
@@ -1,10 +1,28 @@
require 'rack'
require 'timeout'
require 'logger'
require 'uri'
require 'open-uri'
require 'stringio'

module RealWeb
class Server
attr_reader :host, :rack_server

DEFAULT_PORT_RANGE = 8000..10000
DEFAULT_HOST = '127.0.0.1'
DEFAULT_LOGGER = Logger.new(StringIO.new)
DEFAULT_TIMEOUT = 2 # seconds

# return true if available, false if still waiting
def self.server_ready?(server)
open(server.base_uri)
true
rescue OpenURI::HTTPError
true
rescue Errno::ECONNREFUSED => e
false
end

def self.with_rackup(*args)
new(*args) do |server|
Expand All @@ -14,6 +32,21 @@ def self.with_rackup(*args)
end
end

# Create a RealWeb::Server object, either a RealWeb::ForkingServer or
# a RealWeb::ThreadServer.
#
# :port_range - Range specifying acceptable tcp ports to boot on.
# :logger - An instance of Logger.
# :host - Alternative host. Default is 127.0.0.1.
# :verbose - Print server logs and errors to stdout/err
# :timeout - Timout in seconds to wait for the server to boot.
# :ready - A Proc that returns true when the server is ready, or false
# if it is not ready yet. This proc will be called every 100ms with the
# server as an argument. If blank, an open-uri based check will be used.
# :pre_spawn_callback - a lambda to be called with the server object before
# spawning the server.
#
# Any remaining options will be passed to Rack::Server on boot.
def initialize(config_ru, options = {})
@config_ru = config_ru
@running = false
Expand All @@ -22,6 +55,8 @@ def initialize(config_ru, options = {})
@logger = options.delete(:logger) || DEFAULT_LOGGER
@host = options.delete(:host) || DEFAULT_HOST
@verbose = options.delete(:verbose) || false
@timeout = options.delete(:timeout) || DEFAULT_TIMEOUT
@ready = options.delete(:ready) || self.class.method(:server_ready?)

@pre_spawn_callback = options.delete(:pre_spawn_callback)
@rack_options = options
Expand Down Expand Up @@ -85,17 +120,16 @@ def rack_server
end

def wait_for_server
20.times do
Timeout.timeout(@timeout) do
begin
sleep 0.1
open(base_uri)
return
rescue OpenURI::HTTPError
return
rescue Errno::ECONNREFUSED => e
end
end until @ready.call(self)
end
abort "Unable to reach RealWeb server: Problem booting #{@config_ru}"
rescue Timeout::Error
raise RealWeb::ServerUnreachable, <<-ERROR
Unable to reach RealWeb server after #{@timeout}s: #{@config_ru}.#{@verbose || "\nBoot RealWeb with {verbose: true} to print errrors."}
ERROR
end

end
end
2 changes: 2 additions & 0 deletions lib/realweb/thread_server.rb
@@ -1,3 +1,5 @@
require 'realweb/server'

module RealWeb
class ThreadServer < Server

Expand Down
19 changes: 8 additions & 11 deletions spec/realweb_spec.rb
Expand Up @@ -9,6 +9,10 @@ def unauthorized_config_ru
File.expand_path("../unauthorized_config.ru", __FILE__)
end

def slow_config_ru
File.expand_path("../slow_config.ru", __FILE__)
end

shared_examples_for "working server" do
describe ".start_server" do
before { @server = start_server }
Expand Down Expand Up @@ -53,20 +57,9 @@ def with_server(*args, &block)

it_should_behave_like "working server"

describe ".with_server" do

it "cleans up the server block exit" do
pending "Rack handles/defines server stop and cleanup"
end
end

describe ".start_server" do
before { @server = start_server }
after { @server.stop }

it "becomes inaccessible when stop is called" do
pending "Rack handles/defines server stop and cleanup"
end
end

end
Expand Down Expand Up @@ -115,5 +108,9 @@ def with_server(*args, &block)
it "can boot non-200 code servers" do
RealWeb.start_server(unauthorized_config_ru).stop
end

it "accepts an alternate timeout" do
expect { RealWeb.start_server(slow_config_ru, :timeout => 0.1).stop }.to raise_error(RealWeb::ServerUnreachable)
end
end
end
2 changes: 2 additions & 0 deletions spec/slow_config.ru
@@ -0,0 +1,2 @@
sleep 1
run lambda { |env| [200, { 'Content-Type' => 'text/html' }, ['Hello World']] }

0 comments on commit c861772

Please sign in to comment.