Skip to content

Commit

Permalink
[#fetch_multi] Initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
0exp committed Sep 9, 2018
1 parent 96d917c commit 54ee521
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 102 deletions.
5 changes: 3 additions & 2 deletions lib/any_cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,15 @@ def build(driver = Drivers.build(config))
:read_multi,
:write,
:write_multi,
:fetch,
:fetch_multi,
:delete,
:increment,
:decrement,
:expire,
:persist,
:clear,
:exist?,
:fetch
:exist?

# @return [AnyCache::Adapters::Basic]
#
Expand Down
43 changes: 28 additions & 15 deletions lib/any_cache/adapters/active_support_mem_cache_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,34 @@ def write_multi(entries, **options)
driver.write_multi(entries, expires_in: NO_EXPIRATION_TTL, raw: raw)
end

# @param key [String]
# @option expires_in [Integer]
# @option force [Boolean, Proc]
# @return [Object]
#
# @api private
# @since 0.2.0
def fetch(key, **options, &fallback)
force_rewrite = options.fetch(:force, false)
force_rewrite = force_rewrite.call(key) if force_rewrite.respond_to?(:call)
expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)

driver.fetch(key, force: force_rewrite, expires_in: expires_in, &fallback)
end

# @param keys [Array<String>]
# @param options [Hash]
# @param fallback [Proc]
# @return [Hash]
#
# @api private
# @since 0.3.0
def fetch_multi(*keys, **options, &fallback)
keys.each_with_object({}) do |key, dataset|
dataset[key] = fetch(key, **options, &fallback)
end
end

# @param key [String]
# @param amount [Integer]
# @options expires_in [Integer]
Expand Down Expand Up @@ -176,20 +204,5 @@ def persist(key, **options)
def exist?(key, **options)
driver.exist?(key)
end

# @param key [String]
# @option expires_in [Integer]
# @option force [Boolean]
# @return [Object]
#
# @api private
# @since 0.2.0
def fetch(key, **options, &block)
force_rewrite = options.fetch(:force, false)
force_rewrite = force_rewrite.call if force_rewrite.respond_to?(:call)
expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)

driver.fetch(key, force: force_rewrite, expires_in: expires_in, &block)
end
end
end
58 changes: 41 additions & 17 deletions lib/any_cache/adapters/active_support_naive_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,47 @@ def write_multi(entries, **options)
end
end

# @param key [String]
# @param fallback [Proc]
# @option expires_in [Integer]
# @option force [Boolean, Proc]
# @return [Object]
#
# @api private
# @since 0.2.0
def fetch(key, **options, &fallback)
lock.with_write_lock do
force_rewrite = options.fetch(:force, false)
force_rewrite = force_rewrite.call(key) if force_rewrite.respond_to?(:call)
expires_in = options.fetch(:expires_in, self.class::Operation::NO_EXPIRATION_TTL)

super(key, force: force_rewrite, expires_in: expires_in, &fallback)
end
end

# @param keys [Array<String>]
# @param fallback [Proc]
# @option force [Boolean, Proc]
# @option expires_in [Integer]
# @return [Hash]
#
# @api private
# @since 0.3.0
def fetch_multi(*keys, **options, &fallback)
lock.with_write_lock do
force_rewrite = options.fetch(:force, false)
expires_in = options.fetch(:expires_in, self.class::Operation::NO_EXPIRATION_TTL)

# NOTE:
# use own #fetch_multi implementation cuz original #fetch_multi
# does not support :force option
keys.each_with_object({}) do |key, dataset|
force = force_rewrite.respond_to?(:call) ? force_rewrite.call(key) : force_rewrite
dataset[key] = driver.fetch(key, force: force, expires_in: expires_in, &fallback)
end
end
end

# @param key [String]
# @param amount [Integer, Float]
# @option expires_in [NilClass, Integer]
Expand Down Expand Up @@ -156,23 +197,6 @@ def exist?(key, **options)
lock.with_read_lock { super }
end

# @param key [String]
# @option expires_in [Integer]
# @option force [Boolean]
# @return [Object]
#
# @api private
# @since 0.2.0
def fetch(key, **options, &block)
lock.with_write_lock do
force_rewrite = options.fetch(:force, false)
force_rewrite = force_rewrite.call if force_rewrite.respond_to?(:call)
expires_in = options.fetch(:expires_in, self.class::Operation::NO_EXPIRATION_TTL)

super(key, force: force_rewrite, expires_in: expires_in, &block)
end
end

private

# @return [Concurrent::ReentrantReadWriteLock]
Expand Down
49 changes: 34 additions & 15 deletions lib/any_cache/adapters/active_support_redis_cache_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,40 @@ def write_multi(entries, **options)
driver.write_multi(entries, expires_in: NO_EXPIRATION_TTL, raw: raw)
end

# @param key [String]
# @param fallback [Proc]
# @option expires_in [Integer]
# @option force [Boolean, Proc]
# @return [Object]
#
# @api private
# @since 0.2.0
def fetch(key, **options, &fallback)
force_rewrite = options.fetch(:force, false)
force_rewrite = force_rewrite.call(key) if force_rewrite.respond_to?(:call)
expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
raw = options.fetch(:raw, true)

