nimble_nodes 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -5,12 +5,15 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "nimble_nodes"
8
- gem.summary = "gem for connecting apps to the NimbleNodes server"
9
- gem.description = "automatically scales dynos and workers at Heroku"
8
+ gem.summary = "coming soon"
9
+ gem.description = "coming soon"
10
10
  gem.email = "jordan@digitalignition.com"
11
11
  gem.homepage = "http://github.com/glasner/nimble_nodes"
12
12
  gem.authors = ["Jordan Glasner"]
13
13
  gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ gem.add_development_dependency "mocha"
15
+ gem.add_development_dependency "fakeweb"
16
+ gem.add_dependency "json"
14
17
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
18
  end
16
19
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.9
1
+ 0.2.0
@@ -0,0 +1,51 @@
1
+ module NimbleNodes
2
+
3
+ module App
4
+
5
+ #= Rails
6
+
7
+ def self.rails?
8
+ defined?(RAILS_GEM_VERSION) ? true : false
9
+ end
10
+
11
+ def self.rails_version
12
+ RAILS_GEM_VERSION.slice(0..2).to_f
13
+ end
14
+
15
+ #== Check Rails version
16
+ # returns true if gem is loaded in a pre 2.3 version of rails
17
+ def self.use_rails_filter?
18
+ NimbleNodes::App.rails? and NimbleNodes::App.rails_version < 2.3
19
+ end
20
+
21
+ # set through Heroku API when app is created
22
+ def self.name
23
+ ENV['NIMBLE_NODES_APP_NAME']
24
+ end
25
+
26
+ # set through Heroku API when app is created at server
27
+ def self.token
28
+ ENV['NIMBLE_NODES_APP_TOKEN']
29
+ end
30
+
31
+ # returns true if app has been setup at server correctly
32
+ def self.token?
33
+ not NimbleNodes::App.token.nil?
34
+ end
35
+
36
+ # path at server for calling app resource and subresources
37
+ def self.path(subpath='/')
38
+ name = NimbleNodes::App.name
39
+ return nil if name.nil?
40
+ '/' + name + subpath
41
+ end
42
+
43
+ # returns path to platform specific report implementation
44
+ def self.reporter
45
+ path = NimbleNodes::App.use_rails_filter? ? '/rails/filter' : '/middleware'
46
+ NimbleNodes.lib_path(path)
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -2,16 +2,65 @@ module NimbleNodes
2
2
 
3
3
  module Dynos
4
4
 
5
+ #= Settings
6
+
7
+ # shortcut for accessing NimbleNodes.settings[:dynos_pool][key]
8
+ def self.[](key)
9
+ NimbleNodes::Dynos.settings[key]
10
+ end
11
+
12
+ def self.settings
13
+ hash = NimbleNodes::Settings['dynos_pool']
14
+ hash.nil? ? {} : hash
15
+ end
16
+
5
17
  def self.size
6
- ENV['NN_DYNOS_POOL_SIZE']
18
+ NimbleNodes::Dynos['size']
19
+ end
20
+
21
+ def self.min
22
+ NimbleNodes::Dynos['min']
7
23
  end
8
24
 
9
25
  def self.max
10
- ENV['NN_DYNOS_POOL_MAX']
26
+ NimbleNodes::Dynos['max']
27
+ end
28
+
29
+ def self.request_queue
30
+ hash = NimbleNodes::Dynos.settings['request_queue']
31
+ hash.nil? ? {} : hash
32
+ end
33
+
34
+ def self.min_request_queue
35
+ NimbleNodes::Dynos.request_queue['min']
11
36
  end
12
37
 
13
38
  def self.max_request_queue
