activesupport 4.2.11.1 → 6.0.3.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (263) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +399 -411
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -7
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +34 -6
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +58 -53
  12. data/lib/active_support/cache/mem_cache_store.rb +95 -91
  13. data/lib/active_support/cache/memory_store.rb +39 -36
  14. data/lib/active_support/cache/null_store.rb +11 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +75 -42
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  18. data/lib/active_support/cache.rb +331 -217
  19. data/lib/active_support/callbacks.rb +650 -592
  20. data/lib/active_support/concern.rb +35 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  22. data/lib/active_support/concurrency/share_lock.rb +226 -0
  23. data/lib/active_support/configurable.rb +13 -14
  24. data/lib/active_support/core_ext/array/access.rb +41 -1
  25. data/lib/active_support/core_ext/array/conversions.rb +24 -20
  26. data/lib/active_support/core_ext/array/extract.rb +21 -0
  27. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  28. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  29. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  30. data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -6
  31. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  32. data/lib/active_support/core_ext/array.rb +9 -6
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  35. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  36. data/lib/active_support/core_ext/class/attribute.rb +45 -31
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  38. data/lib/active_support/core_ext/class/subclasses.rb +20 -6
  39. data/lib/active_support/core_ext/class.rb +4 -3
  40. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  41. data/lib/active_support/core_ext/date/blank.rb +14 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +17 -14
  43. data/lib/active_support/core_ext/date/conversions.rb +25 -23
  44. data/lib/active_support/core_ext/date/zones.rb +4 -2
  45. data/lib/active_support/core_ext/date.rb +6 -4
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +154 -65
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -13
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  50. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +37 -19
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
  53. data/lib/active_support/core_ext/date_time/conversions.rb +16 -13
  54. data/lib/active_support/core_ext/date_time.rb +7 -5
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/digest.rb +3 -0
  57. data/lib/active_support/core_ext/enumerable.rb +114 -22
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/file.rb +3 -1
  60. data/lib/active_support/core_ext/hash/compact.rb +4 -23
  61. data/lib/active_support/core_ext/hash/conversions.rb +62 -41
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  64. data/lib/active_support/core_ext/hash/except.rb +12 -9
  65. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  66. data/lib/active_support/core_ext/hash/keys.rb +19 -42
  67. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  68. data/lib/active_support/core_ext/hash/slice.rb +5 -27
  69. data/lib/active_support/core_ext/hash/transform_values.rb +4 -22
  70. data/lib/active_support/core_ext/hash.rb +10 -9
  71. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  72. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  73. data/lib/active_support/core_ext/integer/time.rb +11 -18
  74. data/lib/active_support/core_ext/integer.rb +5 -3
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/kernel.rb +5 -5
  79. data/lib/active_support/core_ext/load_error.rb +3 -22
  80. data/lib/active_support/core_ext/marshal.rb +8 -8
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -46
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +144 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +133 -30
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +44 -19
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -7
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/module.rb +13 -11
  94. data/lib/active_support/core_ext/name_error.rb +22 -2
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +129 -136
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +5 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -23
  99. data/lib/active_support/core_ext/numeric.rb +5 -3
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +27 -3
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +13 -93
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +51 -20
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  110. data/lib/active_support/core_ext/object/try.rb +81 -23
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/object.rb +14 -13
  113. data/lib/active_support/core_ext/range/compare_range.rb +76 -0
  114. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  115. data/lib/active_support/core_ext/range/each.rb +18 -17
  116. data/lib/active_support/core_ext/range/include_range.rb +7 -21
  117. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  118. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  119. data/lib/active_support/core_ext/range.rb +7 -4
  120. data/lib/active_support/core_ext/regexp.rb +2 -0
  121. data/lib/active_support/core_ext/securerandom.rb +45 -0
  122. data/lib/active_support/core_ext/string/access.rb +16 -6
  123. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  124. data/lib/active_support/core_ext/string/conversions.rb +7 -4
  125. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  126. data/lib/active_support/core_ext/string/filters.rb +48 -6
  127. data/lib/active_support/core_ext/string/indent.rb +6 -4
  128. data/lib/active_support/core_ext/string/inflections.rb +66 -24
  129. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  130. data/lib/active_support/core_ext/string/multibyte.rb +16 -7
  131. data/lib/active_support/core_ext/string/output_safety.rb +93 -40
  132. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  133. data/lib/active_support/core_ext/string/strip.rb +6 -5
  134. data/lib/active_support/core_ext/string/zones.rb +4 -2
  135. data/lib/active_support/core_ext/string.rb +15 -13
  136. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  137. data/lib/active_support/core_ext/time/calculations.rb +115 -52
  138. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  139. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  140. data/lib/active_support/core_ext/time/zones.rb +41 -7
  141. data/lib/active_support/core_ext/time.rb +7 -6
  142. data/lib/active_support/core_ext/uri.rb +6 -7
  143. data/lib/active_support/core_ext.rb +3 -1
  144. data/lib/active_support/current_attributes.rb +203 -0
  145. data/lib/active_support/dependencies/autoload.rb +2 -0
  146. data/lib/active_support/dependencies/interlock.rb +57 -0
  147. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  148. data/lib/active_support/dependencies.rb +208 -166
  149. data/lib/active_support/deprecation/behaviors.rb +44 -11
  150. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  151. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  152. data/lib/active_support/deprecation/method_wrappers.rb +61 -21
  153. data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
  154. data/lib/active_support/deprecation/reporting.rb +32 -12
  155. data/lib/active_support/deprecation.rb +12 -9
  156. data/lib/active_support/descendants_tracker.rb +57 -9
  157. data/lib/active_support/digest.rb +20 -0
  158. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  159. data/lib/active_support/duration/iso8601_serializer.rb +53 -0
  160. data/lib/active_support/duration.rb +315 -40
  161. data/lib/active_support/encrypted_configuration.rb +45 -0
  162. data/lib/active_support/encrypted_file.rb +100 -0
  163. data/lib/active_support/evented_file_update_checker.rb +234 -0
  164. data/lib/active_support/execution_wrapper.rb +129 -0
  165. data/lib/active_support/executor.rb +8 -0
  166. data/lib/active_support/file_update_checker.rb +62 -37
  167. data/lib/active_support/gem_version.rb +6 -4
  168. data/lib/active_support/gzip.rb +7 -5
  169. data/lib/active_support/hash_with_indifferent_access.rb +129 -30
  170. data/lib/active_support/i18n.rb +9 -6
  171. data/lib/active_support/i18n_railtie.rb +50 -14
  172. data/lib/active_support/inflections.rb +13 -11
  173. data/lib/active_support/inflector/inflections.rb +58 -13
  174. data/lib/active_support/inflector/methods.rb +159 -145
  175. data/lib/active_support/inflector/transliterate.rb +84 -34
  176. data/lib/active_support/inflector.rb +7 -5
  177. data/lib/active_support/json/decoding.rb +32 -30
  178. data/lib/active_support/json/encoding.rb +17 -60
  179. data/lib/active_support/json.rb +4 -2
  180. data/lib/active_support/key_generator.rb +11 -43
  181. data/lib/active_support/lazy_load_hooks.rb +53 -20
  182. data/lib/active_support/locale/en.rb +33 -0
  183. data/lib/active_support/locale/en.yml +2 -0
  184. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  185. data/lib/active_support/log_subscriber.rb +44 -19
  186. data/lib/active_support/logger.rb +9 -23
  187. data/lib/active_support/logger_silence.rb +32 -14
  188. data/lib/active_support/logger_thread_safe_level.rb +32 -8
  189. data/lib/active_support/message_encryptor.rb +166 -53
  190. data/lib/active_support/message_verifier.rb +149 -16
  191. data/lib/active_support/messages/metadata.rb +72 -0
  192. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  193. data/lib/active_support/messages/rotator.rb +56 -0
  194. data/lib/active_support/multibyte/chars.rb +56 -63
  195. data/lib/active_support/multibyte/unicode.rb +56 -290
  196. data/lib/active_support/multibyte.rb +4 -2
  197. data/lib/active_support/notifications/fanout.rb +109 -22
  198. data/lib/active_support/notifications/instrumenter.rb +107 -16
  199. data/lib/active_support/notifications.rb +51 -10
  200. data/lib/active_support/number_helper/number_converter.rb +16 -15
  201. data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -15
  202. data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
  203. data/lib/active_support/number_helper/number_to_human_converter.rb +13 -10
  204. data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -9
  205. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  206. data/lib/active_support/number_helper/number_to_phone_converter.rb +15 -5
  207. data/lib/active_support/number_helper/number_to_rounded_converter.rb +25 -57
  208. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  209. data/lib/active_support/number_helper.rb +105 -68
  210. data/lib/active_support/option_merger.rb +24 -4
  211. data/lib/active_support/ordered_hash.rb +7 -5
  212. data/lib/active_support/ordered_options.rb +27 -5
  213. data/lib/active_support/parameter_filter.rb +128 -0
  214. data/lib/active_support/per_thread_registry.rb +9 -4
  215. data/lib/active_support/proxy_object.rb +2 -0
  216. data/lib/active_support/rails.rb +10 -8
  217. data/lib/active_support/railtie.rb +43 -9
  218. data/lib/active_support/reloader.rb +130 -0
  219. data/lib/active_support/rescuable.rb +108 -53
  220. data/lib/active_support/security_utils.rb +15 -11
  221. data/lib/active_support/string_inquirer.rb +11 -4
  222. data/lib/active_support/subscriber.rb +74 -30
  223. data/lib/active_support/tagged_logging.rb +25 -13
  224. data/lib/active_support/test_case.rb +107 -44
  225. data/lib/active_support/testing/assertions.rb +151 -20
  226. data/lib/active_support/testing/autorun.rb +4 -2
  227. data/lib/active_support/testing/constant_lookup.rb +2 -1
  228. data/lib/active_support/testing/declarative.rb +3 -1
  229. data/lib/active_support/testing/deprecation.rb +13 -10
  230. data/lib/active_support/testing/file_fixtures.rb +38 -0
  231. data/lib/active_support/testing/isolation.rb +35 -26
  232. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  233. data/lib/active_support/testing/parallelization.rb +134 -0
  234. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  235. data/lib/active_support/testing/stream.rb +43 -0
  236. data/lib/active_support/testing/tagged_logging.rb +3 -1
  237. data/lib/active_support/testing/time_helpers.rb +84 -20
  238. data/lib/active_support/time.rb +14 -12
  239. data/lib/active_support/time_with_zone.rb +179 -39
  240. data/lib/active_support/values/time_zone.rb +203 -63
  241. data/lib/active_support/version.rb +3 -1
  242. data/lib/active_support/xml_mini/jdom.rb +116 -115
  243. data/lib/active_support/xml_mini/libxml.rb +16 -13
  244. data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
  245. data/lib/active_support/xml_mini/nokogiri.rb +14 -12
  246. data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
  247. data/lib/active_support/xml_mini/rexml.rb +11 -9
  248. data/lib/active_support/xml_mini.rb +38 -46
  249. data/lib/active_support.rb +13 -11
  250. metadata +84 -26
  251. data/lib/active_support/concurrency/latch.rb +0 -27
  252. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  253. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  254. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  255. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  256. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  257. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
  258. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  259. data/lib/active_support/core_ext/object/itself.rb +0 -15
  260. data/lib/active_support/core_ext/struct.rb +0 -6
  261. data/lib/active_support/core_ext/thread.rb +0 -86
  262. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  263. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,18 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
