Module: Valkey::Utils
- Included in:
- Valkey
- Defined in:
- lib/valkey/utils.rb
Overview
Valkey Utils module
This module provides utility functions for transforming and processing data structures commonly used in Valkey commands.
It includes methods for converting values to boolean, hash, or float, as well as methods for handling specific Valkey command responses.
Constant Summary collapse
- Boolify =
lambda { |value| return value if value.is_a?(TrueClass) || value.is_a?(FalseClass) value != 0 unless value.nil? }
- BoolifySet =
lambda { |value| case value when "OK" true when nil false else value end }
- Hashify =
lambda { |value| if value.is_a?(Hash) value elsif value.respond_to?(:each_slice) if value.first.is_a?(Array) value.to_h else value.each_slice(2).to_h end else value end }
- Pairify =
lambda { |value| if value.respond_to?(:each_slice) if value.first.is_a?(Array) value else value.each_slice(2).to_a end else value end }
- Floatify =
lambda { |value| case value when "inf" Float::INFINITY when "-inf" -Float::INFINITY when String Float(value) else value end }
- FloatifyPair =
lambda { |(first, score)| [first, Floatify.call(score)] }
- FloatifyPairs =
lambda { |value| return value unless value.respond_to?(:each_slice) if value.first.is_a?(Array) value.map(&FloatifyPair) else value.each_slice(2).map(&FloatifyPair) end }
- HashifyInfo =
lambda { |reply| lines = reply.split("\r\n").grep_v(/^(#|$)/) lines.map! { |line| line.split(':', 2) } lines.compact! lines.to_h }
- HashifyStreams =
lambda { |reply| case reply when nil {} else reply.transform_values { |entries| HashifyStreamEntries.call(entries) } end }
- HashifyStreamEntries =
lambda { |reply| return [] if reply.nil? return [] if !reply.is_a?(Array) || reply.empty? # Reply format: [[entry_id, [field1, value1, field2, value2, ...]], ...] # Match redis-rb: return flat arrays [["id", ["field", "value", ...]], ...] # Check if first element is a pair [entry_id, values_array] first_elem = reply.first if first_elem.is_a?(Array) && first_elem.length == 2 # Already in pair format: [[entry_id, [fields...]], ...] reply.compact.map do |entry_id, values| # Return flat array format like redis-rb, not hash values_array = if values.nil? [] elsif values.is_a?(Array) values else [] end [entry_id, values_array] end else # Flat array format: [entry_id1, [field1, value1, ...], entry_id2, [field2, value2, ...], ...] reply.compact.each_slice(2).map do |entry_id, values| # Return flat array format like redis-rb, not hash values_array = if values.nil? [] elsif values.is_a?(Array) values else [] end [entry_id, values_array] end end }
- HashifyStreamAutoclaim =
lambda { |reply| { 'next' => reply[0], 'entries' => if reply[1].nil? [] elsif reply[1].is_a?(Array) # Reply[1] is already an array of entries: [[id, [field, value, ...]], ...] # Use HashifyStreamEntries to convert them properly HashifyStreamEntries.call(reply[1]) else [] end } }
- HashifyStreamAutoclaimJustId =
lambda { |reply| { 'next' => reply[0], 'entries' => reply[1] } }
- HashifyStreamPendings =
lambda { |reply| { 'size' => reply[0], 'min_entry_id' => reply[1], 'max_entry_id' => reply[2], 'consumers' => reply[3].nil? ? {} : reply[3].to_h } }
- HashifyStreamPendingDetails =
lambda { |reply| reply.map do |arr| { 'entry_id' => arr[0], 'consumer' => arr[1], 'elapsed' => arr[2], 'count' => arr[3] } end }
- HashifyClusterNodeInfo =
lambda { |str| arr = str.split { 'node_id' => arr[0], 'ip_port' => arr[1], 'flags' => arr[2].split(','), 'master_node_id' => arr[3], 'ping_sent' => arr[4], 'pong_recv' => arr[5], 'config_epoch' => arr[6], 'link_state' => arr[7], 'slots' => arr[8].nil? ? nil : Range.new(*arr[8].split('-')) } }
- HashifyClusterSlots =
lambda { |reply| reply.map do |arr| first_slot, last_slot = arr[0..1] master = { 'ip' => arr[2][0], 'port' => arr[2][1], 'node_id' => arr[2][2] } replicas = arr[3..].map { |r| { 'ip' => r[0], 'port' => r[1], 'node_id' => r[2] } } { 'start_slot' => first_slot, 'end_slot' => last_slot, 'master' => master, 'replicas' => replicas } end }
- HashifyClusterNodes =
lambda { |reply| reply.split(/[\r\n]+/).map { |str| HashifyClusterNodeInfo.call(str) } }
- HashifyClusterSlaves =
lambda { |reply| reply.map { |str| HashifyClusterNodeInfo.call(str) } }
- Noop =
->(reply) { reply }
Class Method Summary collapse
-
.parse_redis_url(url) ⇒ Hash
Parse Redis URL format: redis://[:password@]host[/db] Also supports: rediss:// (SSL).
Class Method Details
.parse_redis_url(url) ⇒ Hash
Parse Redis URL format: redis://[:password@]host[/db] Also supports: rediss:// (SSL)
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/valkey/utils.rb', line 232 def self.parse_redis_url(url) return {} unless url.is_a?(String) && !url.empty? # Match redis:// or rediss:// URLs # Format: redis[s]://[username:password@]host[:port][/db][?param=value] # Supports: redis://host, redis://user:pass@host, redis://:pass@host # The regex handles: # - No auth: redis://host... # - Username and password: redis://user:pass@host... # - Password only: redis://:pass@host... match = url.match(%r{\A(redis|rediss)://(?:([^:@]*):([^@]+)@)?([^:/]+)(?::(\d+))?(?:/(\d+))?(?:\?.*)?\z}) return {} unless match scheme = match[1] username = match[2] password = match[3] host = match[4] port = match[5]&.to_i db = match[6]&.to_i ssl = scheme == "rediss" result = { host: host, port: port || 6379, ssl: ssl } result[:username] = username if username && !username.empty? result[:password] = password if password && !password.empty? result[:db] = db if db result end |