diff --git a/Gemfile b/Gemfile index f7eff37..f6a560f 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,3 @@ source :rubygems -gem "rake" gemspec \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index 1b361cc..516318f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,13 +2,12 @@ PATH remote: . specs: heroscale (0.0.1) - rack (~> 1.0) GEM remote: http://rubygems.org/ specs: diff-lcs (1.1.2) - rack (1.2.1) + json (1.4.6) rake (0.8.7) rspec (2.1.0) rspec-core (~> 2.1.0) @@ -24,6 +23,6 @@ PLATFORMS DEPENDENCIES heroscale! - rack (~> 1.0) - rake + json + rake (~> 0.8.7) rspec (~> 2.0) diff --git a/Rakefile b/Rakefile index a00847e..2887ec6 100644 --- a/Rakefile +++ b/Rakefile @@ -39,5 +39,4 @@ Rake::RDocTask.new do |rdoc| rdoc.rdoc_files.include("lib/**/*.rb") end - task :default => :spec \ No newline at end of file diff --git a/heroscale.gemspec b/heroscale.gemspec index e49bff8..854063c 100644 --- a/heroscale.gemspec +++ b/heroscale.gemspec @@ -27,8 +27,9 @@ Gem::Specification.new do |s| "README.md" ] - s.add_runtime_dependency 'rack', '~> 1.0' + s.add_development_dependency "json" s.add_development_dependency "rspec", "~> 2.0" + s.add_development_dependency 'rake', '~> 0.8.7' end diff --git a/lib/heroscale.rb b/lib/heroscale.rb new file mode 100644 index 0000000..c782d44 --- /dev/null +++ b/lib/heroscale.rb @@ -0,0 +1,2 @@ +require 'heroscale/middleware' +require 'heroscale/railtie' if defined?(Rails::Railtie) \ No newline at end of file diff --git a/lib/heroscale/middleware.rb b/lib/heroscale/middleware.rb new file mode 100644 index 0000000..e251b19 --- /dev/null +++ b/lib/heroscale/middleware.rb @@ -0,0 +1,29 @@ +module Heroscale + + # simple Rack Middleware that adds a hook to return the heroku env info + class Middleware + def initialize(app) + @app = app + end + + def call(env) + if env["PATH_INFO"] == "/heroscale/status" + queue_wait_time = env['HTTP_X_HEROKU_QUEUE_WAIT_TIME'] + queue_depth = env['HTTP_X_HEROKU_QUEUE_DEPTH'] + dynos_in_use = env['HTTP_X_HEROKU_DYNOS_IN_USE'] + + if queue_wait_time and queue_depth and dynos_in_use + # format the response on heroku + res = %|{"heroku": true, "queue_wait_time": #{queue_wait_time.to_i}, "queue_depth": #{queue_depth.to_i}, "dynos_in_use": #{dynos_in_use.to_i}}| + else + res = %|{"heroku": false}| + end + + [ 200, {'Content-Type' => 'application/json'}, res] + else + @app.call(env) + end + end + + end +end \ No newline at end of file diff --git a/lib/heroscale/railtie.rb b/lib/heroscale/railtie.rb new file mode 100644 index 0000000..e69de29 diff --git a/spec/heroscale/middleware_spec.rb b/spec/heroscale/middleware_spec.rb new file mode 100644 index 0000000..6b9ed89 --- /dev/null +++ b/spec/heroscale/middleware_spec.rb @@ -0,0 +1,74 @@ +require "spec_helper" +require "heroscale" + +require "json" + +describe Heroscale::Middleware do + + # this is our original app (that the middleware is wrapping around) + let(:orig_app) do + lambda do |env| + [ 200, {'Content-Type' => 'application/json'}, "HELLO!"] + end + end + + # this is our app with the middleware attached + let(:app) do + Heroscale::Middleware.new orig_app + end + + def heroku_request(opts = {}) + app.call({ + 'PATH_INFO' => '/heroscale/status', + 'HTTP_X_HEROKU_QUEUE_WAIT_TIME' => (opts[:wait] || 100), + 'HTTP_X_HEROKU_QUEUE_DEPTH' => (opts[:depth] || 0), + 'HTTP_X_HEROKU_DYNOS_IN_USE' => (opts[:dynos] || 1) + }) + end + + context "when querying on a heroku instance" do + before(:each) do + @rack_response = heroku_request(:wait => 100, :depth => 5, :dynos => 12) + @json = JSON.parse(@rack_response.last) + end + + it "should return the 'heroku' field that tells that we're on heroku" do + @json["heroku"].should == true + end + + it "should return the 'queue_wait_time' field that tells us the queue wait time" do + @json["queue_wait_time"].should == 100 + end + + it "should return the 'queue_depth' field that tells us the current queue depth" do + @json["queue_depth"].should == 5 + end + + it "should return the 'dynos_in_use' field that tells us the current heroku dynos in use" do + @json["dynos_in_use"].should == 12 + end + + end + + context "when not quering the status link" do + it "should return the original app's response" do + app.call({}).last.should == "HELLO!" + app.call({"PATH_INFO" => "/"}).last.should == "HELLO!" + app.call({"PATH_INFO" => "/heroscale/"}).last.should == "HELLO!" + app.call({"PATH_INFO" => "/heroscale/status2"}).last.should == "HELLO!" + end + + end + + context "when query while not on a heroku instance" do + before(:each) do + @rack_response = app.call({"PATH_INFO" => "/heroscale/status"}) + @json = JSON.parse(@rack_response.last) + end + + it "should return the 'heroku' field telling use we're not on heroku" do + @json["heroku"].should == false + end + end + +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..33710d0 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,8 @@ +require 'bundler/setup' +require "rspec" + +$:.unshift "lib" + +Rspec.configure do |config| + config.color_enabled = true +end \ No newline at end of file