- require 'dalli'
4
+ require "dalli"
3
5
  rescue LoadError => e
4
6
  $stderr.puts "You don't have dalli installed in your application. Please add it to your Gemfile and run bundle install"
5
7
  raise e
6
8
  end
7
9
 
8
- require 'digest/md5'
9
- require 'active_support/core_ext/marshal'
10
- require 'active_support/core_ext/array/extract_options'
10
+ require "active_support/core_ext/array/extract_options"
11
11
 
12
12
  module ActiveSupport
13
13
  module Cache
14
14
  # A cache store implementation which stores data in Memcached:
15
- # http://memcached.org/
15
+ # https://memcached.org
16
16
  #
17
17
  # This is currently the most popular cache store for production websites.
18
18
  #
@@ -24,13 +24,49 @@ module ActiveSupport
24
24
  # MemCacheStore implements the Strategy::LocalCache strategy which implements
25
25
  # an in-memory cache inside of a block.
26
26
  class MemCacheStore < Store
27
+ # Provide support for raw values in the local cache strategy.
28
+ module LocalCacheWithRaw # :nodoc:
29
+ private
30
+ def write_entry(key, entry, **options)
31
+ if options[:raw] && local_cache
32
+ raw_entry = Entry.new(entry.value.to_s)
33
+ raw_entry.expires_at = entry.expires_at
34
+ super(key, raw_entry, **options)
35
+ else
36
+ super
37
+ end
38
+ end
39
+ end
40
+
41
+ # Advertise cache versioning support.
42
+ def self.supports_cache_versioning?
43
+ true
44
+ end
45
+
46
+ prepend Strategy::LocalCache
47
+ prepend LocalCacheWithRaw
48
+
27
49
  ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/n