14
- ENV['NN_DYNOS_REQUEST_QUEUE_MAX']
39
+ NimbleNodes::Dynos.request_queue['max']
40
+ end
41
+
42
+ #= Status Inspector
43
+
44
+ def self.paused?
45
+ not NimbleNodes::Dynos['paused_at'].nil?
46
+ end
47
+
48
+ #= Monitoring
49
+
50
+ def self.monitor?
51
+ NimbleNodes.active? and !NimbleNodes::Dynos.paused?
52
+ end
53
+
54
+
55
+ # pass over the hash containing Rack env variables
56
+ # a Report will be created and posted if neccessary
57
+ def self.monitor(env)
58
+ begin
59
+ report = NimbleNodes::Report.new(env)
60
+ report.post if report.post?
61
+ rescue
62
+ # rescues any possible errors to ensure app performace isn't affected
63
+ end
15
64
  end
16
65
 
17
66
  end
@@ -6,7 +6,7 @@ module NimbleNodes
6
6
 
7
7
 
8
8
  def call(env)
9
- NimbleNodes.monitor(env)
9
+ NimbleNodes::Dynos.monitor(env) if NimbleNodes::Dynos.monitor?
10
10
  # now, execute the request using our Rails app
11
11
  response = @app.call(env)
12
12
  end
@@ -0,0 +1,17 @@
1
+ module NimbleNodes
2
+ module Rails
3
+ module Filter
4
+
5
+ # Use as a before_filter
6
+ def monitor_heroku_app
7
+ NimbleNodes::Dynos.monitor(request.env) if NimbleNodes::Dynos.monitor?
8
+ end
9
+
10
+
11
+ end
12
+ end
13
+
14
+
15
+ end
16
+
17
+ ActionController::Base.send(:include, NimbleNodes::Rails::Filter)
@@ -2,11 +2,6 @@ module NimbleNodes
2
2
 
3
3
  class Report
4
4
 
5
-
6
- def self.path
7
- "/#{ENV['NN_APP_NAME']}/dynos/reports.json"
8
- end
9
-
10
5
  def initialize(env)
11
6
  @dynos_in_use = env['HTTP_X_HEROKU_DYNOS_IN_USE'].to_i
12
7
  @request_queue_depth = env['HTTP_X_HEROKU_QUEUE_DEPTH'].to_i
@@ -16,29 +11,36 @@ module NimbleNodes
16
11
  params = {
17
12
  :dynos_in_use => @dynos_in_use,
18
13
  :request_queue_size => @request_queue_depth }
19
- NimbleNodes::Server.post(self.class.path, params)
14
+ NimbleNodes::Server.post('/dynos/reports.json', params)
20
15
  end
21
16
 
17
+ # returns true if report needs to be posted to server
22
18
  def post?
23
- return false unless NimbleNodes.installed?
24
19
  return true
25
- return false if NimbleNodes.paused?
26
- dynos_maxed_out? or queue_depth_too_long? or unused_dynos?
20
+ dynos_maxed_out? or queue_depth_too_long? or queue_depth_too_short? or idle_dynos?
27
21
  end
28
22
 
23
+ # returns true if app is using all available dynos
29
24
  def dynos_maxed_out?
30
25
  return false if @dynos_in_use.nil?
31
- @dynos_in_use >= Dynos.max
26
+ @dynos_in_use >= NimbleNodes::Dynos.max
32
27
  end
33
-
28
+
29
+ # returns true if queue depth is over max
34
30
  def queue_depth_too_long?
35
31
  return false if @request_queue_depth.nil?
36
- @request_queue_depth > Dynos.max_request_queue
32
+ @request_queue_depth > NimbleNodes::Dynos.max_request_queue
33
+ end
34
+
35
+ def queue_depth_too_short?
36
+ return false if @request_queue_depth.nil?
37
+ @request_queue_depth < NimbleNodes::Dynos.min_request_queue
37
38
  end
38
39
 
39
- def unused_dynos?
40
+ # returns true if app isn't using all of it's dynos
41
+ def idle_dynos?
40
42
  return false if @dynos_in_use.nil?
41
- @dynos_in_use < Dynos.size
43
+ @dynos_in_use < NimbleNodes::Dynos.size
42
44
  end
43
45
 
44
46
  end
@@ -4,18 +4,63 @@ module NimbleNodes
4
4
 
5
5
  class Server
6
6
 
