Class: Familia::StringKey

Inherits:
DataType show all
Defined in:
lib/familia/data_type/types/stringkey.rb

Direct Known Subclasses

Counter, Lock

Instance Attribute Summary collapse

Attributes included from Settings

#current_key_version, #default_expiration, #delim, #encryption_keys, #encryption_personalization, #logical_database, #prefix, #suffix, #transaction_mode

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Features::Autoloader

autoload_files, included, normalize_to_config_name

Methods included from DataType::Serialization

#deserialize_values, #deserialize_values_with_nil

Methods included from DataType::DatabaseCommands

#current_expiration, #delete!, #echo, #exists?, #expire, #expireat, #move, #persist, #rename, #renamenx, #type

Methods included from DataType::Connection

#dbclient, #dbkey, #direct_access, #uri

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, #ttl, #update_expiration, #uuid

Constructor Details

This class inherits a constructor from Familia::DataType

Instance Attribute Details

#features_enabledObject (readonly) Originally defined in module Features

Returns the value of attribute features_enabled.

#logical_database(val = nil) ⇒ Object Originally defined in module DataType::ClassMethods

#parentObject Originally defined in module DataType::ClassMethods

Returns the value of attribute parent.

#prefixObject Originally defined in module DataType::ClassMethods

Returns the value of attribute prefix.

#suffixObject 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.

Class Method Details

.bitop(operation, destkey, *keys, client: nil) ⇒ Integer

Perform bitwise operations between strings and store result

Examples:

StringKey.bitop(:and, 'result', 'key1', 'key2')

Parameters:

  • operation (String, Symbol)

    Bitwise operation: AND, OR, XOR, NOT

  • destkey (String)

    Destination key to store result

  • keys (Array<String>)

    Source keys for the operation

  • client (Redis, nil) (defaults to: nil)

    Optional Redis client (uses Familia.dbclient if nil)

Returns:

  • (Integer)

    Size of the resulting string in bytes



274
275
276
277
# File 'lib/familia/data_type/types/stringkey.rb', line 274

def bitop(operation, destkey, *keys, client: nil)
  client ||= Familia.dbclient
  client.bitop(operation.to_s.upcase, destkey, *keys)
end

.mget(*keys, client: nil) ⇒ Array

Get values for multiple keys

Examples:

StringKey.mget('user:1:name', 'user:2:name')

Parameters:

  • keys (Array<String>)

    Full Redis key names

  • client (Redis, nil) (defaults to: nil)

    Optional Redis client (uses Familia.dbclient if nil)

Returns:

  • (Array)

    Values for each key (nil for non-existent keys)



239
240
241
242
# File 'lib/familia/data_type/types/stringkey.rb', line 239

def mget(*keys, client: nil)
  client ||= Familia.dbclient
  client.mget(*keys)
end

.mset(hash, client: nil) ⇒ String

Set multiple keys atomically

Examples:

StringKey.mset('user:1:name' => 'Alice', 'user:2:name' => 'Bob')

Parameters:

  • hash (Hash)

    Key-value pairs to set

  • client (Redis, nil) (defaults to: nil)

    Optional Redis client (uses Familia.dbclient if nil)

Returns:

  • (String)

    "OK" on success



250
251
252
253
# File 'lib/familia/data_type/types/stringkey.rb', line 250

def mset(hash, client: nil)
  client ||= Familia.dbclient
  client.mset(*hash.flatten)
end

.msetnx(hash, client: nil) ⇒ Boolean

Set multiple keys only if none of them exist

Examples:

StringKey.msetnx('user:1:name' => 'Alice', 'user:2:name' => 'Bob')

Parameters:

  • hash (Hash)

    Key-value pairs to set

  • client (Redis, nil) (defaults to: nil)

    Optional Redis client (uses Familia.dbclient if nil)

Returns:

  • (Boolean)

    true if all keys were set, false if none were set



261
262
263
264
# File 'lib/familia/data_type/types/stringkey.rb', line 261

def msetnx(hash, client: nil)
  client ||= Familia.dbclient
  client.msetnx(*hash.flatten)
end

Instance Method Details

#append(val) ⇒ Object Also known as: <<



103
104
105
106
107
# File 'lib/familia/data_type/types/stringkey.rb', line 103

def append(val)
  ret = dbclient.append dbkey, val
  update_expiration
  ret
end

#bitcount(start_pos = nil, end_pos = nil) ⇒ Integer

Count the number of set bits (population counting)

Parameters:

  • start_pos (Integer, nil) (defaults to: nil)

    Start byte position (optional)

  • end_pos (Integer, nil) (defaults to: nil)

    End byte position (optional)

Returns:

  • (Integer)

    Number of bits set to 1



190
191
192
193
194
195
196
# File 'lib/familia/data_type/types/stringkey.rb', line 190

