heroku-readonly 0.0.1

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.
@@ -0,0 +1,61 @@
1
+ require 'rest_client'
2
+
3
+ module Heroku
4
+ class ReadOnly
5
+ def initialize(options={})
6
+ @enabled = false
7
+ @have_polled = false
8
+ @url = options[:url]
9
+ @time_between_retries = options[:time_between_retries] || 2
10
+ @write_cache = options[:write_cache]
11
+ @read_cache = options[:read_cache]
12
+ end
13
+
14
+ def check
15
+ Timeout.timeout(1) do
16
+ RestClient.get(@url) != 'ok'
17
+ end
18
+ rescue StandardError, Timeout::Error => e
19
+ true
20
+ end
21
+
22
+ def poll(attempt=1)
23
+ result = check
24
+ if (result == @enabled) || (attempt >= 3)
25
+ @have_polled = true
26
+ @enabled = result
27
+ write_to_cache
28
+ result
29
+ elsif attempt < 3
30
+ sleep(@time_between_retries)
31
+ poll(attempt+1)
32
+ end
33
+ end
34
+
35
+ def write_to_cache
36
+ if @write_cache
37
+ File.open(@write_cache, 'w') { |f| f.write(@enabled ? 'readonly' : 'ok') }
38
+ end
39
+ end
40
+
41
+ def read_from_cache
42
+ if !File.exists?(@read_cache)
43
+ true
44
+ elsif File.mtime(@read_cache) < Time.now - 60*5
45
+ true
46
+ else
47
+ File.read(@read_cache).strip != 'ok'
48
+ end
49
+ end
50
+
51
+ def enabled?
52
+ if @read_cache
53
+ read_from_cache
54
+ elsif !@have_polled
55
+ raise('never polled, no read_cache')
56
+ else
57
+ @enabled
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,72 @@
1
+ require "spec_helper"
2
+
3
+ describe Heroku::ReadOnly do
4
+ let(:url) { "http://foo" }
5
+ let(:readonly) { Heroku::ReadOnly.new(:url => url, :time_between_retries => 0) }
6
+
7
+ it "enabled if the response is a 200 'ok'" do
8
+ FakeWeb.register_uri(:get, url, :body => "ok")
9
+ readonly.poll.should be_false
10
+ readonly.enabled?.should be_false
11
+ end
12
+
13
+ it "enabled if the response has other text" do
14
+ FakeWeb.register_uri(:get, url, :body => "readonly")
15
+ readonly.poll.should be_true
16
+ readonly.enabled?.should be_true
17
+ end
18
+
19
+ it "enabled if the response has another status code" do
20
+ FakeWeb.register_uri(:get, url, :body => "ok", :status => 503)
21
+ readonly.poll.should be_true
22
+ readonly.enabled?.should be_true
23
+ end
24
+
25
+ it "only changes after fetching the same result 3 times" do
26
+ FakeWeb.register_uri(:get, url, :body => "ok")
27
+ readonly.poll.should be_false
28
+ FakeWeb.register_uri(:get, url, [
29
+ { :body => "readonly" },
30
+ { :body => "readonly" },
31
+ { :body => "ok" }
32
+ ])
33
+ readonly.poll.should be_false
34
+ readonly.enabled?.should be_false
35
+ end
36
+
37
+ context "caching" do
38
+ before do
39
+ FakeWeb.register_uri(:get, url, :body => "ok")
40
+ end
41
+
42
+ let(:cache) { "/tmp/read_only_spec" }
43
+ let(:readonly_write) { Heroku::ReadOnly.new(:url => url, :write_cache => cache, :time_between_retries => 0) }
44
+ let(:readonly_read) { Heroku::ReadOnly.new(:read_cache => cache) }
45
+
46
+ before(:each) do
47
+ File.unlink(cache) if File.exists?(cache)
48
+ end
49
+
50
+ it "enabled if the cache doesn't exist" do
51
+ readonly_read.enabled?.should be_true
52
+ end
53
+
54
+ it "enabled if the cache is old" do
55
+ readonly_write.poll.should be_false
56
+ old = Time.now - 60*60
57
+ File.utime(old, old, cache)
58
+ readonly_read.enabled?.should be_true
59
+ end
60
+
61
+ it "enabled if the cache has non-disabled text" do
62
+ FakeWeb.register_uri(:get, url, :body => "readonly")
63
+ readonly_write.poll.should be_true
64
+ readonly_read.enabled?.should be_true
65
+ end
66
+
67
+ it "not enabled if the cache has disabled text" do
68
+ readonly_write.poll.should be_false
69
+ readonly_read.enabled?.should be_false
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,15 @@
1
+ require "rspec/core"
2
+ require "rspec/expectations"
3
+
4
+ require "rubygems"
5
+ require "fakeweb"
6
+
7
+ $:.unshift "#{File.dirname(__FILE__)}/../lib/heroku"
8
+ require "readonly"
9
+
10
+ RSpec.configure do |c|
11
+ c.run_all_when_everything_filtered = true
12
+ c.filter_run :focused => true
13
+ c.alias_example_to :fit, :focused => true
14
+ c.color_enabled = true
15
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: heroku-readonly
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Heroku
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-15 00:00:00 -08:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rake
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: rspec-core
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 2
41
+ - 0
42
+ - 1
43
+ version: 2.0.1
44
+ type: :development
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec-expectations
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 2
55
+ - 0
56
+ - 1
57
+ version: 2.0.1
58
+ type: :development
59
+ version_requirements: *id003
60
+ - !ruby/object:Gem::Dependency
61
+ name: rspec-mocks
62
+ prerelease: false
63
+ requirement: &id004 !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 2
69
+ - 0
70
+ - 1
71
+ version: 2.0.1
72
+ type: :development
73
+ version_requirements: *id004
74
+ - !ruby/object:Gem::Dependency
75
+ name: fakeweb
76
+ prerelease: false
77
+ requirement: &id005 !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ~>
80
+ - !ruby/object:Gem::Version
81
+ segments:
82
+ - 1
83
+ - 3
84
+ - 0
85
+ version: 1.3.0
86
+ type: :development
87
+ version_requirements: *id005
88
+ - !ruby/object:Gem::Dependency
89
+ name: rest-client
90
+ prerelease: false
91
+ requirement: &id006 !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ segments:
96
+ - 1
97
+ - 2
98
+ - 0
99
+ version: 1.2.0
100
+ type: :runtime
101
+ version_requirements: *id006
102
+ description:
103
+ email: support@heroku.com
104
+ executables: []
105
+
106
+ extensions: []
107
+
108
+ extra_rdoc_files: []
109
+
110
+ files:
111
+ - lib/heroku/readonly.rb
112
+ - spec/readonly_spec.rb
113
+ - spec/spec_helper.rb
114
+ has_rdoc: true
115
+ homepage: http://heroku.com/
116
+ licenses: []
117
+
118
+ post_install_message:
119
+ rdoc_options: []
120
+
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ segments:
135
+ - 0
136
+ version: "0"
137
+ requirements: []
138
+
139
+ rubyforge_project:
140
+ rubygems_version: 1.3.6
141
+ signing_key:
142
+ specification_version: 3
143
+ summary: Internal tool
144
+ test_files: []
145
+