7
- def self.post(path,args)
8
- url = URI.parse(url_to(path))
9
- request = Net::HTTP::Post.new(url.path)
10
- request.set_form_data({:token => ENV['NN_APP_TOKEN'], :json => args.to_json, :created_at => Time.now })
11
- response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)}
7
+ #= HTTP Requests
8
+ # GETs and POSTs both add App.token to request automatically
9
+
10
+ def self.get(path)
11
+ begin
12
+ path = NimbleNodes::App.path(path)
13
+ uri = uri_with_token(path)
14
+ path = uri.route_from(NimbleNodes::Server.url[0..-2]).to_s
15
+ request = Net::HTTP::Get.new(path)
16
+ return Net::HTTP.start(uri.host, uri.port) {|http| http.request(request)}.body
17
+ rescue
18
+ return nil
19
+ end
20
+ end
21
+
22
+
23
+ def self.post(path,params)
24
+ begin
25
+ path = NimbleNodes::App.path(path)
26
+ uri = uri(path)
27
+ request = Net::HTTP::Post.new(uri.path)
28
+ request.set_form_data({:token => NimbleNodes::App.token, :json => params.to_json, :created_at => Time.now })
29
+ return Net::HTTP.start(uri.host, uri.port) {|http| http.request(request)}
30
+ rescue
31
+ return nil
32
+ end
33
+ end
34
+
35
+
36
+ #= Domain & URLs
37
+
38
+ # set ENV variable in development to override production domain
39
+ def self.domain
40
+ ENV['NIMBLE_NODES_DOMAIN'].nil? ? 'nimblenodes.com' : ENV['NIMBLE_NODES_DOMAIN']
12
41
  end
13
42
 
14
- def self.url_to(path)
15
- 'http://' + ENV['NN_SERVER_DOMAIN'] + path
16
- # 'http://nimblenodes.com' + path
43
+ # returns string for url to given path at server
44
+ def self.url(path='/')
45
+ 'http://' + domain + path
17
46
  end
18
47
 
48
+ # returns parsed URI for given path at server
49
+ def self.uri(path)
50
+ URI.parse(url(path))
51
+ end
52
+
53
+ # returns parsed URI with App.token in query
54
+ def self.uri_with_token(path)
55
+ uri = uri(path)
56
+ query = (uri.query || '').split('&')
57
+ query.push("token=#{NimbleNodes::App.token}")
58
+ uri.query = query.join('&')
59
+ uri
60
+ end
61
+
62
+
63
+
19
64
  end
20
65
 
21
66
  end
@@ -0,0 +1,51 @@
1
+ module NimbleNodes
2
+
3
+ class Settings
4
+
5
+ #= Setting accessor
6
+ #= allows NimbleNodes::Settings to be treated as a hash
7
+ # shortcut for accessing NimbleNodes.settings cache
8
+ def self.[](key)
9
+ cache[key]
10
+ end
11
+
12
+ private
13
+
14
+ #= Cache
15
+ # settings are fetched once from server and cached in global constant
16
+
17
+ # returns hash of settings from cache or fetched from nimblenodes.com
18
+ def self.cache
19
+ return CACHE if cache? and fresh_cache?
20
+ const_set('CACHE',NimbleNodes::Settings.fetch_from_server)
21
+ end
22
+
23
+ #== Fetch from server
24
+
25
+ # returns hash from parsed server response
26
+ def self.fetch_from_server
27
+ response = NimbleNodes::Server.get("/settings.json")
28
+ return {} if response.nil?
29
+ JSON[response].merge('fetched_at' => Time.now)
30
+ end
31
+
32
+ #== Cache Inspectors
33
+
34
+ # returns true if local settings have been set
35
+ def self.cache?
36
+ defined?(NimbleNodes::Settings::CACHE) and !NimbleNodes::Settings::CACHE.nil? and !NimbleNodes::Settings::CACHE.empty?
37
+ end
38
+
39
+ def self.fresh_cache?
40
+ fetched_at = CACHE['fetched_at']
41
+ return false if fetched_at.nil?
42
+ age = Time.now.to_i - fetched_at.to_i
43
+ five_minutes = 300
44
+ age > five_minutes
45
+ end
46
+
47
+
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,35 @@
1
+ module NimbleNodes
2
+
3
+ module Workers
4
+
5
+ def self.active?
6
+ ENV.has_key?('NN_WORKERS_POOL_ACTIVE')
7
+ end
8
+
9
+ def self.size
10
+ ENV['NN_WORKERS_POOL_SIZE']
11
+ end
12
+
13
+ def self.min
14
+ ENV['NN_WORKERS_POOL_MIN']
15
+ end
16
+
17
+ def self.max
18
+ ENV['NN_WORKERS_POOL_MAX']
19
+ end
20
+
21
+ def self.min
22
+ ENV['NN_WORKERS_POOL_MIN']
23
+ end
24
+
25
+ def self.min_job_queue
26
+ ENV['NN_WORKERS_JOB_QUEUE_MIN']
27
+ end
28
+
29
+ def self.max_job_queue
30
+ ENV['NN_WORKERS_JOB_QUEUE_MAX']
31
+ end
32
+
33
+ end
34
+
35
+ end
data/lib/nimble_nodes.rb CHANGED
@@ -1,36 +1,34 @@
1
+ require 'json'
2
+
1
3
  module NimbleNodes
