any_cache 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -2
  3. data/.rspec +1 -1
  4. data/.rubocop.yml +18 -0
  5. data/.travis.yml +83 -4
  6. data/CHANGELOG.md +5 -0
  7. data/Gemfile +4 -2
  8. data/README.md +241 -18
  9. data/Rakefile +6 -4
  10. data/any_cache.gemspec +21 -7
  11. data/bin/console +5 -11
  12. data/bin/rspec +119 -0
  13. data/gemfiles/active_support.gemfile +7 -0
  14. data/gemfiles/active_support_with_redis.gemfile +8 -0
  15. data/gemfiles/dalli.gemfile +7 -0
  16. data/gemfiles/redis.gemfile +7 -0
  17. data/gemfiles/redis_store.gemfile +7 -0
  18. data/lib/any_cache.rb +49 -3
  19. data/lib/any_cache/adapters.rb +40 -0
  20. data/lib/any_cache/adapters/active_support_file_store.rb +26 -0
  21. data/lib/any_cache/adapters/active_support_file_store/decrement.rb +10 -0
  22. data/lib/any_cache/adapters/active_support_file_store/expire.rb +10 -0
  23. data/lib/any_cache/adapters/active_support_file_store/fetching.rb +28 -0
  24. data/lib/any_cache/adapters/active_support_file_store/increment.rb +10 -0
  25. data/lib/any_cache/adapters/active_support_file_store/operation.rb +10 -0
  26. data/lib/any_cache/adapters/active_support_file_store/persist.rb +10 -0
  27. data/lib/any_cache/adapters/active_support_memory_store.rb +26 -0
  28. data/lib/any_cache/adapters/active_support_memory_store/decrement.rb +10 -0
  29. data/lib/any_cache/adapters/active_support_memory_store/expire.rb +10 -0
  30. data/lib/any_cache/adapters/active_support_memory_store/fetching.rb +16 -0
  31. data/lib/any_cache/adapters/active_support_memory_store/increment.rb +10 -0
  32. data/lib/any_cache/adapters/active_support_memory_store/operation.rb +10 -0
  33. data/lib/any_cache/adapters/active_support_memory_store/persist.rb +10 -0
  34. data/lib/any_cache/adapters/active_support_naive_store.rb +150 -0
  35. data/lib/any_cache/adapters/active_support_naive_store/decrement.rb +72 -0
  36. data/lib/any_cache/adapters/active_support_naive_store/expire.rb +25 -0
  37. data/lib/any_cache/adapters/active_support_naive_store/increment.rb +71 -0
  38. data/lib/any_cache/adapters/active_support_naive_store/operation.rb +64 -0
  39. data/lib/any_cache/adapters/active_support_naive_store/persist.rb +22 -0
  40. data/lib/any_cache/adapters/active_support_redis_cache_store.rb +129 -0
  41. data/lib/any_cache/adapters/basic.rb +118 -0
  42. data/lib/any_cache/adapters/dalli.rb +140 -0
  43. data/lib/any_cache/adapters/delegator.rb +36 -0
  44. data/lib/any_cache/adapters/redis.rb +151 -0
  45. data/lib/any_cache/adapters/redis_store.rb +41 -0
  46. data/lib/any_cache/error.rb +11 -0
  47. data/lib/any_cache/version.rb +5 -2
  48. 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