driver.fetch(key, force: force_rewrite, expires_in: expires_in, raw: raw, &fallback)
end

# @param keys [Array<string]
# @param fallback [Proc]
# @poption expires_in [Integer]
# @option force [Boolean, Proc]
# @return [Hash]
#
# @api private
# @since 0.3.0
def fetch_multi(*keys, **options, &fallback)
# NOTE:
# use own :fetch_multi implementation cuz original :fetch_multi
# doesnt support :force option
keys.each_with_object({}) do |key, dataset|
dataset[key] = fetch(key, **options, &fallback)
end
end

# @param key [String]
# @param amount [Integer, Float]
# @option expires_in [Integer]
Expand Down Expand Up @@ -166,20 +200,5 @@ def persist(key, **options)
def exist?(key, **options)
driver.exist?(key)
end

# @param key [String]
# @option expires_in [Integer]
# @option force [Boolean]
# @return [Object]
#
# @api private
# @since 0.2.0
def fetch(key, **options, &block)
force_rewrite = options.fetch(:force, false)
force_rewrite = force_rewrite.call if force_rewrite.respond_to?(:call)
expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)

driver.fetch(key, force: force_rewrite, expires_in: expires_in, &block)
end
end
end
31 changes: 21 additions & 10 deletions lib/any_cache/adapters/basic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,27 @@ def write_multi(entries, **options)
raise NotImplementedError
end

# @param key [String]
# @param options [Hash]
# @return [Object]
#
# @api private
# @since 0.2.0
def fetch(key, **options, &block)
raise NotImplementedError
end

# @param keys [Array<String>]
# @param options [Hash]
# @param block [Proc]
# @return [Hash]
#
# @api private
# @since 0.3.0
def fetch_multi(*keys, **options, &block)
raise NotImplementedError
end

# @param key [String]
# @param options [Hash]
# @return [void]
Expand Down Expand Up @@ -144,15 +165,5 @@ def clear(**options)
def exist?(key, **options)
raise NotImplementedError
end

# @param key [String]
# @param options [Hash]
# @return [Object]
#
# @api private
# @since 0.2.0
def fetch(key, **options, &block)
raise NotImplementedError
end
end
end
50 changes: 33 additions & 17 deletions lib/any_cache/adapters/dalli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,39 @@ def write_multi(entries, **options)
end
end

# @param key [String]
# @param fallback [Proc]
# @option expires_in [Integer]
# @option force [Boolean, Proc]
# @return [Object]
#
# @api private
# @since 0.2.0
def fetch(key, **options, &fallback)
force_rewrite = options.fetch(:force, false)
force_rewrite = force_rewrite.call(key) if force_rewrite.respond_to?(:call)

# NOTE: can conflict with :cache_nils Dalli::Client's config
read(key).tap { |value| return value if value } unless force_rewrite

fallback.call(key).tap { |value| write(key, value, **options) } if block_given?
end

# @param keys [Array<String>]
# @param fallback [Proc]
# @option force [Boolean, Proc]
# @option expires_in [Integer]
# @return [Hash]
#
# @api private
# @since 0.3.0
def fetch_multi(*keys, **options, &fallback)
# TODO: think about multi-thread approach
keys.each_with_object({}) do |key, dataset|
dataset[key] = fetch(key, **options, &fallback)
end
end

# @param key [String]
# @param options [Hash]
# @return [void]
Expand Down Expand Up @@ -187,22 +220,5 @@ def clear(**options)
def exist?(key, **options)
!get(key).nil? # NOTE: can conflict with :cache_nils Dalli::Client's config
end

# @param key [String]
# @option expires_in [Integer]
# @option force [Boolean]
# @return [Object]
#
# @api private
# @since 0.2.0
def fetch(key, **options)
force_rewrite = options.fetch(:force, false)
force_rewrite = force_rewrite.call if force_rewrite.respond_to?(:call)

# NOTE: can conflict with :cache_nils Dalli::Client's config
read(key).tap { |value| return value if value } unless force_rewrite

yield.tap { |value| write(key, value, **options) } if block_given?
end
end
end
8 changes: 5 additions & 3 deletions lib/any_cache/adapters/delegator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,18 @@ class << self
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
def supported_driver?(driver)
driver.respond_to?(:read) &&
driver.respond_to?(:read_multi) &&
driver.respond_to?(:write) &&
driver.respond_to?(:write_multi) &&
driver.respond_to?(:fetch_multi) &&
driver.respond_to?(:delete) &&
driver.respond_to?(:increment) &&
driver.respond_to?(:decrement) &&
driver.respond_to?(:expire) &&
driver.respond_to?(:persist) &&
driver.respond_to?(:clear) &&
driver.respond_to?(:exist?) &&
driver.respond_to?(:fetch) &&
driver.respond_to?(:read_multi) &&
driver.respond_to?(:write_multi)
driver.respond_to?(:fetch)
end
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
end
Expand All @@ -34,6 +35,7 @@ def supported_driver?(driver)
:read_multi,
:write,
:write_multi,
:fetch_multi,
:delete,
:increment,
:decrement,
Expand Down
Loading

0 comments on commit 54ee521

Please sign in to comment.