flipper-mongo 0.2.1 → 0.2.2
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/Gemfile +1 -0
- data/lib/flipper/adapters/mongo/version.rb +1 -1
- data/lib/flipper/adapters/mongo_single_document.rb +30 -0
- data/lib/flipper/middleware/mongo_single_document_query_cache.rb +36 -0
- data/spec/flipper/adapters/mongo_single_document_spec.rb +55 -1
- data/spec/flipper/middleware/mongo_single_document_query_cache_spec.rb +121 -0
- metadata +9 -6
data/Gemfile
CHANGED
@@ -11,13 +11,43 @@ module Flipper
|
|
11
11
|
def initialize(collection, options = {})
|
12
12
|
@collection = collection
|
13
13
|
@options = options
|
14
|
+
@document_cache = false
|
14
15
|
end
|
15
16
|
|
16
17
|
def_delegators :document, :read, :write, :delete, :set_members, :set_add, :set_delete
|
17
18
|
|
19
|
+
def using_document_cache?
|
20
|
+
@document_cache == true
|
21
|
+
end
|
22
|
+
|
23
|
+
def document_cache=(value)
|
24
|
+
reset_document_cache
|
25
|
+
@document_cache = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def use_document_cache(&block)
|
29
|
+
original = @document_cache
|
30
|
+
@document_cache = true
|
31
|
+
yield
|
32
|
+
ensure
|
33
|
+
@document_cache = original
|
34
|
+
end
|
35
|
+
|
36
|
+
def reset_document_cache
|
37
|
+
@document = nil
|
38
|
+
end
|
39
|
+
|
18
40
|
private
|
19
41
|
|
20
42
|
def document
|
43
|
+
if @document_cache == true
|
44
|
+
@document ||= fresh_document
|
45
|
+
else
|
46
|
+
fresh_document
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def fresh_document
|
21
51
|
Document.new(@collection, :id => @options[:id])
|
22
52
|
end
|
23
53
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Flipper
|
2
|
+
module Middleware
|
3
|
+
class MongoSingleDocumentQueryCache
|
4
|
+
class Body
|
5
|
+
def initialize(target, adapter, original)
|
6
|
+
@target = target
|
7
|
+
@adapter = adapter
|
8
|
+
@original = original
|
9
|
+
end
|
10
|
+
|
11
|
+
def each(&block)
|
12
|
+
@target.each(&block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def close
|
16
|
+
@target.close if @target.respond_to?(:close)
|
17
|
+
ensure
|
18
|
+
@adapter.document_cache = @original
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(app, adapter)
|
23
|
+
@app = app
|
24
|
+
@adapter = adapter
|
25
|
+
end
|
26
|
+
|
27
|
+
def call(env)
|
28
|
+
original = @adapter.using_document_cache?
|
29
|
+
@adapter.document_cache = true
|
30
|
+
|
31
|
+
status, headers, body = @app.call(env)
|
32
|
+
[status, headers, Body.new(body, @adapter, original)]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -35,5 +35,59 @@ describe Flipper::Adapters::MongoSingleDocument do
|
|
35
35
|
collection.update criteria, updates, options
|
36
36
|
end
|
37
37
|
|
38
|
-
|
38
|
+
context "with cache" do
|
39
|
+
before do
|
40
|
+
subject.document_cache = true
|
41
|
+
end
|
42
|
+
|
43
|
+
it_should_behave_like 'a flipper adapter'
|
44
|
+
|
45
|
+
it "should only query mongo once until reloaded" do
|
46
|
+
collection.should_receive(:find_one).with(criteria).once.and_return({})
|
47
|
+
subject.read('foo')
|
48
|
+
subject.read('foo')
|
49
|
+
subject.read('foo')
|
50
|
+
subject.set_members('users')
|
51
|
+
|
52
|
+
subject.reset_document_cache
|
53
|
+
|
54
|
+
collection.should_receive(:find_one).with(criteria).once.and_return({})
|
55
|
+
subject.read('foo')
|
56
|
+
subject.read('foo')
|
57
|
+
subject.set_members('users')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "without cache" do
|
62
|
+
before do
|
63
|
+
subject.document_cache = false
|
64
|
+
end
|
65
|
+
|
66
|
+
it_should_behave_like 'a flipper adapter'
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#use_document_cache" do
|
70
|
+
it "turns cache on for block and restores to original after block" do
|
71
|
+
subject.using_document_cache?.should be_false
|
72
|
+
subject.use_document_cache do
|
73
|
+
subject.using_document_cache?.should be_true
|
74
|
+
end
|
75
|
+
subject.using_document_cache?.should be_false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#document_cache=" do
|
80
|
+
it "sets document cache" do
|
81
|
+
subject.document_cache = true
|
82
|
+
subject.using_document_cache?.should be_true
|
83
|
+
|
84
|
+
subject.document_cache = false
|
85
|
+
subject.using_document_cache?.should be_false
|
86
|
+
end
|
87
|
+
|
88
|
+
it "resets cached document" do
|
89
|
+
subject.should_receive(:reset_document_cache)
|
90
|
+
subject.document_cache = true
|
91
|
+
end
|
92
|
+
end
|
39
93
|
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'rack/test'
|
3
|
+
require 'flipper/middleware/mongo_single_document_query_cache'
|
4
|
+
|
5
|
+
describe Flipper::Middleware::MongoSingleDocumentQueryCache do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
|
8
|
+
let(:collection) { Mongo::Connection.new.db('testing')['testing'] }
|
9
|
+
let(:adapter) { Flipper::Adapters::MongoSingleDocument.new(collection) }
|
10
|
+
let(:flipper) { Flipper.new(adapter) }
|
11
|
+
|
12
|
+
class Enum < Struct.new(:iter)
|
13
|
+
def each(&b)
|
14
|
+
iter.call(&b)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:app) {
|
19
|
+
# ensure scoped for builder block, annoying...
|
20
|
+
instance = adapter
|
21
|
+
middleware = described_class
|
22
|
+
|
23
|
+
Rack::Builder.new do
|
24
|
+
use middleware, instance
|
25
|
+
|
26
|
+
map "/" do
|
27
|
+
run lambda {|env| [200, {}, []] }
|
28
|
+
end
|
29
|
+
|
30
|
+
map "/fail" do
|
31
|
+
run lambda {|env| raise "FAIL!" }
|
32
|
+
end
|
33
|
+
end.to_app
|
34
|
+
}
|
35
|
+
|
36
|
+
it "delegates" do
|
37
|
+
called = false
|
38
|
+
app = lambda { |env|
|
39
|
+
called = true
|
40
|
+
[200, {}, nil]
|
41
|
+
}
|
42
|
+
middleware = described_class.new app, adapter
|
43
|
+
middleware.call({})
|
44
|
+
called.should be_true
|
45
|
+
end
|
46
|
+
|
47
|
+
it "enables document cache during delegation" do
|
48
|
+
app = lambda { |env|
|
49
|
+
adapter.using_document_cache?.should be_true
|
50
|
+
[200, {}, nil]
|
51
|
+
}
|
52
|
+
middleware = described_class.new app, adapter
|
53
|
+
middleware.call({})
|
54
|
+
end
|
55
|
+
|
56
|
+
it "enables document cache for body each" do
|
57
|
+
app = lambda { |env|
|
58
|
+
[200, {}, Enum.new(lambda { |&b|
|
59
|
+
adapter.using_document_cache?.should be_true
|
60
|
+
b.call "hello"
|
61
|
+
})]
|
62
|
+
}
|
63
|
+
middleware = described_class.new app, adapter
|
64
|
+
body = middleware.call({}).last
|
65
|
+
body.each { |x| x.should eql('hello') }
|
66
|
+
end
|
67
|
+
|
68
|
+
it "disables document cache after body close" do
|
69
|
+
app = lambda { |env| [200, {}, []] }
|
70
|
+
middleware = described_class.new app, adapter
|
71
|
+
body = middleware.call({}).last
|
72
|
+
|
73
|
+
adapter.using_document_cache?.should be_true
|
74
|
+
body.close
|
75
|
+
adapter.using_document_cache?.should be_false
|
76
|
+
end
|
77
|
+
|
78
|
+
it "clears document cache after body close" do
|
79
|
+
app = lambda { |env| [200, {}, []] }
|
80
|
+
middleware = described_class.new app, adapter
|
81
|
+
body = middleware.call({}).last
|
82
|
+
adapter.write('hello', 'world')
|
83
|
+
|
84
|
+
adapter.instance_variable_get("@document").should_not be_nil
|
85
|
+
body.close
|
86
|
+
adapter.instance_variable_get("@document").should be_nil
|
87
|
+
end
|
88
|
+
|
89
|
+
it "really does cache" do
|
90
|
+
flipper[:stats].enable
|
91
|
+
|
92
|
+
collection.should_receive(:find_one).once.and_return({})
|
93
|
+
|
94
|
+
app = lambda { |env|
|
95
|
+
flipper[:stats].enabled?
|
96
|
+
flipper[:stats].enabled?
|
97
|
+
flipper[:stats].enabled?
|
98
|
+
flipper[:stats].enabled?
|
99
|
+
flipper[:stats].enabled?
|
100
|
+
flipper[:stats].enabled?
|
101
|
+
|
102
|
+
[200, {}, []]
|
103
|
+
}
|
104
|
+
middleware = described_class.new app, adapter
|
105
|
+
middleware.call({})
|
106
|
+
end
|
107
|
+
|
108
|
+
context "with a successful request" do
|
109
|
+
it "clears the document cache" do
|
110
|
+
adapter.should_receive(:reset_document_cache).twice
|
111
|
+
get '/'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context "when the request raises an error" do
|
116
|
+
it "clears the document cache" do
|
117
|
+
adapter.should_receive(:reset_document_cache).once
|
118
|
+
get '/fail' rescue nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flipper-mongo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: flipper
|
16
|
-
requirement: &
|
16
|
+
requirement: &70110164650060 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '0.2'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70110164650060
|
25
25
|
description: Mongo adapter for Flipper
|
26
26
|
email:
|
27
27
|
- nunemaker@gmail.com
|
@@ -41,9 +41,11 @@ files:
|
|
41
41
|
- lib/flipper/adapters/mongo/document.rb
|
42
42
|
- lib/flipper/adapters/mongo/version.rb
|
43
43
|
- lib/flipper/adapters/mongo_single_document.rb
|
44
|
+
- lib/flipper/middleware/mongo_single_document_query_cache.rb
|
44
45
|
- spec/flipper/adapters/mongo/document_spec.rb
|
45
46
|
- spec/flipper/adapters/mongo_single_document_spec.rb
|
46
47
|
- spec/flipper/adapters/mongo_spec.rb
|
48
|
+
- spec/flipper/middleware/mongo_single_document_query_cache_spec.rb
|
47
49
|
- spec/helper.rb
|
48
50
|
- spec/support/accessor_helpers.rb
|
49
51
|
homepage: http://jnunemaker.github.com/flipper-mongo
|
@@ -60,7 +62,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
60
62
|
version: '0'
|
61
63
|
segments:
|
62
64
|
- 0
|
63
|
-
hash:
|
65
|
+
hash: -3406714501289693291
|
64
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
67
|
none: false
|
66
68
|
requirements:
|
@@ -69,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
71
|
version: '0'
|
70
72
|
segments:
|
71
73
|
- 0
|
72
|
-
hash:
|
74
|
+
hash: -3406714501289693291
|
73
75
|
requirements: []
|
74
76
|
rubyforge_project:
|
75
77
|
rubygems_version: 1.8.10
|
@@ -80,5 +82,6 @@ test_files:
|
|
80
82
|
- spec/flipper/adapters/mongo/document_spec.rb
|
81
83
|
- spec/flipper/adapters/mongo_single_document_spec.rb
|
82
84
|
- spec/flipper/adapters/mongo_spec.rb
|
85
|
+
- spec/flipper/middleware/mongo_single_document_query_cache_spec.rb
|
83
86
|
- spec/helper.rb
|
84
87
|
- spec/support/accessor_helpers.rb
|