Skip to content

Instantly share code, notes, and snippets.

@mtodd
Created September 12, 2008 05:36
Show Gist options
  • Save mtodd/10383 to your computer and use it in GitHub Desktop.
Save mtodd/10383 to your computer and use it in GitHub Desktop.

The Problem


app = Rack::Builder.new do
  use Rack::CommonLogger
  use Rack::Reloader # this is the interesting part
  use Rack::ShowExceptions
  run HelloWorld.new
end

For some reason, the Reloader script’s timestamp keeps getting updated each and every request. WTF? It’s as if the Reloader class kept getting reinitialized every single request.

The Solution

It was.


app = Rack::Builder.new do
  use Rack::CommonLogger
  use Rack::Reloader # this is the interesting part
  use Rack::ShowExceptions
  run HelloWorld.new
end.to_app

The call to to_app call wraps it up and prevents the classes from being reinitialized over and over.

Hmmm.

require 'reloader'
require 'helloworld'
app = Rack::Builder.new do
use Rack::CommonLogger
use Rack::Reloader
use Rack::ShowExceptions
run HelloWorld.new
end.to_app
Rack::Handler::Thin.run app, :Port => 4000
require 'reloader'
require 'helloworld'
use Rack::CommonLogger
use Rack::Reloader
use Rack::ShowExceptions
run HelloWorld.new
%w(rubygems rack thin).each{|dep| require dep }
class HelloWorld
def call(env)
[200, {"Content-Type" => "text/html"}, "Hello World\n"]
end
end
require 'thread'
module Rack
# Rack::Reloader checks on every request, but at most every +secs+
# seconds, if a file loaded changed, and reloads it, logging to
# rack.errors.
#
# It is recommended you use ShowExceptions to catch SyntaxErrors etc.
class Reloader
def initialize(app, secs=10)
puts "Initializing Reloader"
@app = app
@secs = secs # reload every @secs seconds max
@last = Time.now
end
def call(env)
# puts "TIMING: #{Time.now} > #{@last + @secs} => #{Time.now > @last + @secs}"
# puts "ERRORS #{(env["rack.errors"].read rescue nil).inspect}"
if Time.now > @last + @secs
Thread.exclusive {
reload!(env['rack.errors'])
@last = Time.now
}
end
@app.call(env)
end
def reload!(stderr=STDERR)
puts "reloading #{stderr}"
need_reload = $LOADED_FEATURES.find_all { |loaded|
begin
if loaded =~ /\A[.\/]/ # absolute filename or 1.9
abs = loaded
else
abs = $LOAD_PATH.map { |path| ::File.join(path, loaded) }.
find { |file| ::File.exist? file }
end
if abs
::File.mtime(abs) > @last - @secs rescue false
else
false
end
end
}
need_reload.each { |l|
$LOADED_FEATURES.delete l
}
need_reload.each { |to_load|
begin
if require to_load
stderr.puts "#{self.class}: reloaded `#{to_load}'"
end
rescue LoadError, SyntaxError => e
raise e # Possibly ShowExceptions
end
}
stderr.flush
need_reload
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment