nimble_nodes 0.1.9 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +5 -2
- data/VERSION +1 -1
- data/lib/nimble_nodes/app.rb +51 -0
- data/lib/nimble_nodes/dynos.rb +52 -3
- data/lib/nimble_nodes/middleware.rb +1 -1
- data/lib/nimble_nodes/rails/filter.rb +17 -0
- data/lib/nimble_nodes/report.rb +16 -14
- data/lib/nimble_nodes/server.rb +53 -8
- data/lib/nimble_nodes/settings.rb +51 -0
- data/lib/nimble_nodes/workers.rb +35 -0
- data/lib/nimble_nodes.rb +17 -19
- data/nimble_nodes.gemspec +25 -7
- data/test/helper.rb +4 -3
- data/test/unit/test_app.rb +102 -0
- data/test/unit/test_dynos.rb +97 -0
- data/test/unit/test_nimble_nodes.rb +80 -0
- data/test/unit/test_settings.rb +93 -0
- metadata +46 -7
- data/lib/nimble_nodes/filter.rb +0 -15
- data/test/test_nimble_nodes.rb +0 -7
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 = "
|
9
|
-
gem.description = "
|
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
|
+
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
|
data/lib/nimble_nodes/dynos.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
@@ -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)
|
data/lib/nimble_nodes/report.rb
CHANGED
@@ -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(
|
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
|
-
|
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
|
-
|
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
|
data/lib/nimble_nodes/server.rb
CHANGED
@@ -4,18 +4,63 @@ module NimbleNodes
|
|
4
4
|
|
5
5
|
class Server
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
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
|
-
#=
|
16
|
-
|
17
|
-
|
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.
|
24
|
-
not
|
16
|
+
def self.paused?
|
17
|
+
not NimbleNodes::Settings[:paused_at].nil?
|
25
18
|
end
|
26
19
|
|
27
|
-
|
28
|
-
|
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
|
-
|
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.
|
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-
|
13
|
-
s.description = %q{
|
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/
|
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{
|
46
|
+
s.summary = %q{coming soon}
|
41
47
|
s.test_files = [
|
42
48
|
"test/helper.rb",
|
43
|
-
"test/
|
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
|
-
|
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.
|
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-
|
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
|
-
|
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/
|
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:
|
113
|
+
summary: coming soon
|
78
114
|
test_files:
|
79
115
|
- test/helper.rb
|
80
|
-
- test/
|
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
|
data/lib/nimble_nodes/filter.rb
DELETED
data/test/test_nimble_nodes.rb
DELETED