28
50
 
29
- def self.build_mem_cache(*addresses)
51
+ # Creates a new Dalli::Client instance with specified addresses and options.
52
+ # By default address is equal localhost:11211.
53
+ #
54
+ # ActiveSupport::Cache::MemCacheStore.build_mem_cache
55
+ # # => #<Dalli::Client:0x007f98a47d2028 @servers=["localhost:11211"], @options={}, @ring=nil>
56
+ # ActiveSupport::Cache::MemCacheStore.build_mem_cache('localhost:10290')
57
+ # # => #<Dalli::Client:0x007f98a47b3a60 @servers=["localhost:10290"], @options={}, @ring=nil>
58
+ def self.build_mem_cache(*addresses) # :nodoc:
30
59
  addresses = addresses.flatten
31
60
  options = addresses.extract_options!
32
61
  addresses = ["localhost:11211"] if addresses.empty?
33
- Dalli::Client.new(addresses, options)
62
+ pool_options = retrieve_pool_options(options)
63
+
64
+ if pool_options.empty?
65
+ Dalli::Client.new(addresses, options)
66
+ else
67
+ ensure_connection_pool_added!
68
+ ConnectionPool.new(pool_options) { Dalli::Client.new(addresses, options.merge(threadsafe: false)) }
69
+ end
34
70
  end