2
4
 
3
- # returns array of files
4
- def self.files
5
- files = %w(dynos report server)
6
- files.push NimbleNodes.legacy? ? 'filter' : 'middleware'
7
- files
8
- end
9
-
5
+ #= Check Rails version
10
6
  # returns true if gem is loaded in a pre 2.3 version of rails
11
7
  def self.legacy?
12
8
  defined?(RAILS_GEM_VERSION) and RAILS_GEM_VERSION.slice(0..2).to_f < 2.3
13
- end
9
+ end
14
10
 
15
- #= Monitoring
16
- # pass over the hash containing Rack env variables
17
- # a Report will be created and posted if neccessary
18
- def self.monitor(env)
19
- report = NimbleNodes::Report.new(env)
20
- report.post if report.post?
11
+ #= App status inspectors
12
+ def self.active?
13
+ NimbleNodes::App.token? and !NimbleNodes.paused?
21
14
  end
22
15
 
23
- def self.installed?
24
- not ENV['NN_SERVER_DOMAIN'].nil?
16
+ def self.paused?
17
+ not NimbleNodes::Settings[:paused_at].nil?
25
18
  end
26
19
 
27
- def self.paused?
28
- not ENV['NN_APP_PAUSED_AT'].nil?
20
+
21
+
22
+ def self.lib_path(path='')
23
+ File.dirname(__FILE__) + '/nimble_nodes' + path
29
24
  end
30
25
 
31
26
  end
32
27
 
33
- NimbleNodes.files.each { |file| require File.dirname(__FILE__) + "/nimble_nodes/#{file}" }
28
+ files = %w(app settings dynos workers report server)
29
+ files.each { |file| require NimbleNodes.lib_path('/' + file) }
30
+
31
+ require NimbleNodes::App.reporter
34
32
 
35
33
 
36
34
 
data/nimble_nodes.gemspec CHANGED
@@ -5,12 +5,12 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{nimble_nodes}
8
- s.version = "0.1.9"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jordan Glasner"]
12
- s.date = %q{2010-03-23}
13
- s.description = %q{automatically scales dynos and workers at Heroku}
12
+ s.date = %q{2010-04-04}
13
+ s.description = %q{coming soon}
14
14
  s.email = %q{jordan@digitalignition.com}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
@@ -24,23 +24,32 @@ Gem::Specification.new do |s|
24
24
  "Rakefile",
25
25
  "VERSION",
26
26
  "lib/nimble_nodes.rb",
27
+ "lib/nimble_nodes/app.rb",
27
28
  "lib/nimble_nodes/dynos.rb",
28
- "lib/nimble_nodes/filter.rb",
29
29
  "lib/nimble_nodes/middleware.rb",
30
+ "lib/nimble_nodes/rails/filter.rb",
30
31
  "lib/nimble_nodes/report.rb",
31
32
  "lib/nimble_nodes/server.rb",
