class Dalli::KeyManager
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.
Constants
- DEFAULTS
- MAX_KEY_LENGTH
- NAMESPACE_SEPARATOR
- OPTIONS
- TRUNCATED_KEY_SEPARATOR
This is a hard coded md5 for historical reasons
- TRUNCATED_KEY_TARGET_SIZE
This is 249 for historical reasons
Attributes
Public Class Methods
# File lib/dalli/key_manager.rb, line 31 def initialize(client_options) @key_options = DEFAULTS.merge(client_options.select { |k, _| OPTIONS.include?(k) }) validate_digest_class_option(@key_options) @namespace = namespace_from_options end
Public Instance Methods
# File lib/dalli/key_manager.rb, line 73 def digest_class @digest_class ||= @key_options[:digest_class] end
Returns the key with the namespace prefixed, if a namespace is defined. Otherwise just returns the key
# File lib/dalli/key_manager.rb, line 61 def key_with_namespace(key) return key if namespace.nil? "#{namespace}#{NAMESPACE_SEPARATOR}#{key}" end
# File lib/dalli/key_manager.rb, line 67 def key_without_namespace(key) return key if namespace.nil? key.sub(namespace_regexp, '') end
# File lib/dalli/key_manager.rb, line 87 def namespace_from_options 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
# File lib/dalli/key_manager.rb, line 77 def namespace_regexp @namespace_regexp ||= /\A#{Regexp.escape(namespace)}:/.freeze unless namespace.nil? end
# 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
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.
# 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
# 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
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.
# 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