35
71
 
36
72
  # Creates a new MemCacheStore object, with the given memcached server
@@ -53,82 +89,56 @@ module ActiveSupport
53
89
  @data = addresses.first
54
90
  else
55
91
  mem_cache_options = options.dup
56
- UNIVERSAL_OPTIONS.each{|name| mem_cache_options.delete(name)}
92
+ UNIVERSAL_OPTIONS.each { |name| mem_cache_options.delete(name) }
57
93
  @data = self.class.build_mem_cache(*(addresses + [mem_cache_options]))
58
94
  end
59
-
60
- extend Strategy::LocalCache
61
- extend LocalCacheWithRaw
62
- end
63
-
64
- # Reads multiple values from the cache using a single call to the
65
- # servers for all keys. Options can be passed in the last argument.
66
- def read_multi(*names)
67
- options = names.extract_options!
68
- options = merged_options(options)
69
- keys_to_names = Hash[names.map{|name| [escape_key(namespaced_key(name, options)), name]}]
70
- raw_values = @data.get_multi(keys_to_names.keys)
71
- values = {}
72
- raw_values.each do |key, value|
73
- entry = deserialize_entry(value)
74
- values[keys_to_names[key]] = entry.value unless entry.expired?
75
- end
76
- values
77
95
  end
78
96
 
79
97
  # Increment a cached value. This method uses the memcached incr atomic
80
98
  # operator and can only be used on values written with the :raw option.
81
99
  # Calling it on a value not stored with :raw will initialize that value
82
100
  # to zero.
83
- def increment(name, amount = 1, options = nil) # :nodoc:
101
+ def increment(name, amount = 1, options = nil)
84
102
  options = merged_options(options)
85
- instrument(:increment, name, :amount => amount) do
86
- @data.incr(escape_key(namespaced_key(name, options)), amount)
103
+ instrument(:increment, name, amount: amount) do
104
+ rescue_error_with nil do
105
+ @data.with { |c| c.incr(normalize_key(name, options), amount, options[:expires_in]) }
106
+ end
87
107
  end
88
- rescue Dalli::DalliError => e
89
- logger.error("DalliError (#{e}): #{e.message}") if logger
90
- nil
91
108
  end
92
109
 
93
110
  # Decrement a cached value. This method uses the memcached decr atomic
94
111
  # operator and can only be used on values written with the :raw option.
95
112
  # Calling it on a value not stored with :raw will initialize that value
96
113
  # to zero.
97
- def decrement(name, amount = 1, options = nil) # :nodoc:
114
+ def decrement(name, amount = 1, options = nil)
98
115
  options = merged_options(options)
99
- instrument(:decrement, name, :amount => amount) do
100
- @data.decr(escape_key(namespaced_key(name, options)), amount)
116
+ instrument(:decrement, name, amount: amount) do
117
+ rescue_error_with nil do
118
+ @data.with { |c| c.decr(normalize_key(name, options), amount, options[:expires_in]) }
119
+ end
101
120
  end