def bitcount(start_pos = nil, end_pos = nil)
  if start_pos && end_pos
    dbclient.bitcount(dbkey, start_pos, end_pos)
  else
    dbclient.bitcount(dbkey)
  end
end

#bitfield(*args) ⇒ Array

Perform bitfield operations on this string

Examples:

Get an unsigned 8-bit integer at offset 0

str.bitfield('GET', 'u8', 0)

Set and increment

str.bitfield('SET', 'u8', 0, 100, 'INCRBY', 'i5', 100, 1)

Parameters:

  • args (Array)

    Bitfield subcommands and arguments

Returns:

  • (Array)

    Results of the bitfield operations



220
221
222
223
224
# File 'lib/familia/data_type/types/stringkey.rb', line 220

def bitfield(*args)
  ret = dbclient.bitfield(dbkey, *args)
  update_expiration
  ret
end

#bitpos(bit, start_pos = nil, end_pos = nil) ⇒ Integer

Find the position of the first bit set to 0 or 1

Parameters:

  • bit (Integer)

    The bit value to search for (0 or 1)

  • start_pos (Integer, nil) (defaults to: nil)

    Start byte position (optional)

  • end_pos (Integer, nil) (defaults to: nil)

    End byte position (optional)

Returns:

  • (Integer)

    Position of the first bit, or -1 if not found



203
204
205
206
207
208
209
210
211
# File 'lib/familia/data_type/types/stringkey.rb', line 203

def bitpos(bit, start_pos = nil, end_pos = nil)
  if start_pos && end_pos
    dbclient.bitpos(dbkey, bit, start_pos, end_pos)
  elsif start_pos
    dbclient.bitpos(dbkey, bit, start_pos)
  else
    dbclient.bitpos(dbkey, bit)
  end
end

#char_countInteger Also known as: size, length

Returns the number of elements in the list

Returns:

  • (Integer)

    number of elements



33
34
35
# File 'lib/familia/data_type/types/stringkey.rb', line 33

def char_count
  to_s.size
end

#decrementObject Also known as: decr



89
90
91
92
93
# File 'lib/familia/data_type/types/stringkey.rb', line 89

def decrement
  ret = dbclient.decr dbkey
  update_expiration
  ret
end

#decrementby(val) ⇒ Object Also known as: decrby



96
97
98
99
100
# File 'lib/familia/data_type/types/stringkey.rb', line 96

def decrementby(val)
  ret = dbclient.decrby dbkey, val.to_i
  update_expiration
  ret
end

#delObject



226
227
228
229
# File 'lib/familia/data_type/types/stringkey.rb', line 226

def del
  ret = dbclient.del dbkey
  ret.positive?
end

#deserialize_value(val) ⇒ Object

StringKey returns raw values (not JSON parsed)



25
26
27
28
29
# File 'lib/familia/data_type/types/stringkey.rb', line 25

def deserialize_value(val)
  return val if val.is_a?(Redis::Future)
  return @opts[:default] if val.nil?
  val
end

#empty?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/familia/data_type/types/stringkey.rb', line 39

def empty?
  char_count.zero?
end

#getbit(offset) ⇒ Object



110
111
112
# File 'lib/familia/data_type/types/stringkey.rb', line 110

def getbit(offset)
  dbclient.getbit dbkey, offset
end

#getdelString?

Atomically get and delete the value

Returns:

  • (String, nil)

    The value before deletion, or nil if key didn't exist



138
139
140
# File 'lib/familia/data_type/types/stringkey.rb', line 138

def getdel
  dbclient.getdel(dbkey)
end

#getex(ex: nil, px: nil, exat: nil, pxat: nil, persist: false) ⇒ String?

Get value and optionally set expiration atomically

Parameters:

  • ex (Integer, nil) (defaults to: nil)

    Set expiration in seconds

  • px (Integer, nil) (defaults to: nil)

    Set expiration in milliseconds

  • exat (Integer, nil) (defaults to: nil)

    Set expiration at Unix timestamp (seconds)

  • pxat (Integer, nil) (defaults to: nil)

    Set expiration at Unix timestamp (milliseconds)

  • persist (Boolean) (defaults to: false)

    Remove existing expiration

Returns:

  • (String, nil)

    The value



149
150
151
152
153
154
155
156
157
158
# File 'lib/familia/data_type/types/stringkey.rb', line 149

def getex(ex: nil, px: nil, exat: nil, pxat: nil, persist: false)
  options = {}
  options[:ex] = ex if ex
  options[:px] = px if px
  options[:exat] = exat if exat
  options[:pxat] = pxat if pxat
  options[:persist] = persist if persist

  dbclient.getex(dbkey, **options)
end

#getrange(spoint, epoint) ⇒ Object