33
+ "lib/nimble_nodes/settings.rb",
34
+ "lib/nimble_nodes/workers.rb",
32
35
  "nimble_nodes.gemspec",
33
36
  "test/helper.rb",
34
- "test/test_nimble_nodes.rb"
37
+ "test/unit/test_app.rb",
38
+ "test/unit/test_dynos.rb",
39
+ "test/unit/test_nimble_nodes.rb",
40
+ "test/unit/test_settings.rb"
35
41
  ]
36
42
  s.homepage = %q{http://github.com/glasner/nimble_nodes}
37
43
  s.rdoc_options = ["--charset=UTF-8"]
38
44
  s.require_paths = ["lib"]
39
45
  s.rubygems_version = %q{1.3.5}
40
- s.summary = %q{gem for connecting apps to the NimbleNodes server}
46
+ s.summary = %q{coming soon}
41
47
  s.test_files = [
42
48
  "test/helper.rb",
43
- "test/test_nimble_nodes.rb"
49
+ "test/unit/test_app.rb",
50
+ "test/unit/test_dynos.rb",
51
+ "test/unit/test_nimble_nodes.rb",
52
+ "test/unit/test_settings.rb"
44
53
  ]
45
54
 
46
55
  if s.respond_to? :specification_version then
@@ -49,11 +58,20 @@ Gem::Specification.new do |s|
49
58
 
50
59
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
51
60
  s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
61
+ s.add_development_dependency(%q<mocha>, [">= 0"])
62
+ s.add_development_dependency(%q<fakeweb>, [">= 0"])
63
+ s.add_runtime_dependency(%q<json>, [">= 0"])
52
64
  else
53
65
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
66
+ s.add_dependency(%q<mocha>, [">= 0"])
67
+ s.add_dependency(%q<fakeweb>, [">= 0"])
68
+ s.add_dependency(%q<json>, [">= 0"])
54
69
  end
55
70
  else
56
71
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
72
+ s.add_dependency(%q<mocha>, [">= 0"])
73
+ s.add_dependency(%q<fakeweb>, [">= 0"])
74
+ s.add_dependency(%q<json>, [">= 0"])
57
75
  end
58
76
  end
59
77
 
data/test/helper.rb CHANGED
@@ -1,10 +1,11 @@
1
1
  require 'rubygems'
2
2
  require 'test/unit'
3
+
3
4
  require 'shoulda'
5
+ require 'mocha'
6
+ require 'fakeweb'
4
7
 
5
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
- $LOAD_PATH.unshift(File.dirname(__FILE__))
7
- require 'nimble_nodes'
8
+ require File.expand_path(File.dirname(__FILE__)) + '/../lib/nimble_nodes'
8
9
 
9
10
  class Test::Unit::TestCase
10
11
  end
@@ -0,0 +1,102 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/../helper'
2
+
3
+ class TestApp < Test::Unit::TestCase
4
+
5
+ context "An App" do
6
+
7
+ setup { @module = NimbleNodes::App }
8
+
9
+ context "on Rails" do
10
+
11
+ setup { @module.stubs(:rails?).returns(true) }
12
+
13
+ context "2.3 or later" do
14
+ setup { @module.stubs(:rails_version).returns(2.3) }
15
+
16
+ should "not use rails before_filter" do
17
+ assert(!@module.use_rails_filter?)
18
+ end
19
+
20
+ should "return NimbleNodes::Middleware as reporter" do
21
+ assert_equal 'middleware', @module.reporter.split('/').last
22
+ end
23
+
24
+ end
25
+
26
+ context "prior to 2.3" do
27
+ setup { NimbleNodes::App.stubs(:rails_version).returns(2.2) }
28
+
29
+ should "use rails before_filter" do
30
+ assert(@module.use_rails_filter?)
31
+ end
32
+
33
+ should "return NimbleNodes::Filter as reporter" do
34
+ assert_equal 'filter', @module.reporter.split('/').last
35
+ end
36
+
37
+ end
38
+
39
+
40
+ end
41
+
42
+ context "off Rails" do
43
+
44
+ should "return false for rails?" do
45
+ # we're not in Rails so this works
46
+ assert_equal false, @module.rails?
47
+ end
48
+
49
+ should "return NimbleNodes::Middleware as reporter" do
50
+ assert_equal 'middleware', @module.reporter.split('/').last
51
+ end
52
+
53
+ end
54
+
55
+
56
+ context "installed at NimbleNodes" do
57
+
58
+ setup {
59
+ ENV['NIMBLE_NODES_APP_NAME'] = 'nimble-nodes-test'
60
+ ENV['NIMBLE_NODES_APP_TOKEN'] = 'test'
61
+ }
62
+
63
+ should "return name from ENV" do
64
+ assert_equal ENV['NIMBLE_NODES_APP_NAME'], @module.name
65
+ end
66
+
67
+ should "return token from ENV" do
68
+ assert_equal ENV['NIMBLE_NODES_APP_TOKEN'], @module.token
69
+ end
70
+
71
+ should "return true for token?" do
72
+ assert @module.token?
73
+ end
74
+
75
+ should "return relative path at NN server" do
76
+ assert_equal '/nimble-nodes-test/', @module.path
77
+ end
78
+
79
+ should "return relative path to app resource for given path" do
80
+ assert_equal '/nimble-nodes-test/dynos', @module.path('/dynos')
81
+ end
82
+
83
+
84
+ end
85
+
86
+ context "not installed at NimbleNodes" do
87
+
88
+ setup {
89
+ ENV['NIMBLE_NODES_APP_NAME'] = nil
90
+ ENV['NIMBLE_NODES_APP_TOKEN'] = nil
91
+ }
92
+
93
+ should "return false for token?" do
94
+ assert_equal false, @module.token?
95
+ end
96
+
97
+ end
98
+
99
+
100
+ end
101
+
102
+ end
@@ -0,0 +1,97 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/../helper'
2
+
3
+ class Test::Unit::TestCase
4
+
5
+ def self.should_not_raise_anything_when_monitored
6
+ should "not raise any exceptions when sent :monitored?" do
7
+ assert_nothing_raised { @module.monitor? }
8
+ NimbleNodes::Server.stubs(:post).returns(nil)
9
+ assert_nothing_raised { @module.monitor({}) }
10
+ end
11
+ end
12
+
13
+ def self.should_not_be_monitored
14
+ should "not be monitored" do
15
+ assert_equal false, @module.monitor?
16
+ end
17
+ end
18
+
19
+
20
+ end
21
+
22
+
23
+ class TestDynos < Test::Unit::TestCase
24
+
25
+ context "Dynos" do
26
+
27
+ setup {
28
+ @module = NimbleNodes::Dynos
29
+ }
30
+
31
+ context "App setup at NimbleNodes" do
32
+
33
+ setup {
34
+ NimbleNodes::App.stubs({
35
+ :name => 'nimble-nodes-test',
36
+ :token => 'token'
37
+ })
38
+ @module.stubs(:settings).returns({
39
+ 'paused_at' => nil,
40
+ 'min' => 1,
41
+ 'max' => 2
42
+ })
43
+ }
44
+
45
+ context "and App not paused" do
46
+ setup { NimbleNodes.stubs(:paused?).returns(false) }
47
+
48
+ should "be monitored" do
49
+ assert @module.monitor?
50
+ end
51
+
52
+ should_not_raise_anything_when_monitored
53
+
54
+ context "and Dynos paused" do
55
+ setup {
56
+ @module.stubs(:settings).returns({
57
+ 'paused_at' => Time.now,
58
+ 'min' => 1,
59
+ 'max' => 2
60
+ })
61
+ }
62
+
63
+ should "be paused" do
64
+ assert @module.paused?
65
+ end
66
+
67
+ should_not_be_monitored
68
+ should_not_raise_anything_when_monitored
69
+
70
+ end
71
+
72
+
73
+ end
74
+
75
+ context "and App paused" do
76
+ setup { NimbleNodes.stubs(:paused?).returns(true) }
77
+ should_not_be_monitored
78
+ should_not_raise_anything_when_monitored
79
+
80
+ end
81
+
82
+
83
+ end
84
+
85
+ context "App *not* setup at NimbleNodes.com" do
86
+
87
+ should_not_be_monitored
88
+
89
+ should_not_raise_anything_when_monitored
90
+
91
+
92
+ end
93
+
94
+
95
+ end
96
+
97
+ end
@@ -0,0 +1,80 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/../helper'
2
+
3
+ class TestNimbleNodes < Test::Unit::TestCase
4
+
5
+
6
+ context "NimbleNodes module" do
7
+ setup { @module = NimbleNodes }
8
+
9
+ context "in a Rails app" do
10
+
11
+ setup { NimbleNodes::App.stubs(:rails?).returns(true) }
12
+
13
+ context "pre 2.3" do
14
+ setup { NimbleNodes::App.stubs(:rails_version).returns(2.2) }
15
+
16
+ should "use NimbleNodes::Filter as reporter" do
17
+ assert_equal 'filter', @module.reporter.split('/').last
18
+ end
19
+
20
+ end
21
+
22
+ context "2.3 or later" do
23
+ setup { NimbleNodes::App.stubs(:rails_version).returns(2.3) }
24
+
25
+ should "use NimbleNodes::Middleware as reporter" do
26
+ assert_equal 'middleware', @module.reporter.split('/').last
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ context "in a non-Rails app" do
34
+ setup { NimbleNodes::App.stubs(:rails?).returns(false) }
35
+
36
+ should "use NimbleNodes::Middleware" do
37
+ assert_equal 'middleware8', @module.reporter.split('/').last
38
+ end
39
+
40
+ end
41
+
42
+ context "App installed at NimbleNodes" do
43
+
44
+ setup {
45
+ NimbleNodes::App.stubs({
46
+ :name => 'nimble-nodes-test',
47
+ :token => 'token'
48
+ })
49
+ }
50
+
51
+ context "not paused" do
52
+
53
+ setup {
54
+ @module.stubs(:paused?).returns(false)
55
+ }
56
+
57
+ should "be active" do
58
+ assert @module.active?
59
+ end
60
+ end
61
+
62
+ context "paused" do
63
+
64
+ setup {
65
+ @module.stubs(:paused?).returns(true)
66
+ }
67
+
68
+ should "be not active" do
69
+ assert(!@module.active?)
70
+ end
71
+ end
72
+
73
+ end
74
+
75
+
76
+ end
77
+
78
+
79
+
80
+ end
@@ -0,0 +1,93 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/../helper'
2
+
3
+ class Test::Unit::TestCase
4
+
5
+ def self.should_not_raise_any_errors_when_fetching_from_server
6
+ should "not raise any errors when fetching from server" do
7
+ assert_nothing_raised { @module.fetch_from_server }
8
+ end
9
+ end
10
+
11
+ def self.should_not_raise_any_errors_on_unknown_keys
12
+ should "not raise errors on any unknown keys" do
13
+ assert_nothing_raised { @module.cache['bogus-key'] }
14
+ end
15
+ end
16
+
17
+
18
+ end
19
+
20
+ class TestSettings < Test::Unit::TestCase
21
+
22
+ context "Settings" do
23
+
24
+ setup {
25
+ @module = NimbleNodes::Settings
26
+ @module.send(:remove_const,'CACHE') if defined?(@module::CACHE)
27
+ }
28
+
29
+ context "App is installed at NimbleNodes.com" do
30
+ setup do
31
+ NimbleNodes::App.stubs({
32
+ :name => "nimble-nodes-test",
33
+ :token => 'test'
34
+ })
35
+ end
36
+
37
+ context "server responds with JSON" do
38
+
39
+ setup {
40
+ @json = '{"paused_at":null,"dynos_pool":{"size":1,"paused_at":null,"max":1,"request_queue":{"max":5,"min":0},"min":1}}'
41
+ @parsed = JSON[@json]
42
+ NimbleNodes::Server.expects(:get).returns(@json)
43
+ }
44
+
45
+ should "only fetch from server once" do
46
+ @module.expects(:fetch_from_server).once
47
+ @module['paused_at']
48
+ @module['dynos_pool']
49
+ end
50
+
51
+ should "save parsed parsed response in cache" do
52
+ cached = @module.cache
53
+ cached.delete('fetched_at')
54
+ assert_equal @parsed, cached
55
+ end
56
+
57
+ should "add fetched_at to server response" do
58
+ assert_not_nil @module['fetched_at']
59
+ end
60
+
61
+ should_not_raise_any_errors_on_unknown_keys
62
+
63
+ should_not_raise_any_errors_when_fetching_from_server
64
+
65
+ end
66
+
67
+ context "server responds with error" do
68
+ setup { NimbleNodes::Server.expects(:get).once.returns(nil) }
69
+ should_not_raise_any_errors_on_unknown_keys
70
+ should_not_raise_any_errors_when_fetching_from_server
71
+ end
72
+
73
+ end
74
+
75
+ context "App is *not* installed at NimbleNodes.com" do
76
+
77
+ setup {
78
+ NimbleNodes::App.stubs({
79
+ :name => nil,
80
+ :token => nil
81
+ })
82
+ NimbleNodes::Server.expects(:get).returns(nil)
83
+ }
84
+
85
+ should_not_raise_any_errors_on_unknown_keys
86
+ should_not_raise_any_errors_when_fetching_from_server
87
+
88
+ end
89
+
90
+
91
+ end
92
+
93
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nimble_nodes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Glasner
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-03-23 00:00:00 -04:00
12
+ date: 2010-04-04 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,7 +22,37 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: "0"
24
24
  version:
25
- description: automatically scales dynos and workers at Heroku
25
+ - !ruby/object:Gem::Dependency
26
+ name: mocha
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: fakeweb
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: json
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ description: coming soon
26
56
  email: jordan@digitalignition.com
27
57
  executables: []
28
58
 
@@ -39,14 +69,20 @@ files:
39
69
  - Rakefile
40
70
  - VERSION
41
71
  - lib/nimble_nodes.rb
72
+ - lib/nimble_nodes/app.rb
42
73
  - lib/nimble_nodes/dynos.rb
43
- - lib/nimble_nodes/filter.rb
44
74
  - lib/nimble_nodes/middleware.rb
75
+ - lib/nimble_nodes/rails/filter.rb
45
76
  - lib/nimble_nodes/report.rb
46
77
  - lib/nimble_nodes/server.rb
78
+ - lib/nimble_nodes/settings.rb
79
+ - lib/nimble_nodes/workers.rb
47
80
  - nimble_nodes.gemspec
48
81
  - test/helper.rb
49
- - test/test_nimble_nodes.rb
82
+ - test/unit/test_app.rb
83
+ - test/unit/test_dynos.rb
84
+ - test/unit/test_nimble_nodes.rb
85
+ - test/unit/test_settings.rb
50
86
  has_rdoc: true
51
87
  homepage: http://github.com/glasner/nimble_nodes
52
88
  licenses: []
@@ -74,7 +110,10 @@ rubyforge_project:
74
110
  rubygems_version: 1.3.5
75
111
  signing_key:
76
112
  specification_version: 3
77
- summary: gem for connecting apps to the NimbleNodes server
113
+ summary: coming soon
78
114
  test_files:
79
115
  - test/helper.rb
80
- - test/test_nimble_nodes.rb
116
+ - test/unit/test_app.rb
117
+ - test/unit/test_dynos.rb
118
+ - test/unit/test_nimble_nodes.rb
119
+ - test/unit/test_settings.rb
@@ -1,15 +0,0 @@
1
- module NimbleNodes
2
-
3
- module Filter
4
-
5
- # Use as a before_filter
6
- def monitor_heroku_app
7
- NimbleNodes.monitor(request.env)
8
- end
9
-
10
-
11
- end
12
-
13
- end
14
-
15
- ActionController::Base.send(:include, NimbleNodes::Filter)
@@ -1,7 +0,0 @@
1
- require 'helper'
2
-
3
- class TestNimbleNodes < Test::Unit::TestCase
4
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
6
- end
7
- end