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,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnyCache::Adapters
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
class ActiveSupportMemoryStore < ActiveSupportNaiveStore
|
7
|
+
require_relative 'active_support_memory_store/fetching'
|
8
|
+
require_relative 'active_support_memory_store/operation'
|
9
|
+
require_relative 'active_support_memory_store/increment'
|
10
|
+
require_relative 'active_support_memory_store/decrement'
|
11
|
+
require_relative 'active_support_memory_store/expire'
|
12
|
+
require_relative 'active_support_memory_store/persist'
|
13
|
+
|
14
|
+
class << self
|
15
|
+
# @param driver [Object]
|
16
|
+
# @return [Boolean]
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
# @since 0.1.0
|
20
|
+
def supported_driver?(driver)
|
21
|
+
defined?(::ActiveSupport::Cache::MemoryStore) &&
|
22
|
+
driver.is_a?(::ActiveSupport::Cache::MemoryStore)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AnyCache::Adapters::ActiveSupportMemoryStore
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
module Fetching
|
7
|
+
# @param key [String]
|
8
|
+
# @return [NilClass, ActiveSupport::Cache::Entry]
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.1.0
|
12
|
+
def fetch_entry(key)
|
13
|
+
driver.instance_eval { read_entry(key, {}) }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnyCache::Adapters
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
class ActiveSupportNaiveStore < Delegator
|
7
|
+
require_relative 'active_support_naive_store/operation'
|
8
|
+
require_relative 'active_support_naive_store/increment'
|
9
|
+
require_relative 'active_support_naive_store/decrement'
|
10
|
+
require_relative 'active_support_naive_store/expire'
|
11
|
+
require_relative 'active_support_naive_store/persist'
|
12
|
+
|
13
|
+
# @param driver [Object]
|
14
|
+
# @return [void]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
# @since 0.1.0
|
18
|
+
def initialize(driver)
|
19
|
+
super
|
20
|
+
@lock = Concurrent::ReentrantReadWriteLock.new
|
21
|
+
@incr_operation = self.class::Increment.new(driver)
|
22
|
+
@decr_operation = self.class::Decrement.new(driver)
|
23
|
+
@expr_operation = self.class::Expire.new(driver)
|
24
|
+
@pers_operation = self.class::Persist.new(driver)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param key [String]
|
28
|
+
# @param options [Hash]
|
29
|
+
# @return [Object]
|
30
|
+
#
|
31
|
+
# @api private
|
32
|
+
# @since 0.1.0
|
33
|
+
def read(key, **options)
|
34
|
+
lock.with_read_lock { super }
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param key [String]
|
38
|
+
# @param options [Hash]
|
39
|
+
# @return [void]
|
40
|
+
#
|
41
|
+
# @api private
|
42
|
+
# @since 0.1.0
|
43
|
+
def delete(key, **options)
|
44
|
+
lock.with_write_lock { super }
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param options [Hash]
|
48
|
+
# @return [void]
|
49
|
+
#
|
50
|
+
# @api private
|
51
|
+
# @since 0.1.0
|
52
|
+
def clear(**options)
|
53
|
+
lock.with_write_lock { super }
|
54
|
+
end
|
55
|
+
|
56
|
+
# @param key [String]
|
57
|
+
# @param value [Object]
|
58
|
+
# @param options [Hash]
|
59
|
+
# @return [void]
|
60
|
+
#
|
61
|
+
# @api private
|
62
|
+
# @since 0.1.0
|
63
|
+
def write(key, value, **options)
|
64
|
+
lock.with_write_lock do
|
65
|
+
expires_in = options.fetch(:expires_in, self.class::Operation::NO_EXPIRATION_TTL)
|
66
|
+
|
67
|
+
super(key, value, expires_in: expires_in)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# @param key [String]
|
72
|
+
# @param amount [Integer, Float]
|
73
|
+
# @option expires_in [NilClass, Integer]
|
74
|
+
# @return [Integer, Float]
|
75
|
+
#
|
76
|
+
# @api private
|
77
|
+
# @since 0.1.0
|
78
|
+
def increment(key, amount = self.class::Increment::DEFAULT_AMOUNT, **options)
|
79
|
+
lock.with_write_lock do
|
80
|
+
expires_in = options.fetch(:expires_in, self.class::Operation::NO_EXPIRATION_TTL)
|
81
|
+
|
82
|
+
incr_operation.call(key, amount, expires_in: expires_in)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# @param key [String]
|
87
|
+
# @param amount [Integer, Float]
|
88
|
+
# @option expires_in [NilClass, Integer]
|
89
|
+
# @return [Integer, Float]
|
90
|
+
#
|
91
|
+
# @api private
|
92
|
+
# @since 0.1.0
|
93
|
+
def decrement(key, amount = self.class::Decrement::DEFAULT_AMOUNT, **options)
|
94
|
+
lock.with_write_lock do
|
95
|
+
expires_in = options.fetch(:expires_in, self.class::Operation::NO_EXPIRATION_TTL)
|
96
|
+
|
97
|
+
decr_operation.call(key, amount, expires_in: expires_in)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# @param key [String]
|
102
|
+
# @option expires_in [NilClass, Integer]
|
103
|
+
# @return [void]
|
104
|
+
#
|
105
|
+
# @api private
|
106
|
+
# @since 0.1.0
|
107
|
+
def expire(key, expires_in: self.class::Operation::DEAD_TTL)
|
108
|
+
lock.with_write_lock { expr_operation.call(key, expires_in: expires_in) }
|
109
|
+
end
|
110
|
+
|
111
|
+
# @param key [String]
|
112
|
+
# @param options [Hash]
|
113
|
+
# @return [void]
|
114
|
+
#
|
115
|
+
# @api private
|
116
|
+
# @since 0.1.0
|
117
|
+
def persist(key, **options)
|
118
|
+
lock.with_write_lock { pers_operation.call(key) }
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
# @return [Concurrent::ReentrantReadWriteLock]
|
124
|
+
#
|
125
|
+
# @api private
|
126
|
+
# @since 0.1.0
|
127
|
+
attr_reader :lock
|
128
|
+
|
129
|
+
# @return [Operation::Increment]
|
130
|
+
#
|
131
|
+
# @api private
|
132
|
+
# @since 0.1.0
|
133
|
+
attr_reader :incr_operation
|
134
|
+
|
135
|
+
# @return [Operation::Decrement]
|
136
|
+
#
|
137
|
+
# @api private
|
138
|
+
# @since 0.1.0
|
139
|
+
attr_reader :decr_operation
|
140
|
+
|
141
|
+
# @return [Operation::Expire]
|
142
|
+
#
|
143
|
+
# @api private
|
144
|
+
# @since 0.1.0
|
145
|
+
attr_reader :expr_operation
|
146
|
+
|
147
|
+
# @return [Operation::Persist]
|
148
|
+
attr_reader :pers_operation
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AnyCache::Adapters::ActiveSupportNaiveStore
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
class Decrement < Operation
|
7
|
+
# @return [Integer]
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
# @since 0.1.0
|
11
|
+
DEFAULT_AMOUNT = 1
|
12
|
+
|
13
|
+
# @since 0.1.0
|
14
|
+
def_delegators :driver, :decrement
|
15
|
+
|
16
|
+
# @param key [String]
|
17
|
+
# @param amount [Integer, Float]
|
18
|
+
# @option expires_in [NilClass, Integer]
|
19
|
+
# @return [Integer, Float]
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
# @since 0.1.0
|
23
|
+
def call(key, amount = DEFAULT_AMOUNT, expires_in: NO_EXPIRATION_TTL)
|
24
|
+
expires_in ? decr_and_expire(key, amount, expires_in) : decr_existing(key, amount)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# @param key [String]
|
30
|
+
# @param amount [Integer, Float]
|
31
|
+
# @param expires_in [NilClass, Integer]
|
32
|
+
# @return [Integer, Float]
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
# @since 0.1.0
|
36
|
+
def decr_and_expire(key, amount, expires_in)
|
37
|
+
new_amount = decrement(key, amount, expires_in: expires_in)
|
38
|
+
new_amount || decr_non_existing(key, amount, expires_in)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param key [String]
|
42
|
+
# @param amount [Integer, Float]
|
43
|
+
# @return [Integer, Float]
|
44
|
+
#
|
45
|
+
# @api private
|
46
|
+
# @since 0.1.0
|
47
|
+
def decr_existing(key, amount)
|
48
|
+
new_amount = begin
|
49
|
+
entry = fetch_entry(key)
|
50
|
+
decrement(key, amount, expires_in: calc_entry_expiration(entry)) if entry
|
51
|
+
end
|
52
|
+
|
53
|
+
new_amount || decr_non_existing(key, amount)
|
54
|
+
end
|
55
|
+
|
56
|
+
# @param key [String]
|
57
|
+
# @param amount [Integer, Float]
|
58
|
+
# @param expires_in [NilClass, Integer]
|
59
|
+
# @return [Integer, Float]
|
60
|
+
#
|
61
|
+
# @api private
|
62
|
+
# @since 0.1.0
|
63
|
+
def decr_non_existing(key, amount, expires_in = NO_EXPIRATION_TTL)
|
64
|
+
amount = -amount
|
65
|
+
(expires_in ? write(key, amount, expires_in: expires_in) : write(key, amount)) && amount
|
66
|
+
end
|
67
|
+
|
68
|
+
# @!method fetch_entry(key)
|
69
|
+
# @param key [String]
|
70
|
+
# @return [NilClass, ActiveSupport::Cache::Entry]
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AnyCache::Adapters::ActiveSupportNaiveStore
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
class Expire < Operation
|
7
|
+
# @param key [String]
|
8
|
+
# @option expires_in [Integer, NilClass]
|
9
|
+
# @return [void]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.1.0
|
13
|
+
def call(key, expires_in: DEAD_TTL)
|
14
|
+
fetch_entry(key).tap do |entry|
|
15
|
+
next unless entry
|
16
|
+
is_alive = expires_in.positive?
|
17
|
+
is_alive ? write(key, entry.value, expires_in: expires_in) : delete(key)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @!method fetch_entry(key)
|
22
|
+
# @param key [String]
|
23
|
+
# @return [NilClass, ActiveSupport::Cache::Entry]
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AnyCache::Adapters::ActiveSupportNaiveStore
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
class Increment < Operation
|
7
|
+
# @return [Integer]
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
# @since 0.1.0
|
11
|
+
DEFAULT_AMOUNT = 1
|
12
|
+
|
13
|
+
# @since 0.1.0
|
14
|
+
def_delegators :driver, :increment
|
15
|
+
|
16
|
+
# @param key [String]
|
17
|
+
# @param amount [Integer, Float]
|
18
|
+
# @option expires_in [NilClass, Integer]
|
19
|
+
# @return [Integer, Float]
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
# @since 0.1.0
|
23
|
+
def call(key, amount = DEFAULT_AMOUNT, expires_in: NO_EXPIRATION_TTL)
|
24
|
+
expires_in ? incr_and_expire(key, amount, expires_in) : incr_existing(key, amount)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# @param key [String]
|
30
|
+
# @param amount [Integer, Float]
|
31
|
+
# @param expires_in [NilClass, Integer]
|
32
|
+
# @return [Integer, Float]
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
# @since 0.1.0
|
36
|
+
def incr_and_expire(key, amount, expires_in)
|
37
|
+
new_amount = increment(key, amount, expires_in: expires_in)
|
38
|
+
new_amount || incr_non_existing(key, amount, expires_in)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param key [String]
|
42
|
+
# @param amount [Integer, Float]
|
43
|
+
# @return [Integer, Float]
|
44
|
+
#
|
45
|
+
# @api private
|
46
|
+
# @since 0.1.0
|
47
|
+
def incr_existing(key, amount)
|
48
|
+
new_amount = begin
|
49
|
+
entry = fetch_entry(key)
|
50
|
+
increment(key, amount, expires_in: calc_entry_expiration(entry)) if entry
|
51
|
+
end
|
52
|
+
|
53
|
+
new_amount || incr_non_existing(key, amount)
|
54
|
+
end
|
55
|
+
|
56
|
+
# @param key [String]
|
57
|
+
# @param amount [Integer, Float]
|
58
|
+
# @param expires_in [NilClass, Integer]
|
59
|
+
# @return [Integer, Float]
|
60
|
+
#
|
61
|
+
# @api private
|
62
|
+
# @since 0.1.0
|
63
|
+
def incr_non_existing(key, amount, expires_in = NO_EXPIRATION_TTL)
|
64
|
+
(expires_in ? write(key, amount, expires_in: expires_in) : write(key, amount)) && amount
|
65
|
+
end
|
66
|
+
|
67
|
+
# @!method fetch_entry(key)
|
68
|
+
# @param key [String]
|
69
|
+
# @return [NilClass, ActiveSupport::Cache::Entry]
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AnyCache::Adapters::ActiveSupportNaiveStore
|
4
|
+
# @api private
|
5
|
+
# @since 0.1.0
|
6
|
+
class Operation
|
7
|
+
# @since 0.1.0
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
# @return [NilClass]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
# @since 0.1.0
|
14
|
+
NO_EXPIRATION_TTL = nil
|
15
|
+
|
16
|
+
# @return [Integer]
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
# @since 0.1.0
|
20
|
+
DEAD_TTL = 0
|
21
|
+
|
22
|
+
# @since 0.1.0
|
23
|
+
def_delegators :driver, :read, :write, :delete
|
24
|
+
|
25
|
+
# @param driver [Object]
|
26
|
+
# @return [void]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
# @since 0.1.0
|
30
|
+
def initialize(driver)
|
31
|
+
@driver = driver
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# @return [Object]
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
# @since 0.1.0
|
40
|
+
attr_reader :driver
|
41
|
+
|
42
|
+
# @option as_integer [Boolean]
|
43
|
+
# @return [Integer, Float]
|
44
|
+
#
|
45
|
+
# @api private
|
46
|
+
# @since 0.1.0
|
47
|
+
def calc_epoch_time(as_integer: false)
|
48
|
+
as_integer ? Time.now.to_i : Time.now.to_f
|
49
|
+
end
|
50
|
+
|
51
|
+
# @param [ActiveSupport::Cache::Entry]
|
52
|
+
# @return [NilClass, Integer]
|
53
|
+
#
|
54
|
+
# @api private
|
55
|
+
# @since 0.1.0
|
56
|
+
def calc_entry_expiration(entry)
|
57
|
+
entry.expires_at ? (entry.expires_at - calc_epoch_time) : NO_EXPIRATION_TTL
|
58
|
+
end
|
59
|
+
|
60
|
+
# @!method fetch_entry(key)
|
61
|
+
# @param key [String]
|
62
|
+
# @return [NilClass, ActiveSupport::Cache::Entry]
|
63
|
+
end
|
64
|
+
end
|