Class: Familia::HashKey
- Includes:
- DataType::CollectionBase
- Defined in:
- lib/familia/data_type/types/hashkey.rb
Instance Attribute Summary collapse
-
#features_enabled ⇒ Object
included
from Features
readonly
Returns the value of attribute features_enabled.
- #logical_database(val = nil) ⇒ Object included from DataType::ClassMethods
-
#parent ⇒ Object
included
from DataType::ClassMethods
Returns the value of attribute parent.
-
#prefix ⇒ Object
included
from DataType::ClassMethods
Returns the value of attribute prefix.
-
#suffix ⇒ Object
included
from DataType::ClassMethods
Returns the value of attribute suffix.
-
#uri(val = nil) ⇒ Object
included
from DataType::ClassMethods
Returns the value of attribute uri.
Attributes included from Settings
#current_key_version, #default_expiration, #delim, #encryption_keys, #encryption_personalization, #logical_database, #prefix, #schema_path, #schema_validator, #schemas, #strict_write_order, #suffix, #transaction_mode
Instance Method Summary collapse
- #[](field) ⇒ Object (also: #get)
-
#[]=(field, val) ⇒ Object
(also: #put, #store, #add)
+return+ [Integer] Returns 1 if the field is new and added, 0 if the field already existed and the value was updated.
- #decrement(field, by = 1) ⇒ Object (also: #decr, #decrby)
-
#each(matching: nil, batch_size: 100) {|field, value| ... } ⇒ Enumerator, self
Iterates over field-value pairs in the hash.
- #empty? ⇒ Boolean
-
#expire_fields(seconds, *fields) ⇒ Array<Integer>
(also: #hexpire)
Sets expiration time in seconds on one or more hash fields.
-
#expireat_fields(unix_time, *fields) ⇒ Array<Integer>
(also: #hexpireat)
Sets absolute expiration time (Unix timestamp in seconds) on hash fields.
-
#expiretime_fields(*fields) ⇒ Array<Integer>
(also: #hexpiretime)
Returns the absolute Unix expiration timestamp in seconds for hash fields.
- #fetch(field, default = nil) ⇒ Object
-
#field_count ⇒ Integer
(also: #size, #length, #count)
Returns the number of fields in the hash.
- #hgetall ⇒ Object (also: #all)
-
#hsetnx(field, val) ⇒ Integer
Sets field in the hash stored at key to value, only if field does not yet exist.
-
#incrbyfloat(field, by) ⇒ Float
(also: #incrfloat)
Increments the float value of a hash field by the given amount.
- #increment(field, by = 1) ⇒ Object (also: #incr, #incrby)
- #key?(field) ⇒ Boolean (also: #has_key?, #include?, #member?)
- #keys ⇒ Object
-
#persist_fields(*fields) ⇒ Array<Integer>
(also: #hpersist)
Removes expiration from one or more hash fields.
-
#pexpire_fields(milliseconds, *fields) ⇒ Array<Integer>
(also: #hpexpire)
Sets expiration time in milliseconds on one or more hash fields.
-
#pexpireat_fields(unix_time_ms, *fields) ⇒ Array<Integer>
(also: #hpexpireat)
Sets absolute expiration time (Unix timestamp in milliseconds) on hash fields.
-
#pexpiretime_fields(*fields) ⇒ Array<Integer>
(also: #hpexpiretime)
Returns the absolute Unix expiration timestamp in milliseconds for hash fields.
-
#pttl_fields(*fields) ⇒ Array<Integer>
(also: #hpttl)
Returns the remaining TTL in milliseconds for one or more hash fields.
-
#randfield(count = nil, withvalues: false) ⇒ String, ...
(also: #hrandfield)
Returns one or more random fields from the hash.
-
#refresh ⇒ self
The friendly neighborhood refresh method!.
-
#refresh! ⇒ void
The Great Database Refresh-o-matic 3000 for HashKey!.
-
#remove_field(field) ⇒ Integer
(also: #remove, #remove_element)
Removes a field from the hash.
-
#scan(cursor = 0, match: nil, count: nil) ⇒ Array<Integer, Hash>
(also: #hscan)
Incrementally iterates over fields in the hash using cursor-based iteration.
-
#strlen(field) ⇒ Integer
(also: #hstrlen)
Returns the string length of the value associated with field.
-
#ttl_fields(*fields) ⇒ Array<Integer>
(also: #httl)
Returns the remaining TTL in seconds for one or more hash fields.
- #update(hsh = {}) ⇒ Object (also: #merge!)
- #values ⇒ Object
- #values_at(*fields) ⇒ Object
Methods included from DataType::CollectionBase
#collection_type?, #each_record
Methods included from Features::Autoloader
autoload_files, included, normalize_to_config_name
Methods included from DataType::Serialization
#deserialize_value, #deserialize_values, #deserialize_values_with_nil, #serialize_value
Methods included from DataType::DatabaseCommands
#current_expiration, #delete!, #echo, #exists?, #expire, #expireat, #move, #persist, #rename, #renamenx, #type
Methods included from DataType::Connection
Methods included from Connection::Behavior
#connect, #create_dbclient, #multi, #normalize_uri, #pipeline, #pipelined, #transaction, #uri=, #url, #url=
Methods included from Settings
#configure, #default_suffix, #pipelined_mode, #pipelined_mode=
Methods included from Base
add_feature, #as_json, #expired?, #expires?, find_feature, #generate_id, #to_json, #to_s, #ttl, #update_expiration, #uuid
Constructor Details
This class inherits a constructor from Familia::DataType
Instance Attribute Details
#features_enabled ⇒ Object (readonly) Originally defined in module Features
Returns the value of attribute features_enabled.
#logical_database(val = nil) ⇒ Object Originally defined in module DataType::ClassMethods
#parent ⇒ Object Originally defined in module DataType::ClassMethods
Returns the value of attribute parent.
#prefix ⇒ Object Originally defined in module DataType::ClassMethods
Returns the value of attribute prefix.
#suffix ⇒ Object Originally defined in module DataType::ClassMethods
Returns the value of attribute suffix.
#uri(val = nil) ⇒ Object Originally defined in module DataType::ClassMethods
Returns the value of attribute uri.
Instance Method Details
#[](field) ⇒ Object Also known as: get
45 46 47 |
# File 'lib/familia/data_type/types/hashkey.rb', line 45 def [](field) deserialize_value dbclient.hget(dbkey, field.to_s) end |
#[]=(field, val) ⇒ Object Also known as: put, store, add
This method executes a Redis HSET immediately, unlike scalar field setters which are deferred until save. If the parent object has unsaved scalar field changes, consider calling save first to avoid split-brain state.
+return+ [Integer] Returns 1 if the field is new and added, 0 if the field already existed and the value was updated.
28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/familia/data_type/types/hashkey.rb', line 28 def []=(field, val) warn_if_dirty! ret = dbclient.hset dbkey, field.to_s, serialize_value(val) update_expiration ret rescue TypeError => e Familia.error "[hset]= #{e.}" Familia.debug "[hset]= #{dbkey} #{field}=#{val}" echo :hset, Familia.pretty_stack(limit: 1) if Familia.debug # logs via echo to the db and back klass = val.class msg = "Cannot store #{field} => #{val.inspect} (#{klass}) in #{dbkey}" raise e.class, msg end |
#decrement(field, by = 1) ⇒ Object Also known as: decr, decrby
122 123 124 |
# File 'lib/familia/data_type/types/hashkey.rb', line 122 def decrement(field, by = 1) increment field, -by end |
#each(matching: nil, batch_size: 100) {|field, value| ... } ⇒ Enumerator, self
Pattern matches field names only (plain strings). To filter on values, use Enumerable#select instead.
Iterates over field-value pairs in the hash.
Uses HSCAN for memory-efficient iteration. Optionally filters by field name pattern using Redis MATCH.
167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/familia/data_type/types/hashkey.rb', line 167 def each(matching: nil, batch_size: 100, &block) return to_enum(:each, matching: matching, batch_size: batch_size) unless block cursor = 0 loop do new_cursor, pairs = scan(cursor, match: matching, count: batch_size) pairs.each(&block) cursor = new_cursor break if cursor.zero? end self end |
#empty? ⇒ Boolean
18 19 20 |
# File 'lib/familia/data_type/types/hashkey.rb', line 18 def empty? field_count.zero? end |
#expire_fields(seconds, *fields) ⇒ Array<Integer> Also known as: hexpire
Requires Redis 7.4+
Sets expiration time in seconds on one or more hash fields.
293 294 295 |
# File 'lib/familia/data_type/types/hashkey.rb', line 293 def expire_fields(seconds, *fields) call_hash_field_command('HEXPIRE', seconds, fields: fields) end |
#expireat_fields(unix_time, *fields) ⇒ Array<Integer> Also known as: hexpireat
Requires Redis 7.4+
Sets absolute expiration time (Unix timestamp in seconds) on hash fields.
322 323 324 |
# File 'lib/familia/data_type/types/hashkey.rb', line 322 def expireat_fields(unix_time, *fields) call_hash_field_command('HEXPIREAT', unix_time, fields: fields) end |
#expiretime_fields(*fields) ⇒ Array<Integer> Also known as: hexpiretime
Requires Redis 7.4+
Returns the absolute Unix expiration timestamp in seconds for hash fields.
394 395 396 |
# File 'lib/familia/data_type/types/hashkey.rb', line 394 def expiretime_fields(*fields) call_hash_field_command('HEXPIRETIME', fields: fields) end |
#fetch(field, default = nil) ⇒ Object
50 51 52 53 54 55 56 57 58 59 |
# File 'lib/familia/data_type/types/hashkey.rb', line 50 def fetch(field, default = nil) ret = self[field.to_s] if ret.nil? raise IndexError, "No such index for: #{field}" if default.nil? default else ret end end |
#field_count ⇒ Integer Also known as: size, length, count
Returns the number of fields in the hash
11 12 13 |
# File 'lib/familia/data_type/types/hashkey.rb', line 11 def field_count dbclient.hlen dbkey end |
#hgetall ⇒ Object Also known as: all
69 70 71 72 73 |
# File 'lib/familia/data_type/types/hashkey.rb', line 69 def hgetall dbclient.hgetall(dbkey).transform_values do |v| deserialize_value v end end |
#hsetnx(field, val) ⇒ Integer
Sets field in the hash stored at key to value, only if field does not yet exist. If field already exists, this operation has no effect.
81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/familia/data_type/types/hashkey.rb', line 81 def hsetnx(field, val) warn_if_dirty! ret = dbclient.hsetnx dbkey, field.to_s, serialize_value(val) update_expiration if ret == 1 ret rescue TypeError => e Familia.error "[hsetnx] #{e.}" Familia.debug "[hsetnx] #{dbkey} #{field}=#{val}" echo :hsetnx, Familia.pretty_stack(limit: 1) if Familia.debug # logs via echo to the db and back klass = val.class msg = "Cannot store #{field} => #{val.inspect} (#{klass}) in #{dbkey}" raise e.class, msg end |
#incrbyfloat(field, by) ⇒ Float Also known as: incrfloat
Increments the float value of a hash field by the given amount.
223 224 225 226 227 |
# File 'lib/familia/data_type/types/hashkey.rb', line 223 def incrbyfloat(field, by) ret = dbclient.hincrbyfloat(dbkey, field.to_s, by).to_f update_expiration ret end |
#increment(field, by = 1) ⇒ Object Also known as: incr, incrby
114 115 116 117 118 |
# File 'lib/familia/data_type/types/hashkey.rb', line 114 def increment(field, by = 1) ret = dbclient.hincrby(dbkey, field.to_s, by).to_i update_expiration ret end |
#key?(field) ⇒ Boolean Also known as: has_key?, include?, member?
95 96 97 |
# File 'lib/familia/data_type/types/hashkey.rb', line 95 def key?(field) dbclient.hexists dbkey, field.to_s end |
#keys ⇒ Object
61 62 63 |
# File 'lib/familia/data_type/types/hashkey.rb', line 61 def keys dbclient.hkeys dbkey end |
#persist_fields(*fields) ⇒ Array<Integer> Also known as: hpersist
Requires Redis 7.4+
Removes expiration from one or more hash fields.
379 380 381 |
# File 'lib/familia/data_type/types/hashkey.rb', line 379 def persist_fields(*fields) call_hash_field_command('HPERSIST', fields: fields) end |
#pexpire_fields(milliseconds, *fields) ⇒ Array<Integer> Also known as: hpexpire
Requires Redis 7.4+
Sets expiration time in milliseconds on one or more hash fields.
307 308 309 |
# File 'lib/familia/data_type/types/hashkey.rb', line 307 def pexpire_fields(milliseconds, *fields) call_hash_field_command('HPEXPIRE', milliseconds, fields: fields) end |
#pexpireat_fields(unix_time_ms, *fields) ⇒ Array<Integer> Also known as: hpexpireat
Requires Redis 7.4+
Sets absolute expiration time (Unix timestamp in milliseconds) on hash fields.
336 337 338 |
# File 'lib/familia/data_type/types/hashkey.rb', line 336 def pexpireat_fields(unix_time_ms, *fields) call_hash_field_command('HPEXPIREAT', unix_time_ms, fields: fields) end |
#pexpiretime_fields(*fields) ⇒ Array<Integer> Also known as: hpexpiretime
Requires Redis 7.4+
Returns the absolute Unix expiration timestamp in milliseconds for hash fields.
407 408 409 |
# File 'lib/familia/data_type/types/hashkey.rb', line 407 def pexpiretime_fields(*fields) call_hash_field_command('HPEXPIRETIME', fields: fields) end |
#pttl_fields(*fields) ⇒ Array<Integer> Also known as: hpttl
Requires Redis 7.4+
Returns the remaining TTL in milliseconds for one or more hash fields.
364 365 366 |
# File 'lib/familia/data_type/types/hashkey.rb', line 364 def pttl_fields(*fields) call_hash_field_command('HPTTL', fields: fields) end |
#randfield(count = nil, withvalues: false) ⇒ String, ... Also known as: hrandfield
Returns one or more random fields from the hash.
261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'lib/familia/data_type/types/hashkey.rb', line 261 def randfield(count = nil, withvalues: false) if count.nil? dbclient.hrandfield(dbkey) elsif withvalues pairs = dbclient.hrandfield(dbkey, count, withvalues: true) # pairs is array of [field, value, field, value, ...] # Convert to array of [field, deserialized_value] pairs pairs.each_slice(2).map { |field, val| [field, deserialize_value(val)] } else dbclient.hrandfield(dbkey, count) end end |
#refresh ⇒ self
The friendly neighborhood refresh method!
This method is like refresh! but with better manners - it returns self so you can chain it with other methods. It's perfect for when you want to refresh your hash and immediately do something with it.
479 480 481 482 |
# File 'lib/familia/data_type/types/hashkey.rb', line 479 def refresh refresh! self end |
#refresh! ⇒ void
This operation is atomic - it either succeeds completely or fails safely. Any unsaved changes to the hash will be overwritten.
This method returns an undefined value.
The Great Database Refresh-o-matic 3000 for HashKey!
This method performs a complete refresh of the hash's state from the database. It's like giving your hash a memory transfusion - out with the old state, in with the fresh data straight from Valkey/Redis!
452 453 454 455 456 457 458 459 460 461 |
# File 'lib/familia/data_type/types/hashkey.rb', line 452 def refresh! Familia.trace :REFRESH, nil, self.class.uri if Familia.debug? raise Familia::KeyNotFoundError, dbkey unless dbclient.exists(dbkey) fields = hgetall Familia.debug "[refresh!] #{self.class} #{dbkey} #{fields.keys}" # For HashKey, we update by merging the fresh data update(fields) end |
#remove_field(field) ⇒ Integer Also known as: remove, remove_element
Removes a field from the hash
105 106 107 108 109 110 |
# File 'lib/familia/data_type/types/hashkey.rb', line 105 def remove_field(field) warn_if_dirty! ret = dbclient.hdel dbkey, field.to_s update_expiration ret end |
#scan(cursor = 0, match: nil, count: nil) ⇒ Array<Integer, Hash> Also known as: hscan
Incrementally iterates over fields in the hash using cursor-based iteration.
This is more memory-efficient than hgetall for large hashes.
200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/familia/data_type/types/hashkey.rb', line 200 def scan(cursor = 0, match: nil, count: nil) opts = {} opts[:match] = match if match opts[:count] = count if count new_cursor, pairs = dbclient.hscan(dbkey, cursor, **opts) # pairs is an array of [field, value] pairs, convert to hash with deserialization result_hash = pairs.to_h.transform_values { |v| deserialize_value(v) } [new_cursor.to_i, result_hash] end |
#strlen(field) ⇒ Integer Also known as: hstrlen
Returns the string length of the value associated with field.
238 239 240 |
# File 'lib/familia/data_type/types/hashkey.rb', line 238 def strlen(field) dbclient.hstrlen(dbkey, field.to_s) end |
#ttl_fields(*fields) ⇒ Array<Integer> Also known as: httl
Requires Redis 7.4+
Returns the remaining TTL in seconds for one or more hash fields.
351 352 353 |
# File 'lib/familia/data_type/types/hashkey.rb', line 351 def ttl_fields(*fields) call_hash_field_command('HTTL', fields: fields) end |
#update(hsh = {}) ⇒ Object Also known as: merge!
128 129 130 131 132 133 134 135 136 137 |
# File 'lib/familia/data_type/types/hashkey.rb', line 128 def update(hsh = {}) warn_if_dirty! raise ArgumentError, 'Argument to bulk_set must be a hash' unless hsh.is_a?(Hash) data = hsh.inject([]) { |ret, pair| ret << [pair[0], serialize_value(pair[1])] }.flatten ret = dbclient.hmset(dbkey, *data) update_expiration ret end |
#values ⇒ Object
65 66 67 |
# File 'lib/familia/data_type/types/hashkey.rb', line 65 def values dbclient.hvals(dbkey).map { |v| deserialize_value v } end |
#values_at(*fields) ⇒ Object
140 141 142 143 144 |
# File 'lib/familia/data_type/types/hashkey.rb', line 140 def values_at *fields string_fields = fields.flatten.compact.map(&:to_s) elements = dbclient.hmget(dbkey, *string_fields) deserialize_values(*elements) end |