From 80f38e6a242e012cf49ca6d7cf896e7ed80b6330 Mon Sep 17 00:00:00 2001 From: Rustam Ibragimov Date: Fri, 21 Sep 2018 15:01:45 +0300 Subject: [PATCH] [multi-operations] redis: delete matched proto --- lib/any_cache/adapters/redis.rb | 25 +++++++++++- .../adapters/redis/delete_matched_basic.rb | 40 +++++++++++++++++++ .../adapters/redis/delete_matched_heavy.rb | 21 ++++++++++ .../adapters/redis/delete_matched_softly.rb | 21 ++++++++++ 4 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 lib/any_cache/adapters/redis/delete_matched_basic.rb create mode 100644 lib/any_cache/adapters/redis/delete_matched_heavy.rb create mode 100644 lib/any_cache/adapters/redis/delete_matched_softly.rb diff --git a/lib/any_cache/adapters/redis.rb b/lib/any_cache/adapters/redis.rb index 6ada93b..1eb4344 100644 --- a/lib/any_cache/adapters/redis.rb +++ b/lib/any_cache/adapters/redis.rb @@ -45,7 +45,25 @@ def supported_driver?(driver) :flushdb, :exists, :mapped_mget, - :mapped_mset + :mapped_mset, + :scan + + # @return [AnyCache::Adapters::Redis::DeleteMatchedHeavy] + attr_reader :delete_matched_heavy + + # @return [AnyCache::Adapters::Redis::DeleteMatchedSoftly] + attr_reader :delete_matched_softly + + # @param driver [Object] + # @return [void] + # + # @api private + # @since 0.3.0 + def initialize(driver) + super + @delete_matched_heavy = DeleteMatchedHeavy.new(self) + @delete_matched_softly = DeleteMatchedSoftly.new(self) + end # @param key [String] # @param options [Hash] @@ -138,7 +156,10 @@ def delete(key, **options) # @api private # @since 0.3.0 def delete_matched(pattern, **options) - + case pattern + when String then delete_matched_softly.call(pattern, **options) + when Regexp then delete_matched_heavy.call(pattern, **options) + end end # @param key [String] diff --git a/lib/any_cache/adapters/redis/delete_matched_basic.rb b/lib/any_cache/adapters/redis/delete_matched_basic.rb new file mode 100644 index 0000000..7f5d9e5 --- /dev/null +++ b/lib/any_cache/adapters/redis/delete_matched_basic.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +class AnyCache::Adapters::Redis + class DeleteMatchedBasic + # @since 0.3.0 + extend Forwardable + + # @return [String] + # + # @api private + # @since 0.3.0 + CURSOR_LOOP_FLAG = "0" + + # @return [Integer] + # + # @api private + # @since 0.3.0 + BATCH_SIZE = 10 + + # @return [AnyCache::Adapters::Redis] + # + # @api private + # @since 0.3.0 + attr_reader :adapter + + # @param adapter [AnyCache::Adapters::Redis] + # @return [void] + # + # @api private + # @since 0.3.0 + def initiaalize(adapter) + @adapter = adapter + end + + # @!method delete_matched(pattern, **options) + # @param pattern [Object] + # @param options [Hash] + # @return [void] + end +end diff --git a/lib/any_cache/adapters/redis/delete_matched_heavy.rb b/lib/any_cache/adapters/redis/delete_matched_heavy.rb new file mode 100644 index 0000000..eebd47a --- /dev/null +++ b/lib/any_cache/adapters/redis/delete_matched_heavy.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class AnyCache::Adapters::Redis + class DeleteMatchedHeavy < DeleteMatchedBasic + # @param pattern [Regexp] + # @param options [Hash] + # @return [void] + # + # @api private + # @since 0.3.0 + def delete_matched(pattern, **options) + cursor = CURSOR_LOOP_FLAG + + loop do + cursor, keys = adapter.scan(cursor, count: BATCH_SIZE) + adapter.del(keys.grep(pattern)) + break if cursor == CURSOR_LOOP_FLAG + end + end + end +end diff --git a/lib/any_cache/adapters/redis/delete_matched_softly.rb b/lib/any_cache/adapters/redis/delete_matched_softly.rb new file mode 100644 index 0000000..2d0e2fd --- /dev/null +++ b/lib/any_cache/adapters/redis/delete_matched_softly.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class AnyCache::Adapters::Redis + class DeleteMatchedSoftly < DeleteMatchedBasic + # @param pattern [String] + # @param options [Hash] + # @return [void] + # + # @api private + # @since 0.3.0 + def delete_matched(pattern, **options) + cursor = CURSOR_LOOP_FLAG + + loop do + cursor, keys = adapter.scan(cursor, match: pattern, count: BATCH_SIZE) + adapter.del(keys) + break if cursor == CURSOR_LOOP_FLAG + end + end + end +end