Class: Dalli::KeyManager
- Inherits:
-
Object
- Object
- Dalli::KeyManager
- Defined in:
- lib/dalli/key_manager.rb
Overview
This class manages and validates keys sent to Memcached, ensuring that they meet Memcached key length requirements, and supporting the implementation of optional namespaces on a per-Dalli client basis.
Constant Summary collapse
- MAX_KEY_LENGTH =
250
- NAMESPACE_SEPARATOR =
':'
- TRUNCATED_KEY_SEPARATOR =
This is a hard coded md5 for historical reasons
':md5:'
- TRUNCATED_KEY_TARGET_SIZE =
This is 249 for historical reasons
249
- DEFAULTS =
{ digest_class: ::Digest::MD5 }.freeze
- OPTIONS =
%i[digest_class namespace].freeze
Instance Attribute Summary collapse
-
#namespace ⇒ Object
readonly
Returns the value of attribute namespace.
Instance Method Summary collapse
- #digest_class ⇒ Object
-
#initialize(client_options) ⇒ KeyManager
constructor
A new instance of KeyManager.
-
#key_with_namespace(key) ⇒ Object
Returns the key with the namespace prefixed, if a namespace is defined.
- #key_without_namespace(key) ⇒ Object
- #namespace_from_options ⇒ Object
- #namespace_regexp ⇒ Object
- #prefix_length(digest) ⇒ Object
-
#truncated_key(key) ⇒ Object
Produces a truncated key, if the raw key is longer than the maximum allowed length.
- #validate_digest_class_option(opts) ⇒ Object
-
#validate_key(key) ⇒ Object
Validates the key, and transforms as needed.
Constructor Details
#initialize(client_options) ⇒ KeyManager
Returns a new instance of KeyManager.
31 32 33 34 35 36 37 |
# File 'lib/dalli/key_manager.rb', line 31 def initialize() @key_options = DEFAULTS.merge(.select { |k, _| OPTIONS.include?(k) }) validate_digest_class_option(@key_options) @namespace = end |
Instance Attribute Details
#namespace ⇒ Object (readonly)
Returns the value of attribute namespace.
29 30 31 |
# File 'lib/dalli/key_manager.rb', line 29 def namespace @namespace end |
Instance Method Details
#digest_class ⇒ Object
73 74 75 |
# File 'lib/dalli/key_manager.rb', line 73 def digest_class @digest_class ||= @key_options[:digest_class] end |
#key_with_namespace(key) ⇒ Object
Returns the key with the namespace prefixed, if a namespace is defined. Otherwise just returns the key
61 62 63 64 65 |
# File 'lib/dalli/key_manager.rb', line 61 def key_with_namespace(key) return key if namespace.nil? "#{namespace}#{NAMESPACE_SEPARATOR}#{key}" end |
#key_without_namespace(key) ⇒ Object
67 68 69 70 71 |
# File 'lib/dalli/key_manager.rb', line 67 def key_without_namespace(key) return key if namespace.nil? key.sub(namespace_regexp, '') end |
#namespace_from_options ⇒ Object
87 88 89 90 91 92 93 |
# File 'lib/dalli/key_manager.rb', line 87 def raw_namespace = @key_options[:namespace] return nil unless raw_namespace return raw_namespace.call.to_s if raw_namespace.is_a?(Proc) raw_namespace.to_s end |
#namespace_regexp ⇒ Object
77 78 79 |
# File 'lib/dalli/key_manager.rb', line 77 def namespace_regexp @namespace_regexp ||= /\A#{Regexp.escape(namespace)}:/.freeze unless namespace.nil? end |
#prefix_length(digest) ⇒ Object
105 106 107 108 109 110 111 |
# File 'lib/dalli/key_manager.rb', line 105 def prefix_length(digest) return TRUNCATED_KEY_TARGET_SIZE - (TRUNCATED_KEY_SEPARATOR.length + digest.length) if namespace.nil? # For historical reasons, truncated keys with namespaces had a length of 250 rather # than 249 TRUNCATED_KEY_TARGET_SIZE + 1 - (TRUNCATED_KEY_SEPARATOR.length + digest.length) end |
#truncated_key(key) ⇒ Object
Produces a truncated key, if the raw key is longer than the maximum allowed length. The truncated key is produced by generating a hex digest of the key, and appending that to a truncated section of the key.
100 101 102 103 |
# File 'lib/dalli/key_manager.rb', line 100 def truncated_key(key) digest = digest_class.hexdigest(key) "#{key[0, prefix_length(digest)]}#{TRUNCATED_KEY_SEPARATOR}#{digest}" end |
#validate_digest_class_option(opts) ⇒ Object
81 82 83 84 85 |
# File 'lib/dalli/key_manager.rb', line 81 def validate_digest_class_option(opts) return if opts[:digest_class].respond_to?(:hexdigest) raise ArgumentError, 'The digest_class object must respond to the hexdigest method' end |
#validate_key(key) ⇒ Object
Validates the key, and transforms as needed.
If the key is nil or empty, raises ArgumentError. Whitespace characters are allowed for historical reasons, but likely shouldn’t be used. If the key (with namespace) is shorter than the memcached maximum allowed key length, just returns the argument key Otherwise computes a “truncated” key that uses a truncated prefix combined with a 32-byte hex digest of the whole key.
50 51 52 53 54 55 |
# File 'lib/dalli/key_manager.rb', line 50 def validate_key(key) raise ArgumentError, 'key cannot be blank' unless key&.length&.positive? key = key_with_namespace(key) key.length > MAX_KEY_LENGTH ? truncated_key(key) : key end |