Module: Sequel::Plugins::QueryCache::DatasetMethods
- Defined in:
- lib/sequel-query-cache/dataset_methods.rb
Constant Summary collapse
- CACHE_BY_DEFAULT_PROC =
lambda do |ds, opts| if ds.opts[:limit] && opts[:if_limit] return true if (opts[:if_limit] == true) || (opts[:if_limit] >= ds.opts[:limit]) end false end
Instance Method Summary collapse
- #cache_clear_on_update ⇒ Object
- #cache_clear_on_update=(v) ⇒ Object
-
#cache_del ⇒ Object
Deletes the cache value using the current dataset’s key and logs the action.
-
#cache_driver ⇒ Object
Returns the model’s cache driver.
-
#cache_get ⇒ Object
Gets the cache value using the current dataset’s key and logs the action.
-
#cache_key ⇒ Object
Returns the default cache key if a manual cache key has not been set.
-
#cache_key=(cache_key) ⇒ Object
Sets a manual cache key for a dataset that overrides the default MD5 hash.
-
#cache_options(opts = nil) ⇒ Object
Copies the model’s
cache_optionsand merges them with options provided byoptsif any are provided. -
#cache_set(value, opts = {}) ⇒ Object
Sets the cache value using the current dataset’s key and logs the action.
-
#cached(opts = nil) ⇒ Object
Clones the current dataset, sets it to be cached and returns the new dataset.
- #clear_cache_keys! ⇒ Object
-
#clone(opts = nil) ⇒ Object
Overrides the dataset’s existing clone method.
-
#default_cache_key ⇒ Object
Creates a default cache key, which is an MD5 base64 digest of the the literal select SQL with
Sequel:added as a prefix. -
#default_cached ⇒ Object
Clones the current dataset, returns the caching state to whatever would be default for that dataset and returns the new dataset.
-
#delete(&block) ⇒ Object
Overrides the dataset’s existing
deletemethod. -
#each ⇒ Object
Sets self as the source_dataset on a result if that result supports source datasets.
-
#fetch_rows(sql) ⇒ Object
Overrides the dataset’s existing
fetch_rowsmethod. -
#is_cacheable=(is_cacheable) ⇒ Object
Sets the value for
@is_cacheablewhich is used as the return value from #is_cacheable?. -
#is_cacheable? ⇒ Boolean
Determines whether or not a dataset should be cached.
-
#is_cacheable_by_default? ⇒ Boolean
Determines whether or not to cache a dataset based on the configuration settings of the plugin.
-
#not_cached ⇒ Object
Clones the current dataset, sets it to not be cached and returns the new dataset.
-
#update(values = {}, &block) ⇒ Object
Overrides the dataset’s existing
updatemethod.
Instance Method Details
#cache_clear_on_update ⇒ Object
176 177 178 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 176 def cache_clear_on_update @cache_clear_on_update.nil? ? true : @cache_clear_on_update end |
#cache_clear_on_update=(v) ⇒ Object
180 181 182 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 180 def cache_clear_on_update=(v) @cache_clear_on_update = !!v end |
#cache_del ⇒ Object
Deletes the cache value using the current dataset’s key and logs the action.
171 172 173 174 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 171 def cache_del db.log_info("CACHE DEL: #{cache_key}") cache_driver.del(cache_key) end |
#cache_driver ⇒ Object
Returns the model’s cache driver. – TODO: Caching should be modified to be a database/dataset extension with a tiny plugin for the models. However, this works just fine for now. ++
22 23 24 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 22 def cache_driver model.cache_driver end |
#cache_get ⇒ Object
Gets the cache value using the current dataset’s key and logs the action. The underlying driver should return nil in the event that there is no cached data. Also logs whether there was a hit or miss on the cache.
149 150 151 152 153 154 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 149 def cache_get db.log_info("CACHE GET: #{cache_key}") cached_rows = cache_driver.get(cache_key) db.log_info("CACHE #{cached_rows ? 'HIT' : 'MISS'}: #{cache_key}") cached_rows end |
#cache_key ⇒ Object
Returns the default cache key if a manual cache key has not been set. The cache key is used by the storage engines to retrieve cached data. The default will suffice in almost all instances.
123 124 125 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 123 def cache_key @cache_key || default_cache_key end |
#cache_key=(cache_key) ⇒ Object
Sets a manual cache key for a dataset that overrides the default MD5 hash. This key has no Sequel: prefix, so if that’s important, remember to add it manually.
Note: Setting the cache key manually is NOT inherited by cloned datasets since keys are presumed to be for the current dataset and any changes, such as where clauses or limits, should result in a new key. In general, you shouldn’t change the cache key unless you have a really good reason for doing so.
136 137 138 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 136 def cache_key=(cache_key) @cache_key = cache_key ? cache_key.to_s : nil end |
#cache_options(opts = nil) ⇒ Object
Copies the model’s cache_options and merges them with options provided by opts if any are provided. Returns the current cache_options.
@cache_options is cloned when the dataset is cloned.
30 31 32 33 34 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 30 def (opts=nil) ||= model. = .merge(opts) if opts end |
#cache_set(value, opts = {}) ⇒ Object
Sets the cache value using the current dataset’s key and logs the action. In general, this method should not be called directly. It’s exposed because model instances need access to it.
An opts hash can be passed to override any default options being sent to the driver. The most common use for this would be to modify the ttl for a cache. However, this should probably be done using #cached rather than doing anything directly via this method.
164 165 166 167 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 164 def cache_set(value, opts={}) db.log_info("CACHE SET: #{cache_key}") cache_driver.set(cache_key, value, opts.merge()) end |
#cached(opts = nil) ⇒ Object
Clones the current dataset, sets it to be cached and returns the new dataset. This is useful for chaining purposes:
dataset.where(column1: true).order(:column2).cached.all
In the above example, the data would always be pulled from the cache or cached if it wasn’t already. The value of @is_cacheable is cloned when a dataset is cloned, so the following example would also have the same result:
dataset.cached.where(column1: true).order(:column2).all
opts is passed to #cache_options on the new dataset.
81 82 83 84 85 86 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 81 def cached(opts=nil) c = clone c.(opts) c.is_cacheable = true c end |
#clear_cache_keys! ⇒ Object
140 141 142 143 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 140 def clear_cache_keys! remove_instance_variable(:@default_cache_key) if defined? @default_cache_key remove_instance_variable(:@cache_key) if defined? @cache_key end |
#clone(opts = nil) ⇒ Object
Overrides the dataset’s existing clone method. Clones the existing dataset but clears any manually set cache key and the memoized default cache key to ensure it’s regenerated by the new dataset.
247 248 249 250 251 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 247 def clone(opts=nil) c = super(opts) c.clear_cache_keys! c end |
#default_cache_key ⇒ Object
Creates a default cache key, which is an MD5 base64 digest of the the literal select SQL with Sequel: added as a prefix. This value is memoized because assembling the SQL string and hashing it every time this method gets called is obnoxious.
116 117 118 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 116 def default_cache_key @default_cache_key ||= "Sequel:#{Digest::MD5.base64digest(sql)}" end |
#default_cached ⇒ Object
Clones the current dataset, returns the caching state to whatever would be default for that dataset and returns the new dataset. See #cached for further details and examples.
Note: This is the “proper” way to clear @is_cacheable once it’s been set.
102 103 104 105 106 107 108 109 110 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 102 def default_cached if defined? @is_cacheable c = clone c.remove_instance_variable(:@is_cacheable) c else self end end |
#delete(&block) ⇒ Object
Overrides the dataset’s existing delete method. Deletes an existing cache after a successful delete.
194 195 196 197 198 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 194 def delete(&block) result = super cache_del if is_cacheable? result end |
#each ⇒ Object
Sets self as the source_dataset on a result if that result supports source datasets. While it can almost certainly be presumed the result will, if the dataset’s row_proc has been modified for some reason the result might be different than expected.
237 238 239 240 241 242 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 237 def each super do |r| r.source_dataset = self if r.respond_to? :source_dataset= yield r end end |
#fetch_rows(sql) ⇒ Object
Overrides the dataset’s existing fetch_rows method. If the dataset is cacheable it will do one of two things:
If a cache exists it will yield the cached rows rather query the database.
If a cache does not exist it will query the database, store the results in an array, cache those and then yield the results like the original method would have.
Note: If you’re using PostgreSQL, or another database where each iterates with the cursor rather over the dataset results, you’ll lose that functionality when caching is enabled for a query since the entire result is iterated first before it is yielded. If that behavior is important, remember to disable caching for that particular query.
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 215 def fetch_rows(sql) if is_cacheable? if cached_rows = cache_get # Symbolize the row keys before yielding as they're often strings # when the data is deserialized. Sequel doesn't play nice with # string keys. cached_rows.each{|r| yield r.reduce({}){|h,v| h[v[0].to_sym]=v[1]; h}} else cached_rows = [] super(sql){|r| cached_rows << r} cache_set(cached_rows) cached_rows.each{|r| yield r} end else super end end |
#is_cacheable=(is_cacheable) ⇒ Object
Sets the value for @is_cacheable which is used as the return value from #is_cacheable?. @is_cacheable is cloned when the dataset is cloned.
Note: In general, #cached and #not_cached should be used to set this value. This method exists primarily for their use.
64 65 66 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 64 def is_cacheable=(is_cacheable) @is_cacheable = !!is_cacheable end |
#is_cacheable? ⇒ Boolean
Determines whether or not a dataset should be cached. If @is_cacheable is set that value will be returned, otherwise the default value will be returned by #is_cacheable_by_default?
54 55 56 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 54 def is_cacheable? defined?(@is_cacheable) ? @is_cacheable : is_cacheable_by_default? end |
#is_cacheable_by_default? ⇒ Boolean
Determines whether or not to cache a dataset based on the configuration settings of the plugin. – TODO: Specify a place to find those settings. However, where those are applied is currently in flux. Also, further document how this process actually works. ++
43 44 45 46 47 48 49 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 43 def is_cacheable_by_default? cache_by_default = [:cache_by_default] return false unless cache_by_default return true if cache_by_default[:always] proc = cache_by_default[:proc] || CACHE_BY_DEFAULT_PROC proc.call(self, cache_by_default) end |
#not_cached ⇒ Object
Clones the current dataset, sets it to not be cached and returns the new dataset. See #cached for further details and examples.
90 91 92 93 94 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 90 def not_cached c = clone c.is_cacheable = false c end |
#update(values = {}, &block) ⇒ Object
Overrides the dataset’s existing update method. Deletes an existing cache after a successful update.
186 187 188 189 190 |
# File 'lib/sequel-query-cache/dataset_methods.rb', line 186 def update(values={}, &block) result = super cache_del if is_cacheable? && cache_clear_on_update result end |