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.
- data/lib/heroku/readonly.rb +61 -0
- data/spec/readonly_spec.rb +72 -0
- data/spec/spec_helper.rb +15 -0
- metadata +145 -0
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|
+
|