102
- rescue Dalli::DalliError => e
103
- logger.error("DalliError (#{e}): #{e.message}") if logger
104
- nil
105
121
  end
106
122
 
107
123
  # Clear the entire cache on all memcached servers. This method should
108
124
  # be used with care when shared cache is being used.
109
125
  def clear(options = nil)
110
- @data.flush_all
111
- rescue Dalli::DalliError => e
112
- logger.error("DalliError (#{e}): #{e.message}") if logger
113
- nil
126
+ rescue_error_with(nil) { @data.with { |c| c.flush_all } }
114
127
  end
115
128
 
116
129
  # Get the statistics from the memcached servers.
117
130
  def stats
118
- @data.stats
131
+ @data.with { |c| c.stats }
119
132
  end
120
133
 
121
- protected
134
+ private
122
135
  # Read an entry from the cache.
123
- def read_entry(key, options) # :nodoc:
124
- deserialize_entry(@data.get(escape_key(key), options))
125
- rescue Dalli::DalliError => e
126
- logger.error("DalliError (#{e}): #{e.message}") if logger
127
- nil
136
+ def read_entry(key, **options)
137
+ rescue_error_with(nil) { deserialize_entry(@data.with { |c| c.get(key, options) }) }
128
138
  end
129
139
 
130
140
  # Write an entry to the cache.
131
- def write_entry(key, entry, options) # :nodoc:
141
+ def write_entry(key, entry, **options)
132
142
  method = options && options[:unless_exist] ? :add : :set
133
143
  value = options[:raw] ? entry.value.to_s : entry
134
144
  expires_in = options[:expires_in].to_i
@@ -136,63 +146,57 @@ module ActiveSupport
136
146
  # Set the memcache expire a few minutes in the future to support race condition ttls on read
137
147
  expires_in += 5.minutes
138
148
  end
139
- @data.send(method, escape_key(key), value, expires_in, options)
140
- rescue Dalli::DalliError => e
141
- logger.error("DalliError (#{e}): #{e.message}") if logger
142
- false
149
+ rescue_error_with false do
150
+ @data.with { |c| c.send(method, key, value, expires_in, **options) }
151
+ end
143
152
  end
144
153
 
145
- # Delete an entry from the cache.
146
- def delete_entry(key, options) # :nodoc:
147
- @data.delete(escape_key(key))
148
- rescue Dalli::DalliError => e
149
- logger.error("DalliError (#{e}): #{e.message}") if logger
150
- false
154
+ # Reads multiple entries from the cache implementation.
155
+ def read_multi_entries(names, **options)
156
+ keys_to_names = Hash[names.map { |name| [normalize_key(name, options), name] }]
157
+
158
+ raw_values = @data.with { |c| c.get_multi(keys_to_names.keys) }
159
+ values = {}
160
+
161
+ raw_values.each do |key, value|
162
+ entry = deserialize_entry(value)
163
+
164
+ unless entry.expired? || entry.mismatched?(normalize_version(keys_to_names[key], options))
165
+ values[keys_to_names[key]] = entry.value
166
+ end
167
+ end
168
+
169
+ values
151
170
  end
152
171
 
153
- private
172
+ # Delete an entry from the cache.
173
+ def delete_entry(key, **options)
174
+ rescue_error_with(false) { @data.with { |c| c.delete(key) } }
175
+ end
154
176
 
155
177
  # Memcache keys are binaries. So we need to force their encoding to binary
156
178
  # before applying the regular expression to ensure we are escaping all
157
179
  # characters properly.
158
- def escape_key(key)
159
- key = key.to_s.dup
180
+ def normalize_key(key, options)
181
+ key = super.dup
160
182
  key = key.force_encoding(Encoding::ASCII_8BIT)
161
- key = key.gsub(ESCAPE_KEY_CHARS){ |match| "%#{match.getbyte(0).to_s(16).upcase}" }
162
- key = "#{key[0, 213]}:md5:#{Digest::MD5.hexdigest(key)}" if key.size > 250
183
+ key = key.gsub(ESCAPE_KEY_CHARS) { |match| "%#{match.getbyte(0).to_s(16).upcase}" }
184
+ key = "#{key[0, 213]}:md5:#{ActiveSupport::Digest.hexdigest(key)}" if key.size > 250
163
185
  key