120
121
122
# File 'lib/familia/data_type/types/stringkey.rb', line 120

def getrange(spoint, epoint)
  dbclient.getrange dbkey, spoint, epoint
end

#getset(val) ⇒ Object



130
131
132
133
134
# File 'lib/familia/data_type/types/stringkey.rb', line 130

def getset(val)
  ret = dbclient.getset dbkey, val
  update_expiration
  ret
end

#incrbyfloat(val) ⇒ Float Also known as: incrfloat

Increment value by a float amount

Parameters:

  • val (Float, Numeric)

    The amount to increment by

Returns:

  • (Float)

    The new value after increment



163
164
165
166
167
# File 'lib/familia/data_type/types/stringkey.rb', line 163

def incrbyfloat(val)
  ret = dbclient.incrbyfloat(dbkey, val.to_f)
  update_expiration
  ret
end

#incrementObject Also known as: incr



75
76
77
78
79
# File 'lib/familia/data_type/types/stringkey.rb', line 75

def increment
  ret = dbclient.incr(dbkey)
  update_expiration
  ret
end

#incrementby(val) ⇒ Object Also known as: incrby



82
83
84
85
86
# File 'lib/familia/data_type/types/stringkey.rb', line 82

def incrementby(val)
  ret = dbclient.incrby(dbkey, val.to_i)
  update_expiration
  ret
end

#initObject



7
# File 'lib/familia/data_type/types/stringkey.rb', line 7

def init; end

#psetex(milliseconds, val) ⇒ String

Set value with expiration in milliseconds

Parameters:

  • milliseconds (Integer)

    Expiration time in milliseconds

  • val (Object)

    The value to set

Returns:

  • (String)

    "OK" on success



182
183
184
# File 'lib/familia/data_type/types/stringkey.rb', line 182

def psetex(milliseconds, val)
  dbclient.psetex(dbkey, milliseconds.to_i, serialize_value(val))
end

#serialize_value(val) ⇒ Object

StringKey uses raw string serialization (not JSON) because Redis string operations like INCR, DECR, APPEND operate on raw values. This overrides the base JSON serialization from DataType.



12
13
14
15
16
17
18
19
20
21
22
# File 'lib/familia/data_type/types/stringkey.rb', line 12

def serialize_value(val)
  Familia.trace :TOREDIS, nil, "#{val}<#{val.class}>" if Familia.debug?

  # Handle Familia object references - extract identifier
  if val.is_a?(Familia::Base) || (val.is_a?(Class) && val.ancestors.include?(Familia::Base))
    return val.is_a?(Class) ? val.name : val.identifier
  end

  # StringKey uses raw string conversion for Redis compatibility
  val.to_s
end

#setbit(offset, val) ⇒ Object



114
115
116
117
118
# File 'lib/familia/data_type/types/stringkey.rb', line 114

def setbit(offset, val)
  ret = dbclient.setbit dbkey, offset, val
  update_expiration
  ret
end

#setex(seconds, val) ⇒ String

Set value with expiration in seconds

Parameters:

  • seconds (Integer)

    Expiration time in seconds

  • val (Object)

    The value to set

Returns:

  • (String)

    "OK" on success



174
175
176
# File 'lib/familia/data_type/types/stringkey.rb', line 174

def setex(seconds, val)
  dbclient.setex(dbkey, seconds.to_i, serialize_value(val))
end

#setnx(val) ⇒ Object



69
70
71
72
73
# File 'lib/familia/data_type/types/stringkey.rb', line 69

def setnx(val)
  ret = dbclient.setnx(dbkey, serialize_value(val))
  update_expiration
  ret
end

#setrange(offset, val) ⇒ Object



124
125
126
127
128
# File 'lib/familia/data_type/types/stringkey.rb', line 124

def setrange(offset, val)
  ret = dbclient.setrange dbkey, offset, val
  update_expiration
  ret
end

#to_iObject



57
58
59
# File 'lib/familia/data_type/types/stringkey.rb', line 57

def to_i
  value.to_i
end

#to_sObject



51
52
53
54
55
# File 'lib/familia/data_type/types/stringkey.rb', line 51

def to_s
  return super if value.to_s.empty?

  value.to_s
end

#valueObject Also known as: content, get



43
44
45
46
47
# File 'lib/familia/data_type/types/stringkey.rb', line 43

def value
  echo :value, Familia.pretty_stack(limit: 1) if Familia.debug
  dbclient.setnx dbkey, @opts[:default] if @opts[:default]
  deserialize_value dbclient.get(dbkey)
end

#value=(val) ⇒ Object Also known as: replace, set



61
62
63
64
65
# File 'lib/familia/data_type/types/stringkey.rb', line 61

def value=(val)
  ret = dbclient.set(dbkey, serialize_value(val))
  update_expiration
  ret
end