mongoid-query_cache 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2c0ccfe940fad749e4ceafff08dc37a188506349
4
+ data.tar.gz: 02bfa64270f52dfa363a3f5cec8d0e6008593b69
5
+ SHA512:
6
+ metadata.gz: 72155e3fa5918d6dcd918b9288867f9a5b00a86b56c851c75a08b9ebd28f730aba400e958c384878dd24dabb0651bc09c8ec5dffb8c0908303acece8932b7afb
7
+ data.tar.gz: 5a3dc435fcdfbbc39ed2c6d062d608cba4427d9cfe94d987868e3c2666dc8c96d9d60295b85b2e9a83b4a96127cf0a7ceb94c0bf7932a5c1e7f1706463c0f939
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mongoid-query_cache.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Philip Claren
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Philip Claren
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ Mongoid3-Query-Cache
2
+ ====================
3
+
4
+ Backport of the Mongoid 4 QueryCache for Mongoid 3.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,233 @@
1
+ require 'mongoid/query_cache/version'
2
+ require 'mongoid/query_cache/railtie' if defined? Rails
3
+
4
+ module Mongoid
5
+
6
+ # A cache of database queries on a per-request basis.
7
+ #
8
+ module QueryCache
9
+ class << self
10
+
11
+ # Get the cached queries.
12
+ #
13
+ # @example Get the cached queries from the current thread.
14
+ # QueryCache.cache_table
15
+ #
16
+ # @return [ Hash ] The hash of cached queries.
17
+ #
18
+ def cache_table
19
+ Thread.current["[mongoid]:query_cache"] ||= {}
20
+ end
21
+
22
+ # Clear the query cache.
23
+ #
24
+ # @example Clear the cache.
25
+ # QueryCache.clear_cache
26
+ #
27
+ # @return [ nil ] Always nil.
28
+ #
29
+ def clear_cache
30
+ Thread.current["[mongoid]:query_cache"] = nil
31
+ end
32
+
33
+ # Set whether the cache is enabled.
34
+ #
35
+ # @example Set if the cache is enabled.
36
+ # QueryCache.enabled = true
37
+ #
38
+ # @param [ true, false ] value The enabled value.
39
+ #
40
+ def enabled=(value)
41
+ Thread.current["[mongoid]:query_cache:enabled"] = value
42
+ end
43
+
44
+ # Is the query cache enabled on the current thread?
45
+ #
46
+ # @example Is the query cache enabled?
47
+ # QueryCache.enabled?
48
+ #
49
+ # @return [ true, false ] If the cache is enabled.
50
+ #
51
+ def enabled?
52
+ !!Thread.current["[mongoid]:query_cache:enabled"]
53
+ end
54
+
55
+ # Execute the block while using the query cache.
56
+ #
57
+ # @example Execute with the cache.
58
+ # QueryCache.cache { collection.find }
59
+ #
60
+ # @return [ Object ] The result of the block.
61
+ #
62
+ def cache
63
+ enabled = QueryCache.enabled?
64
+ QueryCache.enabled = true
65
+ yield
66
+ ensure
67
+ QueryCache.enabled = enabled
68
+ end
69
+ end
70
+
71
+ # The middleware to be added to a rack application in order to activate the
72
+ # query cache.
73
+ #
74
+ class Middleware
75
+
76
+ # Instantiate the middleware.
77
+ #
78
+ # @example Create the new middleware.
79
+ # Middleware.new(app)
80
+ #
81
+ # @param [ Object ] app The rack applciation stack.
82
+ #
83
+ def initialize(app)
84
+ @app = app
85
+ end
86
+
87
+ # Execute the request, wrapping in a query cache.
88
+ #
89
+ # @example Execute the request.
90
+ # middleware.call(env)
91
+ #
92
+ # @param [ Object ] env The environment.
93
+ #
94
+ # @return [ Object ] The result of the call.
95
+ #
96
+ def call(env)
97
+ QueryCache.cache { @app.call(env) }
98
+ ensure
99
+ QueryCache.clear_cache
100
+ end
101
+ end
102
+
103
+ module Base # :nodoc:
104
+
105
+ def alias_query_cache_clear(*method_names)
106
+ method_names.each do |method_name|
107
+ class_eval <<-CODE, __FILE__, __LINE__ + 1
108
+ def #{method_name}_with_clear_cache(*args) # def upsert_with_clear_cache(*args)
109
+ QueryCache.clear_cache # QueryCache.clear_cache
110
+ #{method_name}_without_clear_cache(*args) # upsert_without_clear_cache(*args)
111
+ end # end
112
+ CODE
113
+
114
+ alias_method_chain method_name, :clear_cache
115
+ end
116
+ end
117
+ end
118
+
119
+ # Module to include in objects which need to wrap caching behaviour around
120
+ # them.
121
+ #
122
+ module Cacheable
123
+
124
+ private
125
+
126
+ def with_cache(context = :cursor, &block)
127
+ return yield unless QueryCache.enabled?
128
+ return yield if system_collection?
129
+ key = cache_key.push(context)
130
+
131
+ if QueryCache.cache_table.has_key?(key)
132
+ instrument(key) { QueryCache.cache_table[key] }
133
+ else
134
+ QueryCache.cache_table[key] = yield
135
+ end
136
+ end
137
+
138
+ def instrument(key, &block)
139
+ ActiveSupport::Notifications.instrument("query_cache.mongoid", key: key, &block)
140
+ end
141
+ end
142
+
143
+ # Adds behaviour around caching to a Moped Query object.
144
+ #
145
+ module Query
146
+ extend ActiveSupport::Concern
147
+ include Cacheable
148
+
149
+ included do
150
+ extend QueryCache::Base
151
+ alias_method_chain :cursor, :cache
152
+ alias_method_chain :first, :cache
153
+ alias_query_cache_clear :remove, :remove_all, :update, :update_all, :upsert
154
+ end
155
+
156
+ # Provide a wrapped query cache cursor.
157
+ #
158
+ # @example Get the wrapped caching cursor.
159
+ # query.cursor_with_cache
160
+ #
161
+ # @return [ CachedCursor ] The cached cursor.
162
+ #
163
+ def cursor_with_cache
164
+ CachedCursor.new(session, operation)
165
+ end
166
+
167
+ # Override first with caching.
168
+ #
169
+ # @example Get the first with a cache.
170
+ # query.first_with_cache
171
+ #
172
+ # @return [ Hash ] The first document.
173
+ #
174
+ def first_with_cache
175
+ with_cache(:first) do
176
+ first_without_cache
177
+ end
178
+ end
179
+
180
+ private
181
+
182
+ def cache_key
183
+ [ operation.database, operation.collection, operation.selector, operation.limit, operation.skip, operation.fields ]
184
+ end
185
+
186
+ def system_collection?
187
+ operation.collection =~ /^system./
188
+ end
189
+ end
190
+
191
+ # Adds behaviour to the query cache for collections.
192
+ #
193
+ module Collection
194
+ extend ActiveSupport::Concern
195
+
196
+ included do
197
+ extend QueryCache::Base
198
+ alias_query_cache_clear :insert
199
+ end
200
+ end
201
+
202
+ # A Cursor that attempts to load documents from memory first before hitting
203
+ # the database if the same query has already been executed.
204
+ #
205
+ class CachedCursor < Moped::Cursor
206
+ include Cacheable
207
+
208
+ # Override the loading of docs to attempt to fetch from the cache.
209
+ #
210
+ # @example Load the documents.
211
+ # cursor.load_docs
212
+ #
213
+ # @return [ Array<Hash> ] The documents.
214
+ #
215
+ def load_docs
216
+ with_cache { super }
217
+ end
218
+
219
+ private
220
+
221
+ def cache_key
222
+ [ @database, @collection, @selector, @options[:limit], @options[:skip], @options[:fields] ]
223
+ end
224
+
225
+ def system_collection?
226
+ @collection =~ /^system./
227
+ end
228
+ end
229
+ end
230
+ end
231
+
232
+ Moped::Query.send(:include, Mongoid::QueryCache::Query)
233
+ Moped::Collection.send(:include, Mongoid::QueryCache::Collection)
@@ -0,0 +1,7 @@
1
+ module Mongoid::QueryCache
2
+ class Railtie < Rails::Railtie
3
+ initializer 'mongoid.query_cache.insert_middleware' do |app|
4
+ app.config.middleware.use 'Mongoid::QueryCache::Middleware'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module Mongoid
2
+ module QueryCache
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mongoid/query_cache/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'mongoid-query_cache'
8
+ spec.version = Mongoid::QueryCache::VERSION
9
+ spec.authors = ['Philip Claren']
10
+ spec.email = ['philip.claren@googlemail.com']
11
+ spec.summary = 'Backport of the Mongoid 4 QueryCache for Mongoid 3.'
12
+ spec.description = 'Backport of the Mongoid 4 QueryCache for Mongoid 3.'
13
+ spec.homepage = ''
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.6'
22
+ spec.add_development_dependency 'rake', '~> 10.3'
23
+ spec.add_development_dependency 'rspec', '~> 2.13'
24
+
25
+ spec.add_dependency 'mongoid', '~> 3.1'
26
+ end
@@ -0,0 +1,8 @@
1
+ test:
2
+ sessions:
3
+ default:
4
+ database: mongoid_query_cache_test
5
+ hosts:
6
+ - localhost:27017
7
+ options:
8
+ consistency: :strong
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ class Band
4
+ include Mongoid::Document
5
+ end
6
+
7
+ describe Mongoid::QueryCache do
8
+
9
+ around do |spec|
10
+ Mongoid::QueryCache.clear_cache
11
+ Mongoid::QueryCache.cache { spec.run }
12
+ end
13
+
14
+ context 'when inserting an index' do
15
+
16
+ it 'does not cache the query' do
17
+ Mongoid::QueryCache.should_receive(:cache_table).never
18
+ Band.collection.indexes.create(name: 1)
19
+ end
20
+ end
21
+ end
22
+
23
+ describe Mongoid::QueryCache::Middleware do
24
+
25
+ let :middleware do
26
+ Mongoid::QueryCache::Middleware.new(app)
27
+ end
28
+
29
+ context 'when not touching mongoid on the app' do
30
+
31
+ let(:app) do
32
+ ->(env) { @enabled = Mongoid::QueryCache.enabled?; [200, env, "app"] }
33
+ end
34
+
35
+ it 'returns success' do
36
+ code, _ = middleware.call({})
37
+ expect(code).to eq(200)
38
+ end
39
+
40
+ it 'enableds the query cache' do
41
+ middleware.call({})
42
+ expect(@enabled).to be true
43
+ end
44
+ end
45
+
46
+ context 'when querying on the app' do
47
+
48
+ let(:app) do
49
+ ->(env) {
50
+ Band.all.to_a
51
+ [200, env, "app"]
52
+ }
53
+ end
54
+
55
+ it 'returns success' do
56
+ code, _ = middleware.call({})
57
+ expect(code).to eq(200)
58
+ end
59
+
60
+ it 'cleans the query cache after reponds' do
61
+ middleware.call({})
62
+ expect(Mongoid::QueryCache.cache_table).to be_empty
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,15 @@
1
+ # Configure Rails Environment
2
+ ENV['RACK_ENV'] = 'test'
3
+
4
+ require 'bundler/setup'
5
+ Bundler.setup
6
+
7
+ require 'mongoid'
8
+ require 'mongoid/query_cache'
9
+
10
+ Mongoid.load!(File.expand_path('../../spec/config/mongoid.yml', __FILE__))
11
+
12
+
13
+ RSpec.configure do |config|
14
+ # some (optional) config here
15
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongoid-query_cache
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Philip Claren
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.13'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.13'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mongoid
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.1'
69
+ description: Backport of the Mongoid 4 QueryCache for Mongoid 3.
70
+ email:
71
+ - philip.claren@googlemail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - Gemfile
79
+ - LICENSE
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - lib/mongoid/query_cache.rb
84
+ - lib/mongoid/query_cache/railtie.rb
85
+ - lib/mongoid/query_cache/version.rb
86
+ - mongoid-query_cache.gemspec
87
+ - spec/config/mongoid.yml
88
+ - spec/mongoid_query_cache_spec.rb
89
+ - spec/spec_helper.rb
90
+ homepage: ''
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.2.2
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Backport of the Mongoid 4 QueryCache for Mongoid 3.
114
+ test_files:
115
+ - spec/config/mongoid.yml
116
+ - spec/mongoid_query_cache_spec.rb
117
+ - spec/spec_helper.rb