164
186
  end
165
187
 
166
- def deserialize_entry(raw_value)
167
- if raw_value
168
- entry = Marshal.load(raw_value) rescue raw_value
188
+ def deserialize_entry(entry)
189
+ if entry
169
190
  entry.is_a?(Entry) ? entry : Entry.new(entry)
170
- else
171
- nil
172
191
  end
173
192
  end
174
193
 
175
- # Provide support for raw values in the local cache strategy.
176
- module LocalCacheWithRaw # :nodoc:
177
- protected
178
- def read_entry(key, options)
179
- entry = super
180
- if options[:raw] && local_cache && entry
181
- entry = deserialize_entry(entry.value)
182
- end
183
- entry
184
- end
185
-
186
- def write_entry(key, entry, options) # :nodoc:
187
- retval = super
188
- if options[:raw] && local_cache && retval
189
- raw_entry = Entry.new(entry.value.to_s)
190
- raw_entry.expires_at = entry.expires_at
191
- local_cache.write_entry(key, raw_entry, options)
192
- end
193
- retval
194
- end
195
- end
194
+ def rescue_error_with(fallback)
195
+ yield
196
+ rescue Dalli::DalliError => e
197
+ logger.error("DalliError (#{e}): #{e.message}") if logger
198
+ fallback
199
+ end
196
200
  end
197
201
  end
198
202
  end
@@ -1,10 +1,12 @@
1
- require 'monitor'
1
+ # frozen_string_literal: true
2
+
3
+ require "monitor"
2
4
 
3
5
  module ActiveSupport
4
6
  module Cache
5
7
  # A cache store implementation which stores everything into memory in the
6
8
  # same process. If you're running multiple Ruby on Rails server processes
7
- # (which is the case if you're using mongrel_cluster or Phusion Passenger),
9
+ # (which is the case if you're using Phusion Passenger or puma clustered mode),
8
10
  # then this means that Rails server process instances won't be able
9
11
  # to share cache data with each other and this may not be the most
10
12
  # appropriate cache in that scenario.
@@ -28,6 +30,12 @@ module ActiveSupport
28
30
  @pruning = false
29
31
  end
30
32
 
33
+ # Advertise cache versioning support.
34
+ def self.supports_cache_versioning?
35
+ true
36
+ end
37
+
38
+ # Delete all data stored in a given cache store.
31
39
  def clear(options = nil)
32
40
  synchronize do
33
41
  @data.clear
@@ -39,11 +47,11 @@ module ActiveSupport
39
47
  # Preemptively iterates through all stored keys and removes the ones which have expired.
40
48
  def cleanup(options = nil)
41
49
  options = merged_options(options)
42
- instrument(:cleanup, :size => @data.size) do
43
- keys = synchronize{ @data.keys }
50
+ instrument(:cleanup, size: @data.size) do
51
+ keys = synchronize { @data.keys }
44
52
  keys.each do |key|
45
53
  entry = @data[key]
46
- delete_entry(key, options) if entry && entry.expired?
54
+ delete_entry(key, **options) if entry && entry.expired?
47
55
  end
48
56
  end
49
57
  end
@@ -54,13 +62,13 @@ module ActiveSupport
54
62
  return if pruning?
55
63
  @pruning = true
56
64
  begin
57
- start_time = Time.now
65
+ start_time = Concurrent.monotonic_time
58
66
  cleanup
59
- instrument(:prune, target_size, :from => @cache_size) do
60
- keys = synchronize{ @key_access.keys.sort{|a,b| @key_access[a].to_f <=> @key_access[b].to_f} }
67
+ instrument(:prune, target_size, from: @cache_size) do
68
+ keys = synchronize { @key_access.keys.sort { |a, b| @key_access[a].to_f <=> @key_access[b].to_f } }
61
69
  keys.each do |key|
62
- delete_entry(key, options)
63
- return if @cache_size <= target_size || (max_time && Time.now - start_time > max_time)
70
+ delete_entry(key, **options)
71
+ return if @cache_size <= target_size || (max_time && Concurrent.monotonic_time - start_time > max_time)
64
72
  end
65
73
  end
66
74
  ensure
@@ -75,39 +83,22 @@ module ActiveSupport
75
83
 
76
84
  # Increment an integer value in the cache.
77
85
  def increment(name, amount = 1, options = nil)
