activesupport 3.1.0 → 5.0.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +798 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +13 -7
- data/lib/active_support/array_inquirer.rb +44 -0
- data/lib/active_support/backtrace_cleaner.rb +38 -34
- data/lib/active_support/benchmarkable.rb +17 -28
- data/lib/active_support/cache/file_store.rb +85 -70
- data/lib/active_support/cache/mem_cache_store.rb +75 -66
- data/lib/active_support/cache/memory_store.rb +31 -23
- data/lib/active_support/cache/null_store.rb +41 -0
- data/lib/active_support/cache/strategy/local_cache.rb +73 -70
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
- data/lib/active_support/cache.rb +360 -294
- data/lib/active_support/callbacks.rb +563 -393
- data/lib/active_support/concern.rb +42 -34
- data/lib/active_support/concurrency/latch.rb +19 -0
- data/lib/active_support/concurrency/share_lock.rb +186 -0
- data/lib/active_support/configurable.rb +70 -12
- data/lib/active_support/core_ext/array/access.rb +53 -9
- data/lib/active_support/core_ext/array/conversions.rb +109 -62
- data/lib/active_support/core_ext/array/extract_options.rb +2 -2
- data/lib/active_support/core_ext/array/grouping.rb +39 -32
- data/lib/active_support/core_ext/array/inquiry.rb +17 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
- data/lib/active_support/core_ext/array/wrap.rb +16 -18
- data/lib/active_support/core_ext/array.rb +2 -2
- data/lib/active_support/core_ext/benchmark.rb +7 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -36
- data/lib/active_support/core_ext/class/attribute.rb +47 -34
- data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -79
- data/lib/active_support/core_ext/class/subclasses.rb +12 -7
- data/lib/active_support/core_ext/class.rb +0 -3
- data/lib/active_support/core_ext/date/blank.rb +12 -0
- data/lib/active_support/core_ext/date/calculations.rb +57 -167
- data/lib/active_support/core_ext/date/conversions.rb +31 -42
- data/lib/active_support/core_ext/date/zones.rb +2 -10
- data/lib/active_support/core_ext/date.rb +5 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +335 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +1 -0
- data/lib/active_support/core_ext/date_time/blank.rb +12 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +132 -65
- data/lib/active_support/core_ext/date_time/compatibility.rb +5 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +36 -34
- data/lib/active_support/core_ext/date_time.rb +5 -0
- data/lib/active_support/core_ext/digest/uuid.rb +51 -0
- data/lib/active_support/core_ext/enumerable.rb +81 -74
- data/lib/active_support/core_ext/file/atomic.rb +53 -26
- data/lib/active_support/core_ext/file.rb +0 -1
- data/lib/active_support/core_ext/hash/compact.rb +20 -0
- data/lib/active_support/core_ext/hash/conversions.rb +175 -70
- data/lib/active_support/core_ext/hash/deep_merge.rb +30 -8
- data/lib/active_support/core_ext/hash/except.rb +11 -12
- data/lib/active_support/core_ext/hash/indifferent_access.rb +7 -8
- data/lib/active_support/core_ext/hash/keys.rb +147 -24
- data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
- data/lib/active_support/core_ext/hash/slice.rb +22 -14
- data/lib/active_support/core_ext/hash/transform_values.rb +29 -0
- data/lib/active_support/core_ext/hash.rb +2 -2
- data/lib/active_support/core_ext/integer/inflections.rb +13 -1
- data/lib/active_support/core_ext/integer/multiple.rb +4 -0
- data/lib/active_support/core_ext/integer/time.rb +12 -22
- data/lib/active_support/core_ext/kernel/agnostics.rb +2 -2
- data/lib/active_support/core_ext/kernel/concern.rb +12 -0
- data/lib/active_support/core_ext/kernel/debugger.rb +2 -15
- data/lib/active_support/core_ext/kernel/reporting.rb +12 -62
- data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
- data/lib/active_support/core_ext/kernel.rb +2 -3
- data/lib/active_support/core_ext/load_error.rb +14 -7
- data/lib/active_support/core_ext/marshal.rb +22 -0
- data/lib/active_support/core_ext/module/aliasing.rb +16 -12
- data/lib/active_support/core_ext/module/anonymous.rb +12 -8
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
- data/lib/active_support/core_ext/module/attribute_accessors.rb +165 -13
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
- data/lib/active_support/core_ext/module/concerning.rb +135 -0
- data/lib/active_support/core_ext/module/delegation.rb +141 -68
- data/lib/active_support/core_ext/module/deprecation.rb +17 -3
- data/lib/active_support/core_ext/module/introspection.rb +9 -31
- data/lib/active_support/core_ext/module/method_transplanting.rb +3 -0
- data/lib/active_support/core_ext/module/qualified_const.rb +70 -0
- data/lib/active_support/core_ext/module/reachable.rb +1 -3
- data/lib/active_support/core_ext/module/remove_method.rb +24 -5
- data/lib/active_support/core_ext/module.rb +3 -3
- data/lib/active_support/core_ext/name_error.rb +15 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
- data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
- data/lib/active_support/core_ext/numeric/time.rb +31 -36
- data/lib/active_support/core_ext/numeric.rb +2 -0
- data/lib/active_support/core_ext/object/acts_like.rb +4 -4
- data/lib/active_support/core_ext/object/blank.rb +52 -18
- data/lib/active_support/core_ext/object/deep_dup.rb +53 -0
- data/lib/active_support/core_ext/object/duplicable.rb +12 -20
- data/lib/active_support/core_ext/object/inclusion.rb +13 -1
- data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
- data/lib/active_support/core_ext/object/json.rb +205 -0
- data/lib/active_support/core_ext/object/to_param.rb +1 -55
- data/lib/active_support/core_ext/object/to_query.rb +66 -9
- data/lib/active_support/core_ext/object/try.rb +124 -33
- data/lib/active_support/core_ext/object/with_options.rb +37 -11
- data/lib/active_support/core_ext/object.rb +2 -1
- data/lib/active_support/core_ext/range/conversions.rb +17 -7
- data/lib/active_support/core_ext/range/each.rb +21 -0
- data/lib/active_support/core_ext/range/include_range.rb +20 -18
- data/lib/active_support/core_ext/range/overlaps.rb +1 -1
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/securerandom.rb +23 -0
- data/lib/active_support/core_ext/string/access.rb +95 -90
- data/lib/active_support/core_ext/string/behavior.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +41 -38
- data/lib/active_support/core_ext/string/exclude.rb +6 -1
- data/lib/active_support/core_ext/string/filters.rb +70 -17
- data/lib/active_support/core_ext/string/indent.rb +43 -0
- data/lib/active_support/core_ext/string/inflections.rb +139 -59
- data/lib/active_support/core_ext/string/inquiry.rb +2 -2
- data/lib/active_support/core_ext/string/multibyte.rb +46 -65
- data/lib/active_support/core_ext/string/output_safety.rb +153 -56
- data/lib/active_support/core_ext/string/strip.rb +3 -6
- data/lib/active_support/core_ext/string/zones.rb +14 -0
- data/lib/active_support/core_ext/string.rb +2 -3
- data/lib/active_support/core_ext/struct.rb +3 -0
- data/lib/active_support/core_ext/time/calculations.rb +173 -173
- data/lib/active_support/core_ext/time/compatibility.rb +5 -0
- data/lib/active_support/core_ext/time/conversions.rb +33 -29
- data/lib/active_support/core_ext/time/marshal.rb +2 -56
- data/lib/active_support/core_ext/time/zones.rb +57 -32
- data/lib/active_support/core_ext/time.rb +5 -0
- data/lib/active_support/core_ext/uri.rb +13 -19
- data/lib/active_support/core_ext.rb +3 -2
- data/lib/active_support/dependencies/autoload.rb +47 -20
- data/lib/active_support/dependencies/interlock.rb +51 -0
- data/lib/active_support/dependencies.rb +315 -265
- data/lib/active_support/deprecation/behaviors.rb +71 -30
- data/lib/active_support/deprecation/instance_delegator.rb +24 -0
- data/lib/active_support/deprecation/method_wrappers.rb +59 -18
- data/lib/active_support/deprecation/proxy_wrappers.rb +82 -14
- data/lib/active_support/deprecation/reporting.rb +61 -14
- data/lib/active_support/deprecation.rb +38 -13
- data/lib/active_support/descendants_tracker.rb +34 -19
- data/lib/active_support/duration/iso8601_parser.rb +122 -0
- data/lib/active_support/duration/iso8601_serializer.rb +51 -0
- data/lib/active_support/duration.rb +85 -14
- data/lib/active_support/evented_file_update_checker.rb +194 -0
- data/lib/active_support/execution_wrapper.rb +117 -0
- data/lib/active_support/executor.rb +6 -0
- data/lib/active_support/file_update_checker.rb +138 -17
- data/lib/active_support/gem_version.rb +15 -0
- data/lib/active_support/gzip.rb +11 -5
- data/lib/active_support/hash_with_indifferent_access.rb +199 -49
- data/lib/active_support/i18n.rb +6 -2
- data/lib/active_support/i18n_railtie.rb +40 -21
- data/lib/active_support/inflections.rb +22 -13
- data/lib/active_support/inflector/inflections.rb +175 -144
- data/lib/active_support/inflector/methods.rb +328 -91
- data/lib/active_support/inflector/transliterate.rb +51 -37
- data/lib/active_support/json/decoding.rb +31 -22
- data/lib/active_support/json/encoding.rb +88 -248
- data/lib/active_support/key_generator.rb +71 -0
- data/lib/active_support/lazy_load_hooks.rb +27 -25
- data/lib/active_support/locale/en.yml +102 -3
- data/lib/active_support/log_subscriber/test_helper.rb +24 -21
- data/lib/active_support/log_subscriber.rb +36 -49
- data/lib/active_support/logger.rb +106 -0
- data/lib/active_support/logger_silence.rb +28 -0
- data/lib/active_support/logger_thread_safe_level.rb +31 -0
- data/lib/active_support/message_encryptor.rb +72 -36
- data/lib/active_support/message_verifier.rb +96 -24
- data/lib/active_support/multibyte/chars.rb +88 -333
- data/lib/active_support/multibyte/unicode.rb +156 -136
- data/lib/active_support/multibyte.rb +5 -28
- data/lib/active_support/notifications/fanout.rb +115 -19
- data/lib/active_support/notifications/instrumenter.rb +52 -15
- data/lib/active_support/notifications.rb +168 -33
- data/lib/active_support/number_helper/number_converter.rb +182 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +44 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +28 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +62 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +92 -0
- data/lib/active_support/number_helper.rb +368 -0
- data/lib/active_support/option_merger.rb +1 -1
- data/lib/active_support/ordered_hash.rb +18 -183
- data/lib/active_support/ordered_options.rb +44 -24
- data/lib/active_support/per_thread_registry.rb +58 -0
- data/lib/active_support/proxy_object.rb +13 -0
- data/lib/active_support/rails.rb +27 -0
- data/lib/active_support/railtie.rb +25 -34
- data/lib/active_support/reloader.rb +129 -0
- data/lib/active_support/rescuable.rb +98 -48
- data/lib/active_support/security_utils.rb +27 -0
- data/lib/active_support/string_inquirer.rb +14 -9
- data/lib/active_support/subscriber.rb +120 -0
- data/lib/active_support/tagged_logging.rb +78 -0
- data/lib/active_support/test_case.rb +69 -17
- data/lib/active_support/testing/assertions.rb +43 -41
- data/lib/active_support/testing/autorun.rb +12 -0
- data/lib/active_support/testing/constant_lookup.rb +50 -0
- data/lib/active_support/testing/declarative.rb +7 -21
- data/lib/active_support/testing/deprecation.rb +14 -33
- data/lib/active_support/testing/file_fixtures.rb +34 -0
- data/lib/active_support/testing/isolation.rb +53 -95
- data/lib/active_support/testing/method_call_assertions.rb +41 -0
- data/lib/active_support/testing/setup_and_teardown.rb +21 -82
- data/lib/active_support/testing/stream.rb +42 -0
- data/lib/active_support/testing/tagged_logging.rb +25 -0
- data/lib/active_support/testing/time_helpers.rb +134 -0
- data/lib/active_support/time.rb +6 -23
- data/lib/active_support/time_with_zone.rb +239 -92
- data/lib/active_support/values/time_zone.rb +236 -160
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +5 -7
- data/lib/active_support/xml_mini/jdom.rb +19 -13
- data/lib/active_support/xml_mini/libxml.rb +3 -4
- data/lib/active_support/xml_mini/libxmlsax.rb +2 -3
- data/lib/active_support/xml_mini/nokogiri.rb +3 -4
- data/lib/active_support/xml_mini/nokogirisax.rb +2 -3
- data/lib/active_support/xml_mini/rexml.rb +8 -10
- data/lib/active_support/xml_mini.rb +66 -34
- data/lib/active_support.rb +40 -23
- metadata +185 -134
- data/CHANGELOG +0 -1534
- data/lib/active_support/base64.rb +0 -42
- data/lib/active_support/basic_object.rb +0 -21
- data/lib/active_support/buffered_logger.rb +0 -137
- data/lib/active_support/cache/compressed_mem_cache_store.rb +0 -13
- data/lib/active_support/cache/synchronized_memory_store.rb +0 -11
- data/lib/active_support/core_ext/array/random_access.rb +0 -30
- data/lib/active_support/core_ext/array/uniq_by.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -44
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +0 -178
- data/lib/active_support/core_ext/date/freeze.rb +0 -31
- data/lib/active_support/core_ext/date_time/zones.rb +0 -21
- data/lib/active_support/core_ext/exception.rb +0 -3
- data/lib/active_support/core_ext/file/path.rb +0 -5
- data/lib/active_support/core_ext/float/rounding.rb +0 -19
- data/lib/active_support/core_ext/float.rb +0 -1
- data/lib/active_support/core_ext/hash/deep_dup.rb +0 -11
- data/lib/active_support/core_ext/hash/diff.rb +0 -13
- data/lib/active_support/core_ext/kernel/requires.rb +0 -28
- data/lib/active_support/core_ext/logger.rb +0 -81
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +0 -31
- data/lib/active_support/core_ext/module/method_names.rb +0 -14
- data/lib/active_support/core_ext/module/synchronization.rb +0 -43
- data/lib/active_support/core_ext/object/to_json.rb +0 -19
- data/lib/active_support/core_ext/proc.rb +0 -14
- data/lib/active_support/core_ext/process/daemon.rb +0 -23
- data/lib/active_support/core_ext/process.rb +0 -1
- data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
- data/lib/active_support/core_ext/range/cover.rb +0 -3
- data/lib/active_support/core_ext/rexml.rb +0 -46
- data/lib/active_support/core_ext/string/encoding.rb +0 -11
- data/lib/active_support/core_ext/string/interpolation.rb +0 -2
- data/lib/active_support/core_ext/string/xchar.rb +0 -18
- data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
- data/lib/active_support/file_watcher.rb +0 -36
- data/lib/active_support/json/variable.rb +0 -9
- data/lib/active_support/memoizable.rb +0 -105
- data/lib/active_support/multibyte/exceptions.rb +0 -8
- data/lib/active_support/multibyte/utils.rb +0 -60
- data/lib/active_support/ruby/shim.rb +0 -22
- data/lib/active_support/secure_random.rb +0 -6
- data/lib/active_support/testing/mochaing.rb +0 -7
- data/lib/active_support/testing/pending.rb +0 -52
- data/lib/active_support/testing/performance/jruby.rb +0 -115
- data/lib/active_support/testing/performance/rubinius.rb +0 -113
- data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
- data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
- data/lib/active_support/testing/performance/ruby.rb +0 -152
- data/lib/active_support/testing/performance.rb +0 -317
- data/lib/active_support/time/autoload.rb +0 -5
- data/lib/active_support/whiny_nil.rb +0 -60
@@ -1,17 +1,18 @@
|
|
1
1
|
begin
|
2
|
-
require '
|
2
|
+
require 'dalli'
|
3
3
|
rescue LoadError => e
|
4
|
-
$stderr.puts "You don't have
|
4
|
+
$stderr.puts "You don't have dalli installed in your application. Please add it to your Gemfile and run bundle install"
|
5
5
|
raise e
|
6
6
|
end
|
7
7
|
|
8
8
|
require 'digest/md5'
|
9
|
-
require 'active_support/core_ext/
|
9
|
+
require 'active_support/core_ext/marshal'
|
10
|
+
require 'active_support/core_ext/array/extract_options'
|
10
11
|
|
11
12
|
module ActiveSupport
|
12
13
|
module Cache
|
13
14
|
# A cache store implementation which stores data in Memcached:
|
14
|
-
# http://
|
15
|
+
# http://memcached.org/
|
15
16
|
#
|
16
17
|
# This is currently the most popular cache store for production websites.
|
17
18
|
#
|
@@ -21,23 +22,47 @@ module ActiveSupport
|
|
21
22
|
# server goes down, then MemCacheStore will ignore it until it comes back up.
|
22
23
|
#
|
23
24
|
# MemCacheStore implements the Strategy::LocalCache strategy which implements
|
24
|
-
# an in
|
25
|
+
# an in-memory cache inside of a block.
|
25
26
|
class MemCacheStore < Store
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
# Provide support for raw values in the local cache strategy.
|
28
|
+
module LocalCacheWithRaw # :nodoc:
|
29
|
+
protected
|
30
|
+
def read_entry(key, options)
|
31
|
+
entry = super
|
32
|
+
if options[:raw] && local_cache && entry
|
33
|
+
entry = deserialize_entry(entry.value)
|
34
|
+
end
|
35
|
+
entry
|
36
|
+
end
|
37
|
+
|
38
|
+
def write_entry(key, entry, options) # :nodoc:
|
39
|
+
if options[:raw] && local_cache
|
40
|
+
raw_entry = Entry.new(entry.value.to_s)
|
41
|
+
raw_entry.expires_at = entry.expires_at
|
42
|
+
super(key, raw_entry, options)
|
43
|
+
else
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
32
47
|
end
|
33
48
|
|
49
|
+
prepend Strategy::LocalCache
|
50
|
+
prepend LocalCacheWithRaw
|
51
|
+
|
34
52
|
ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/n
|
35
53
|
|
36
|
-
|
54
|
+
# Creates a new Dalli::Client instance with specified addresses and options.
|
55
|
+
# By default address is equal localhost:11211.
|
56
|
+
#
|
57
|
+
# ActiveSupport::Cache::MemCacheStore.build_mem_cache
|
58
|
+
# # => #<Dalli::Client:0x007f98a47d2028 @servers=["localhost:11211"], @options={}, @ring=nil>
|
59
|
+
# ActiveSupport::Cache::MemCacheStore.build_mem_cache('localhost:10290')
|
60
|
+
# # => #<Dalli::Client:0x007f98a47b3a60 @servers=["localhost:10290"], @options={}, @ring=nil>
|
61
|
+
def self.build_mem_cache(*addresses) # :nodoc:
|
37
62
|
addresses = addresses.flatten
|
38
63
|
options = addresses.extract_options!
|
39
64
|
addresses = ["localhost:11211"] if addresses.empty?
|
40
|
-
|
65
|
+
Dalli::Client.new(addresses, options)
|
41
66
|
end
|
42
67
|
|
43
68
|
# Creates a new MemCacheStore object, with the given memcached server
|
@@ -48,26 +73,21 @@ module ActiveSupport
|
|
48
73
|
#
|
49
74
|
# If no addresses are specified, then MemCacheStore will connect to
|
50
75
|
# localhost port 11211 (the default memcached port).
|
51
|
-
#
|
52
|
-
# Instead of addresses one can pass in a MemCache-like object. For example:
|
53
|
-
#
|
54
|
-
# require 'memcached' # gem install memcached; uses C bindings to libmemcached
|
55
|
-
# ActiveSupport::Cache::MemCacheStore.new(Memcached::Rails.new("localhost:11211"))
|
56
76
|
def initialize(*addresses)
|
57
77
|
addresses = addresses.flatten
|
58
78
|
options = addresses.extract_options!
|
59
79
|
super(options)
|
60
80
|
|
61
|
-
|
81
|
+
unless [String, Dalli::Client, NilClass].include?(addresses.first.class)
|
82
|
+
raise ArgumentError, "First argument must be an empty array, an array of hosts or a Dalli::Client instance."
|
83
|
+
end
|
84
|
+
if addresses.first.is_a?(Dalli::Client)
|
62
85
|
@data = addresses.first
|
63
86
|
else
|
64
87
|
mem_cache_options = options.dup
|
65
88
|
UNIVERSAL_OPTIONS.each{|name| mem_cache_options.delete(name)}
|
66
89
|
@data = self.class.build_mem_cache(*(addresses + [mem_cache_options]))
|
67
90
|
end
|
68
|
-
|
69
|
-
extend Strategy::LocalCache
|
70
|
-
extend LocalCacheWithRaw
|
71
91
|
end
|
72
92
|
|
73
93
|
# Reads multiple values from the cache using a single call to the
|
@@ -75,7 +95,8 @@ module ActiveSupport
|
|
75
95
|
def read_multi(*names)
|
76
96
|
options = names.extract_options!
|
77
97
|
options = merged_options(options)
|
78
|
-
|
98
|
+
|
99
|
+
keys_to_names = Hash[names.map{|name| [normalize_key(name, options), name]}]
|
79
100
|
raw_values = @data.get_multi(keys_to_names.keys, :raw => true)
|
80
101
|
values = {}
|
81
102
|
raw_values.each do |key, value|
|
@@ -91,12 +112,11 @@ module ActiveSupport
|
|
91
112
|
# to zero.
|
92
113
|
def increment(name, amount = 1, options = nil) # :nodoc:
|
93
114
|
options = merged_options(options)
|
94
|
-
|
95
|
-
|
115
|
+
instrument(:increment, name, :amount => amount) do
|
116
|
+
rescue_error_with nil do
|
117
|
+
@data.incr(normalize_key(name, options), amount)
|
118
|
+
end
|
96
119
|
end
|
97
|
-
response == Response::NOT_FOUND ? nil : response.to_i
|
98
|
-
rescue MemCache::MemCacheError
|
99
|
-
nil
|
100
120
|
end
|
101
121
|
|
102
122
|
# Decrement a cached value. This method uses the memcached decr atomic
|
@@ -105,18 +125,17 @@ module ActiveSupport
|
|
105
125
|
# to zero.
|
106
126
|
def decrement(name, amount = 1, options = nil) # :nodoc:
|
107
127
|
options = merged_options(options)
|
108
|
-
|
109
|
-
|
128
|
+
instrument(:decrement, name, :amount => amount) do
|
129
|
+
rescue_error_with nil do
|
130
|
+
@data.decr(normalize_key(name, options), amount)
|
131
|
+
end
|
110
132
|
end
|
111
|
-
response == Response::NOT_FOUND ? nil : response.to_i
|
112
|
-
rescue MemCache::MemCacheError
|
113
|
-
nil
|
114
133
|
end
|
115
134
|
|
116
135
|
# Clear the entire cache on all memcached servers. This method should
|
117
136
|
# be used with care when shared cache is being used.
|
118
137
|
def clear(options = nil)
|
119
|
-
@data.flush_all
|
138
|
+
rescue_error_with(nil) { @data.flush_all }
|
120
139
|
end
|
121
140
|
|
122
141
|
# Get the statistics from the memcached servers.
|
@@ -127,10 +146,7 @@ module ActiveSupport
|
|
127
146
|
protected
|
128
147
|
# Read an entry from the cache.
|
129
148
|
def read_entry(key, options) # :nodoc:
|
130
|
-
deserialize_entry(@data.get(
|
131
|
-
rescue MemCache::MemCacheError => e
|
132
|
-
logger.error("MemCacheError (#{e}): #{e.message}") if logger
|
133
|
-
nil
|
149
|
+
rescue_error_with(nil) { deserialize_entry(@data.get(key, options)) }
|
134
150
|
end
|
135
151
|
|
136
152
|
# Write an entry to the cache.
|
@@ -142,20 +158,14 @@ module ActiveSupport
|
|
142
158
|
# Set the memcache expire a few minutes in the future to support race condition ttls on read
|
143
159
|
expires_in += 5.minutes
|
144
160
|
end
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
logger.error("MemCacheError (#{e}): #{e.message}") if logger
|
149
|
-
false
|
161
|
+
rescue_error_with false do
|
162
|
+
@data.send(method, key, value, expires_in, options)
|
163
|
+
end
|
150
164
|
end
|
151
165
|
|
152
166
|
# Delete an entry from the cache.
|
153
167
|
def delete_entry(key, options) # :nodoc:
|
154
|
-
|
155
|
-
response == Response::DELETED
|
156
|
-
rescue MemCache::MemCacheError => e
|
157
|
-
logger.error("MemCacheError (#{e}): #{e.message}") if logger
|
158
|
-
false
|
168
|
+
rescue_error_with(false) { @data.delete(key) }
|
159
169
|
end
|
160
170
|
|
161
171
|
private
|
@@ -163,36 +173,35 @@ module ActiveSupport
|
|
163
173
|
# Memcache keys are binaries. So we need to force their encoding to binary
|
164
174
|
# before applying the regular expression to ensure we are escaping all
|
165
175
|
# characters properly.
|
166
|
-
def
|
167
|
-
key =
|
168
|
-
key = key.force_encoding(
|
176
|
+
def normalize_key(key, options)
|
177
|
+
key = super.dup
|
178
|
+
key = key.force_encoding(Encoding::ASCII_8BIT)
|
169
179
|
key = key.gsub(ESCAPE_KEY_CHARS){ |match| "%#{match.getbyte(0).to_s(16).upcase}" }
|
170
180
|
key = "#{key[0, 213]}:md5:#{Digest::MD5.hexdigest(key)}" if key.size > 250
|
171
181
|
key
|
172
182
|
end
|
173
183
|
|
184
|
+
def escape_key(key)
|
185
|
+
ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
|
186
|
+
`escape_key` is deprecated and will be removed from Rails 5.1.
|
187
|
+
Please use `normalize_key` which will return a fully resolved key or nothing.
|
188
|
+
MESSAGE
|
189
|
+
key
|
190
|
+
end
|
191
|
+
|
174
192
|
def deserialize_entry(raw_value)
|
175
193
|
if raw_value
|
176
194
|
entry = Marshal.load(raw_value) rescue raw_value
|
177
195
|
entry.is_a?(Entry) ? entry : Entry.new(entry)
|
178
|
-
else
|
179
|
-
nil
|
180
196
|
end
|
181
197
|
end
|
182
198
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
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
|
199
|
+
def rescue_error_with(fallback)
|
200
|
+
yield
|
201
|
+
rescue Dalli::DalliError => e
|
202
|
+
logger.error("DalliError (#{e}): #{e.message}") if logger
|
203
|
+
fallback
|
204
|
+
end
|
196
205
|
end
|
197
206
|
end
|
198
207
|
end
|
@@ -36,6 +36,7 @@ module ActiveSupport
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
# Preemptively iterates through all stored keys and removes the ones which have expired.
|
39
40
|
def cleanup(options = nil)
|
40
41
|
options = merged_options(options)
|
41
42
|
instrument(:cleanup, :size => @data.size) do
|
@@ -74,30 +75,12 @@ module ActiveSupport
|
|
74
75
|
|
75
76
|
# Increment an integer value in the cache.
|
76
77
|
def increment(name, amount = 1, options = nil)
|
77
|
-
|
78
|
-
options = merged_options(options)
|
79
|
-
if num = read(name, options)
|
80
|
-
num = num.to_i + amount
|
81
|
-
write(name, num, options)
|
82
|
-
num
|
83
|
-
else
|
84
|
-
nil
|
85
|
-
end
|
86
|
-
end
|
78
|
+
modify_value(name, amount, options)
|
87
79
|
end
|
88
80
|
|
89
81
|
# Decrement an integer value in the cache.
|
90
82
|
def decrement(name, amount = 1, options = nil)
|
91
|
-
|
92
|
-
options = merged_options(options)
|
93
|
-
if num = read(name, options)
|
94
|
-
num = num.to_i - amount
|
95
|
-
write(name, num, options)
|
96
|
-
num
|
97
|
-
else
|
98
|
-
nil
|
99
|
-
end
|
100
|
-
end
|
83
|
+
modify_value(name, -amount, options)
|
101
84
|
end
|
102
85
|
|
103
86
|
def delete_matched(matcher, options = nil)
|
@@ -122,6 +105,13 @@ module ActiveSupport
|
|
122
105
|
end
|
123
106
|
|
124
107
|
protected
|
108
|
+
|
109
|
+
PER_ENTRY_OVERHEAD = 240
|
110
|
+
|
111
|
+
def cached_size(key, entry) # :nodoc:
|
112
|
+
key.to_s.bytesize + entry.size + PER_ENTRY_OVERHEAD
|
113
|
+
end
|
114
|
+
|
125
115
|
def read_entry(key, options) # :nodoc:
|
126
116
|
entry = @data[key]
|
127
117
|
synchronize do
|
@@ -135,10 +125,15 @@ module ActiveSupport
|
|
135
125
|
end
|
136
126
|
|
137
127
|
def write_entry(key, entry, options) # :nodoc:
|
128
|
+
entry.dup_value!
|
138
129
|
synchronize do
|
139
130
|
old_entry = @data[key]
|
140
|
-
|
141
|
-
|
131
|
+
return false if @data.key?(key) && options[:unless_exist]
|
132
|
+
if old_entry
|
133
|
+
@cache_size -= (old_entry.size - entry.size)
|
134
|
+
else
|
135
|
+
@cache_size += cached_size(key, entry)
|
136
|
+
end
|
142
137
|
@key_access[key] = Time.now.to_f
|
143
138
|
@data[key] = entry
|
144
139
|
prune(@max_size * 0.75, @max_prune_time) if @cache_size > @max_size
|
@@ -150,10 +145,23 @@ module ActiveSupport
|
|
150
145
|
synchronize do
|
151
146
|
@key_access.delete(key)
|
152
147
|
entry = @data.delete(key)
|
153
|
-
@cache_size -= entry
|
148
|
+
@cache_size -= cached_size(key, entry) if entry
|
154
149
|
!!entry
|
155
150
|
end
|
156
151
|
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def modify_value(name, amount, options)
|
156
|
+
synchronize do
|
157
|
+
options = merged_options(options)
|
158
|
+
if num = read(name, options)
|
159
|
+
num = num.to_i + amount
|
160
|
+
write(name, num, options)
|
161
|
+
num
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
157
165
|
end
|
158
166
|
end
|
159
167
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ActiveSupport
|
2
|
+
module Cache
|
3
|
+
# A cache store implementation which doesn't actually store anything. Useful in
|
4
|
+
# development and test environments where you don't want caching turned on but
|
5
|
+
# need to go through the caching interface.
|
6
|
+
#
|
7
|
+
# This cache does implement the local cache strategy, so values will actually
|
8
|
+
# be cached inside blocks that utilize this strategy. See
|
9
|
+
# ActiveSupport::Cache::Strategy::LocalCache for more details.
|
10
|
+
class NullStore < Store
|
11
|
+
prepend Strategy::LocalCache
|
12
|
+
|
13
|
+
def clear(options = nil)
|
14
|
+
end
|
15
|
+
|
16
|
+
def cleanup(options = nil)
|
17
|
+
end
|
18
|
+
|
19
|
+
def increment(name, amount = 1, options = nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
def decrement(name, amount = 1, options = nil)
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete_matched(matcher, options = nil)
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
def read_entry(key, options) # :nodoc:
|
30
|
+
end
|
31
|
+
|
32
|
+
def write_entry(key, entry, options) # :nodoc:
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def delete_entry(key, options) # :nodoc:
|
37
|
+
false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,13 +1,36 @@
|
|
1
1
|
require 'active_support/core_ext/object/duplicable'
|
2
2
|
require 'active_support/core_ext/string/inflections'
|
3
|
+
require 'active_support/per_thread_registry'
|
3
4
|
|
4
5
|
module ActiveSupport
|
5
6
|
module Cache
|
6
7
|
module Strategy
|
7
|
-
# Caches that implement LocalCache will be backed by an in
|
8
|
+
# Caches that implement LocalCache will be backed by an in-memory cache for the
|
8
9
|
# duration of a block. Repeated calls to the cache for the same key will hit the
|
9
|
-
# in
|
10
|
+
# in-memory cache for faster access.
|
10
11
|
module LocalCache
|
12
|
+
autoload :Middleware, 'active_support/cache/strategy/local_cache_middleware'
|
13
|
+
|
14
|
+
# Class for storing and registering the local caches.
|
15
|
+
class LocalCacheRegistry # :nodoc:
|
16
|
+
extend ActiveSupport::PerThreadRegistry
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@registry = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def cache_for(local_cache_key)
|
23
|
+
@registry[local_cache_key]
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_cache_for(local_cache_key, value)
|
27
|
+
@registry[local_cache_key] = value
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.set_cache_for(l, v); instance.set_cache_for l, v; end
|
31
|
+
def self.cache_for(l); instance.cache_for l; end
|
32
|
+
end
|
33
|
+
|
11
34
|
# Simple memory backed cache. This cache is not thread safe and is intended only
|
12
35
|
# for serving as a temporary memory cache for a single thread.
|
13
36
|
class LocalStore < Store
|
@@ -16,7 +39,7 @@ module ActiveSupport
|
|
16
39
|
@data = {}
|
17
40
|
end
|
18
41
|
|
19
|
-
# Don't allow synchronizing since it isn't thread safe
|
42
|
+
# Don't allow synchronizing since it isn't thread safe.
|
20
43
|
def synchronize # :nodoc:
|
21
44
|
yield
|
22
45
|
end
|
@@ -37,99 +60,54 @@ module ActiveSupport
|
|
37
60
|
def delete_entry(key, options)
|
38
61
|
!!@data.delete(key)
|
39
62
|
end
|
40
|
-
end
|
41
63
|
|
42
|
-
|
43
|
-
|
44
|
-
save_val = Thread.current[thread_local_key]
|
45
|
-
begin
|
46
|
-
Thread.current[thread_local_key] = LocalStore.new
|
47
|
-
yield
|
48
|
-
ensure
|
49
|
-
Thread.current[thread_local_key] = save_val
|
64
|
+
def fetch_entry(key, options = nil) # :nodoc:
|
65
|
+
@data.fetch(key) { @data[key] = yield }
|
50
66
|
end
|
51
67
|
end
|
52
68
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
class Middleware # :nodoc:
|
57
|
-
attr_reader :name, :thread_local_key
|
58
|
-
|
59
|
-
def initialize(name, thread_local_key)
|
60
|
-
@name = name
|
61
|
-
@thread_local_key = thread_local_key
|
62
|
-
@app = nil
|
63
|
-
end
|
64
|
-
|
65
|
-
def new(app)
|
66
|
-
@app = app
|
67
|
-
self
|
68
|
-
end
|
69
|
-
|
70
|
-
def call(env)
|
71
|
-
Thread.current[thread_local_key] = LocalStore.new
|
72
|
-
@app.call(env)
|
73
|
-
ensure
|
74
|
-
Thread.current[thread_local_key] = nil
|
75
|
-
end
|
69
|
+
# Use a local cache for the duration of block.
|
70
|
+
def with_local_cache
|
71
|
+
use_temporary_local_cache(LocalStore.new) { yield }
|
76
72
|
end
|
77
|
-
|
78
73
|
# Middleware class can be inserted as a Rack handler to be local cache for the
|
79
74
|
# duration of request.
|
80
75
|
def middleware
|
81
76
|
@middleware ||= Middleware.new(
|
82
77
|
"ActiveSupport::Cache::Strategy::LocalCache",
|
83
|
-
|
78
|
+
local_cache_key)
|
84
79
|
end
|
85
80
|
|
86
81
|
def clear(options = nil) # :nodoc:
|
87
|
-
|
82
|
+
return super unless cache = local_cache
|
83
|
+
cache.clear(options)
|
88
84
|
super
|
89
85
|
end
|
90
86
|
|
91
87
|
def cleanup(options = nil) # :nodoc:
|
92
|
-
|
88
|
+
return super unless cache = local_cache
|
89
|
+
cache.clear(options)
|
93
90
|
super
|
94
91
|
end
|
95
92
|
|
96
93
|
def increment(name, amount = 1, options = nil) # :nodoc:
|
94
|
+
return super unless local_cache
|
97
95
|
value = bypass_local_cache{super}
|
98
|
-
|
99
|
-
local_cache.mute do
|
100
|
-
if value
|
101
|
-
local_cache.write(name, value, options)
|
102
|
-
else
|
103
|
-
local_cache.delete(name, options)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
96
|
+
write_cache_value(name, value, options)
|
107
97
|
value
|
108
98
|
end
|
109
99
|
|
110
100
|
def decrement(name, amount = 1, options = nil) # :nodoc:
|
101
|
+
return super unless local_cache
|
111
102
|
value = bypass_local_cache{super}
|
112
|
-
|
113
|
-
local_cache.mute do
|
114
|
-
if value
|
115
|
-
local_cache.write(name, value, options)
|
116
|
-
else
|
117
|
-
local_cache.delete(name, options)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
103
|
+
write_cache_value(name, value, options)
|
121
104
|
value
|
122
105
|
end
|
123
106
|
|
124
107
|
protected
|
125
108
|
def read_entry(key, options) # :nodoc:
|
126
|
-
if local_cache
|
127
|
-
|
128
|
-
unless entry
|
129
|
-
entry = super
|
130
|
-
local_cache.write_entry(key, entry, options)
|
131
|
-
end
|
132
|
-
entry
|
109
|
+
if cache = local_cache
|
110
|
+
cache.fetch_entry(key) { super }
|
133
111
|
else
|
134
112
|
super
|
135
113
|
end
|
@@ -145,22 +123,47 @@ module ActiveSupport
|
|
145
123
|
super
|
146
124
|
end
|
147
125
|
|
126
|
+
def set_cache_value(value, name, amount, options) # :nodoc:
|
127
|
+
ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
|
128
|
+
`set_cache_value` is deprecated and will be removed from Rails 5.1.
|
129
|
+
Please use `write_cache_value` instead.
|
130
|
+
MESSAGE
|
131
|
+
write_cache_value name, value, options
|
132
|
+
end
|
133
|
+
|
134
|
+
def write_cache_value(name, value, options) # :nodoc:
|
135
|
+
name = normalize_key(name, options)
|
136
|
+
cache = local_cache
|
137
|
+
cache.mute do
|
138
|
+
if value
|
139
|
+
cache.write(name, value, options)
|
140
|
+
else
|
141
|
+
cache.delete(name, options)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
148
146
|
private
|
149
|
-
|
150
|
-
|
147
|
+
|
148
|
+
def local_cache_key
|
149
|
+
@local_cache_key ||= "#{self.class.name.underscore}_local_cache_#{object_id}".gsub(/[\/-]/, '_').to_sym
|
151
150
|
end
|
152
151
|
|
153
152
|
def local_cache
|
154
|
-
|
153
|
+
LocalCacheRegistry.cache_for(local_cache_key)
|
155
154
|
end
|
156
155
|
|
157
156
|
def bypass_local_cache
|
158
|
-
|
157
|
+
use_temporary_local_cache(nil) { yield }
|
158
|
+
end
|
159
|
+
|
160
|
+
def use_temporary_local_cache(temporary_cache)
|
161
|
+
save_cache = LocalCacheRegistry.cache_for(local_cache_key)
|
159
162
|
begin
|
160
|
-
|
163
|
+
LocalCacheRegistry.set_cache_for(local_cache_key, temporary_cache)
|
161
164
|
yield
|
162
165
|
ensure
|
163
|
-
|
166
|
+
LocalCacheRegistry.set_cache_for(local_cache_key, save_cache)
|
164
167
|
end
|
165
168
|
end
|
166
169
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rack/body_proxy'
|
2
|
+
require 'rack/utils'
|
3
|
+
|
4
|
+
module ActiveSupport
|
5
|
+
module Cache
|
6
|
+
module Strategy
|
7
|
+
module LocalCache
|
8
|
+
|
9
|
+
#--
|
10
|
+
# This class wraps up local storage for middlewares. Only the middleware method should
|
11
|
+
# construct them.
|
12
|
+
class Middleware # :nodoc:
|
13
|
+
attr_reader :name, :local_cache_key
|
14
|
+
|
15
|
+
def initialize(name, local_cache_key)
|
16
|
+
@name = name
|
17
|
+
@local_cache_key = local_cache_key
|
18
|
+
@app = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def new(app)
|
22
|
+
@app = app
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def call(env)
|
27
|
+
LocalCacheRegistry.set_cache_for(local_cache_key, LocalStore.new)
|
28
|
+
response = @app.call(env)
|
29
|
+
response[2] = ::Rack::BodyProxy.new(response[2]) do
|
30
|
+
LocalCacheRegistry.set_cache_for(local_cache_key, nil)
|
31
|
+
end
|
32
|
+
response
|
33
|
+
rescue Rack::Utils::InvalidParameterError
|
34
|
+
LocalCacheRegistry.set_cache_for(local_cache_key, nil)
|
35
|
+
[400, {}, []]
|
36
|
+
rescue Exception
|
37
|
+
LocalCacheRegistry.set_cache_for(local_cache_key, nil)
|
38
|
+
raise
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|