any_cache 0.0.0 → 0.1.0
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.
- checksums.yaml +4 -4
- data/.gitignore +6 -2
- data/.rspec +1 -1
- data/.rubocop.yml +18 -0
- data/.travis.yml +83 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile +4 -2
- data/README.md +241 -18
- data/Rakefile +6 -4
- data/any_cache.gemspec +21 -7
- data/bin/console +5 -11
- data/bin/rspec +119 -0
- data/gemfiles/active_support.gemfile +7 -0
- data/gemfiles/active_support_with_redis.gemfile +8 -0
- data/gemfiles/dalli.gemfile +7 -0
- data/gemfiles/redis.gemfile +7 -0
- data/gemfiles/redis_store.gemfile +7 -0
- data/lib/any_cache.rb +49 -3
- data/lib/any_cache/adapters.rb +40 -0
- data/lib/any_cache/adapters/active_support_file_store.rb +26 -0
- data/lib/any_cache/adapters/active_support_file_store/decrement.rb +10 -0
- data/lib/any_cache/adapters/active_support_file_store/expire.rb +10 -0
- data/lib/any_cache/adapters/active_support_file_store/fetching.rb +28 -0
- data/lib/any_cache/adapters/active_support_file_store/increment.rb +10 -0
- data/lib/any_cache/adapters/active_support_file_store/operation.rb +10 -0
- data/lib/any_cache/adapters/active_support_file_store/persist.rb +10 -0
- data/lib/any_cache/adapters/active_support_memory_store.rb +26 -0
- data/lib/any_cache/adapters/active_support_memory_store/decrement.rb +10 -0
- data/lib/any_cache/adapters/active_support_memory_store/expire.rb +10 -0
- data/lib/any_cache/adapters/active_support_memory_store/fetching.rb +16 -0
- data/lib/any_cache/adapters/active_support_memory_store/increment.rb +10 -0
- data/lib/any_cache/adapters/active_support_memory_store/operation.rb +10 -0
- data/lib/any_cache/adapters/active_support_memory_store/persist.rb +10 -0
- data/lib/any_cache/adapters/active_support_naive_store.rb +150 -0
- data/lib/any_cache/adapters/active_support_naive_store/decrement.rb +72 -0
- data/lib/any_cache/adapters/active_support_naive_store/expire.rb +25 -0
- data/lib/any_cache/adapters/active_support_naive_store/increment.rb +71 -0
- data/lib/any_cache/adapters/active_support_naive_store/operation.rb +64 -0
- data/lib/any_cache/adapters/active_support_naive_store/persist.rb +22 -0
- data/lib/any_cache/adapters/active_support_redis_cache_store.rb +129 -0
- data/lib/any_cache/adapters/basic.rb +118 -0
- data/lib/any_cache/adapters/dalli.rb +140 -0
- data/lib/any_cache/adapters/delegator.rb +36 -0
- data/lib/any_cache/adapters/redis.rb +151 -0
- data/lib/any_cache/adapters/redis_store.rb +41 -0
- data/lib/any_cache/error.rb +11 -0
- data/lib/any_cache/version.rb +5 -2
- metadata +127 -5
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AnyCache::Adapters::ActiveSupportNaiveStore
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
class Persist < Operation
|
7
|
+
# @param key [String]
|
8
|
+
# @return [void]
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.1.0
|
12
|
+
def call(key)
|
13
|
+
fetch_entry(key).tap do |entry|
|
14
|
+
write(key, entry.value, expires_in: NO_EXPIRATION_TTL) if entry
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# @!method fetch_entry(key)
|
19
|
+
# @param key [String]
|
20
|
+
# @return [NilClass, ActiveSupport::Cache::Entry]
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnyCache::Adapters
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
class ActiveSupportRedisCacheStore < Basic
|
7
|
+
# TODO: think about locks
|
8
|
+
|
9
|
+
class << self
|
10
|
+
# @param driver [Object]
|
11
|
+
# @return [Boolean]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
# @since 0.1.0
|
15
|
+
def supported_driver?(driver)
|
16
|
+
defined?(::Redis) &&
|
17
|
+
defined?(::ActiveSupport::Cache::RedisCacheStore) &&
|
18
|
+
driver.is_a?(::ActiveSupport::Cache::RedisCacheStore)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# @since 0.1.0
|
23
|
+
def_delegators :driver, :delete, :clear
|
24
|
+
|
25
|
+
# @return [NilClass]
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
# @since 0.1.0
|
29
|
+
NO_EXPIRATION_TTL = nil
|
30
|
+
|
31
|
+
# @return [Integer]
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
# @since 0.1.0
|
35
|
+
DEAD_TTL = 0
|
36
|
+
|
37
|
+
# @return [Integer]
|
38
|
+
#
|
39
|
+
# @api private
|
40
|
+
# @since 0.1.0
|
41
|
+
DEFAULT_INCR_DECR_AMOUNT = 1
|
42
|
+
|
43
|
+
# @param key
|
44
|
+
# @param options [Hash]
|
45
|
+
# @return [Object]
|
46
|
+
#
|
47
|
+
# @api private
|
48
|
+
# @since 0.1.0
|
49
|
+
def read(key, **options)
|
50
|
+
driver.read(key, raw: true)
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param key [String]
|
54
|
+
# @param value [Object]
|
55
|
+
# @option expires_in [NilClass, Integer] Time in seconds
|
56
|
+
# @return [void]
|
57
|
+
#
|
58
|
+
# @api private
|
59
|
+
# @since 0.1.0
|
60
|
+
def write(key, value, **options)
|
61
|
+
expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
|
62
|
+
|
63
|
+
driver.write(key, value, expires_in: expires_in, raw: true)
|
64
|
+
end
|
65
|
+
|
66
|
+
# @param key [String]
|
67
|
+
# @param amount [Integer, Float]
|
68
|
+
# @option expires_in [Integer]
|
69
|
+
# @return [Integer, Float]
|
70
|
+
#
|
71
|
+
# @api private
|
72
|
+
# @since 0.1.0
|
73
|
+
def increment(key, amount = DEFAULT_INCR_DECR_AMOUNT, **options)
|
74
|
+
expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
|
75
|
+
is_initial = expires_in && !read(key)
|
76
|
+
|
77
|
+
if is_initial
|
78
|
+
write(key, amount, expires_in: expires_in) && amount
|
79
|
+
else
|
80
|
+
driver.increment(key, amount).tap do
|
81
|
+
expire(key, expires_in: expires_in) if expires_in
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# @param key [String]
|
87
|
+
# @param amount [Integer, Float]
|
88
|
+
# @option expires_in [Integer]
|
89
|
+
# @return [Integer, Float]
|
90
|
+
#
|
91
|
+
# @api private
|
92
|
+
# @since 0.1.0
|
93
|
+
def decrement(key, amount = DEFAULT_INCR_DECR_AMOUNT, **options)
|
94
|
+
expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
|
95
|
+
is_initial = expires_in && !read(key)
|
96
|
+
|
97
|
+
if is_initial
|
98
|
+
write(key, -amount, expires_in: expires_in) && -amount
|
99
|
+
else
|
100
|
+
driver.decrement(key, amount).tap do
|
101
|
+
expire(key, expires_in: expires_in) if expires_in
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# @param key [String]
|
107
|
+
# @option expires_in [Integer]
|
108
|
+
# @return [void]
|
109
|
+
#
|
110
|
+
# @api private
|
111
|
+
# @since 0.1.0
|
112
|
+
def expire(key, expires_in: DEAD_TTL)
|
113
|
+
read(key).tap do |value|
|
114
|
+
is_alive = expires_in ? expires_in.positive? : false
|
115
|
+
is_alive ? write(key, value, expires_in: expires_in) : delete(key)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# @param key [String]
|
120
|
+
# @param options [Hash]
|
121
|
+
# @return [void]
|
122
|
+
#
|
123
|
+
# @api private
|
124
|
+
# @since 0.1.0
|
125
|
+
def persist(key, **options)
|
126
|
+
read(key).tap { |value| write(key, value) }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnyCache::Adapters
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
class Basic
|
7
|
+
# @since 0.1.0
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# @param driver [Object]
|
12
|
+
# @return [Boolean]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
# @since 0.1.0
|
16
|
+
def supported_driver?(driver)
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Object]
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
# @since 0.1.0
|
25
|
+
attr_reader :driver
|
26
|
+
|
27
|
+
# @param driver [Object]
|
28
|
+
# @return [void]
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
# @since 0.1.0
|
32
|
+
def initialize(driver)
|
33
|
+
@driver = driver
|
34
|
+
end
|
35
|
+
|
36
|
+
# @param key [String]
|
37
|
+
# @param options [Hash]
|
38
|
+
# @return [Object]
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
# @since 0.1.0
|
42
|
+
def read(key, **options)
|
43
|
+
raise NotImplementedError
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param key [String]
|
47
|
+
# @param value [Object]
|
48
|
+
# @param options [Hash]
|
49
|
+
# @return [void]
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
# @sinc 0.1.0
|
53
|
+
def write(key, value, **options)
|
54
|
+
raise NotImplementedError
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param key [String]
|
58
|
+
# @param options [Hash]
|
59
|
+
# @return [void]
|
60
|
+
#
|
61
|
+
# @api private
|
62
|
+
# @since 0.1.0
|
63
|
+
def delete(key, **options)
|
64
|
+
raise NotImplementedError
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param key [String]
|
68
|
+
# @param value [Integer, Float]
|
69
|
+
# @param options [Hash]
|
70
|
+
# @return [Integer, Float]
|
71
|
+
#
|
72
|
+
# @api private
|
73
|
+
# @sinc 0.1.0
|
74
|
+
def increment(key, value, **options)
|
75
|
+
raise NotImplementedError
|
76
|
+
end
|
77
|
+
|
78
|
+
# @param key [String]
|
79
|
+
# @param value [Integer, Float]
|
80
|
+
# @param options [Hash]
|
81
|
+
# @return [Integer, Float]
|
82
|
+
#
|
83
|
+
# @api private
|
84
|
+
# @since 0.1.0
|
85
|
+
def decrement(key, value, **options)
|
86
|
+
raise NotImplementedError
|
87
|
+
end
|
88
|
+
|
89
|
+
# @param key [String]
|
90
|
+
# @option expires_in [Integer]
|
91
|
+
# @return [void]
|
92
|
+
#
|
93
|
+
# @api private
|
94
|
+
# @since 0.1.0
|
95
|
+
def expire(key, expires_in:)
|
96
|
+
raise NotImplementedError
|
97
|
+
end
|
98
|
+
|
99
|
+
# @param key [String]
|
100
|
+
# @param options [Hash]
|
101
|
+
# @return [void]
|
102
|
+
#
|
103
|
+
# @api private
|
104
|
+
# @since 0.1.0
|
105
|
+
def persist(key, **options)
|
106
|
+
raise NotImplementedError
|
107
|
+
end
|
108
|
+
|
109
|
+
# @param options [Hash]
|
110
|
+
# @return [void]
|
111
|
+
#
|
112
|
+
# @api private
|
113
|
+
# @since 0.1.0
|
114
|
+
def clear(**options)
|
115
|
+
raise NotImplementedError
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnyCache::Adapters
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
class Dalli < Basic
|
7
|
+
class << self
|
8
|
+
# @param driver [Object]
|
9
|
+
# @return [Boolean]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.1.0
|
13
|
+
def supported_driver?(driver)
|
14
|
+
defined?(::Dalli::Client) && driver.is_a?(::Dalli::Client)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Integer]
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
# @since 0.1.0
|
22
|
+
NO_EXPIRATION_TTL = 0
|
23
|
+
|
24
|
+
# @return [NilClass]
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
# @since 0.1.0
|
28
|
+
DEAD_TTL = nil
|
29
|
+
|
30
|
+
# @return [Integer]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
# @since 0.1.0
|
34
|
+
DEFAULT_INCR_DECR_AMOUNT = 1
|
35
|
+
|
36
|
+
# @return [Integer]
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
# @since 0.1.0
|
40
|
+
MIN_DECRESEAD_VAL = 0
|
41
|
+
|
42
|
+
# @since 0.1.0
|
43
|
+
def_delegators :driver,
|
44
|
+
:get,
|
45
|
+
:set,
|
46
|
+
:incr,
|
47
|
+
:decr,
|
48
|
+
:multi,
|
49
|
+
:touch,
|
50
|
+
:flush
|
51
|
+
|
52
|
+
# @param key [String]
|
53
|
+
# @param options [Hash]
|
54
|
+
# @return [Object]
|
55
|
+
#
|
56
|
+
# @api private
|
57
|
+
# @since 0.1.0
|
58
|
+
def read(key, **options)
|
59
|
+
get(key)
|
60
|
+
end
|
61
|
+
|
62
|
+
def write(key, value, **options)
|
63
|
+
expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
|
64
|
+
|
65
|
+
set(key, value, expires_in, raw: true)
|
66
|
+
end
|
67
|
+
|
68
|
+
# @param key [String]
|
69
|
+
# @param options [Hash]
|
70
|
+
# @return [void]
|
71
|
+
#
|
72
|
+
# @api private
|
73
|
+
# @since 0.1.0
|
74
|
+
def delete(key, **options)
|
75
|
+
driver.delete(key)
|
76
|
+
end
|
77
|
+
|
78
|
+
# @param key [String]
|
79
|
+
# @param amount [Integer]
|
80
|
+
# @option expires_in [NilClass, Integer]
|
81
|
+
# @return [NilClass, Integer]
|
82
|
+
#
|
83
|
+
# @api private
|
84
|
+
# @since 0.1.0
|
85
|
+
def increment(key, amount = DEFAULT_INCR_DECR_AMOUNT, **options)
|
86
|
+
expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
|
87
|
+
|
88
|
+
# TODO: think about #cas and Concurrent::ReentrantReadWriteLock
|
89
|
+
incr(key, amount, expires_in, amount).tap do |new_amount|
|
90
|
+
touch(key, expires_in) if new_amount && expires_in.positive?
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# @param key [String]
|
95
|
+
# @param amount [Integer]
|
96
|
+
# @option expires_in [NilClass, Integer]
|
97
|
+
# @return [NilClass, Integer]
|
98
|
+
#
|
99
|
+
# @api private
|
100
|
+
# @since 0.1.0
|
101
|
+
def decrement(key, amount = DEFAULT_INCR_DECR_AMOUNT, **options)
|
102
|
+
expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
|
103
|
+
|
104
|
+
# TODO: think about #cas and Concurrent::ReentrantReadWriteLock
|
105
|
+
decr(key, amount, expires_in, MIN_DECRESEAD_VAL).tap do |new_amount|
|
106
|
+
touch(key, expires_in) if new_amount && expires_in.positive?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# @param key [String]
|
111
|
+
# @option expires_in [Integer]
|
112
|
+
# @return [void]
|
113
|
+
#
|
114
|
+
# @api private
|
115
|
+
# @since 0.1.0
|
116
|
+
def expire(key, expires_in: DEAD_TTL)
|
117
|
+
is_alive = expires_in ? expires_in.positive? : false
|
118
|
+
is_alive ? touch(key, expires_in) : driver.delete(key)
|
119
|
+
end
|
120
|
+
|
121
|
+
# @param key [String]
|
122
|
+
# @param options [Hash]
|
123
|
+
# @return [void]
|
124
|
+
#
|
125
|
+
# @api private
|
126
|
+
# @since 0.1.0
|
127
|
+
def persist(key, **options)
|
128
|
+
touch(key, NO_EXPIRATION_TTL)
|
129
|
+
end
|
130
|
+
|
131
|
+
# @param options [Hash]
|
132
|
+
# @return [void]
|
133
|
+
#
|
134
|
+
# @api private
|
135
|
+
# @since 0.1.0
|
136
|
+
def clear(**options)
|
137
|
+
flush(0) # NOTE: 0 is a flush delay
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnyCache::Adapters
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
class Delegator < Basic
|
7
|
+
class << self
|
8
|
+
# @param driver [Object]
|
9
|
+
# @return [Boolean]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.1.0
|
13
|
+
def supported_driver?(driver)
|
14
|
+
driver.respond_to?(:read) &&
|
15
|
+
driver.respond_to?(:write) &&
|
16
|
+
driver.respond_to?(:delete) &&
|
17
|
+
driver.respond_to?(:increment) &&
|
18
|
+
driver.respond_to?(:decrement) &&
|
19
|
+
driver.respond_to?(:expire) &&
|
20
|
+
driver.respond_to?(:persist) &&
|
21
|
+
driver.respond_to?(:clear)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @since 0.1.0
|
26
|
+
def_delegators :driver,
|
27
|
+
:read,
|
28
|
+
:write,
|
29
|
+
:delete,
|
30
|
+
:increment,
|
31
|
+
:decrement,
|
32
|
+
:expire,
|
33
|
+
:persist,
|
34
|
+
:clear
|
35
|
+
end
|
36
|
+
end
|