78
- synchronize do
79
- options = merged_options(options)
80
- if num = read(name, options)
81
- num = num.to_i + amount
82
- write(name, num, options)
83
- num
84
- else
85
- nil
86
- end
87
- end
86
+ modify_value(name, amount, options)
88
87
  end
89
88
 
90
89
  # Decrement an integer value in the cache.
91
90
  def decrement(name, amount = 1, options = nil)
92
- synchronize do
93
- options = merged_options(options)
94
- if num = read(name, options)
95
- num = num.to_i - amount
96
- write(name, num, options)
97
- num
98
- else
99
- nil
100
- end
101
- end
91
+ modify_value(name, -amount, options)
102
92
  end
103
93
 
94
+ # Deletes cache entries if the cache key matches a given pattern.
104
95
  def delete_matched(matcher, options = nil)
105
96
  options = merged_options(options)
106
97
  instrument(:delete_matched, matcher.inspect) do
107
98
  matcher = key_matcher(matcher, options)
108
99
  keys = synchronize { @data.keys }
109
100
  keys.each do |key|
110
- delete_entry(key, options) if key.match(matcher)
101
+ delete_entry(key, **options) if key.match(matcher)
111
102
  end
112
103
  end
113
104
  end
@@ -122,18 +113,19 @@ module ActiveSupport
122
113
  @monitor.synchronize(&block)
123
114
  end
124
115
 
125
- protected
126
-
116
+ private
127
117
  PER_ENTRY_OVERHEAD = 240
128
118
 
129
119
  def cached_size(key, entry)
130
120
  key.to_s.bytesize + entry.size + PER_ENTRY_OVERHEAD
131
121
  end
132
122
 
133
- def read_entry(key, options) # :nodoc:
123
+ def read_entry(key, **options)
134
124
  entry = @data[key]
135
125
  synchronize do
136
126
  if entry
127
+ entry = entry.dup
128
+ entry.dup_value!
137
129
  @key_access[key] = Time.now.to_f
138
130
  else
139
131
  @key_access.delete(key)
@@ -142,7 +134,7 @@ module ActiveSupport
142
134
  entry
143
135
  end
144
136
 
145
- def write_entry(key, entry, options) # :nodoc:
137
+ def write_entry(key, entry, **options)
146
138
  entry.dup_value!
147
139
  synchronize do
148
140
  old_entry = @data[key]
@@ -159,7 +151,7 @@ module ActiveSupport
159
151
  end
160
152
  end
161
153
 
162
- def delete_entry(key, options) # :nodoc:
154
+ def delete_entry(key, **options)
163
155
  synchronize do
164
156
  @key_access.delete(key)
165
157
  entry = @data.delete(key)
@@ -167,6 +159,17 @@ module ActiveSupport
167
159
  !!entry
168
160
  end
169
161
  end
162
+
163
+ def modify_value(name, amount, options)
164
+ synchronize do
165
+ options = merged_options(options)
166
+ if num = read(name, options)
167
+ num = num.to_i + amount
168
+ write(name, num, options)
169
+ num
170
+ end
171
+ end
172
+ end
170
173
  end
171
174
  end
172
175
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  module Cache
3
5
  # A cache store implementation which doesn't actually store anything. Useful in
@@ -8,9 +10,11 @@ module ActiveSupport
8
10
  # be cached inside blocks that utilize this strategy. See
9
11
  # ActiveSupport::Cache::Strategy::LocalCache for more details.
10
12
  class NullStore < Store
11
- def initialize(options = nil)
12
- super(options)
13
- extend Strategy::LocalCache
13
+ prepend Strategy::LocalCache
14
+
15
+ # Advertise cache versioning support.
16
+ def self.supports_cache_versioning?
17
+ true
14
18
  end
15
19
 
16
20
  def clear(options = nil)
@@ -28,15 +32,15 @@ module ActiveSupport
28
32
  def delete_matched(matcher, options = nil)
29
33
  end
30
34
 
31
- protected
32
- def read_entry(key, options) # :nodoc:
35
+ private
36
+ def read_entry(key, **options)
33
37
  end
34
38
 
35
- def write_entry(key, entry, options) # :nodoc:
39
+ def write_entry(key, entry, **options)
36
40
  true
37
41
  end
38
42
 
39
- def delete_entry(key, options) # :nodoc:
43
+ def delete_entry(key, **options)
40
44
  false
41
45
  end
42
46
  end