familia 1.2.1 → 2.0.0.pre.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +68 -0
  3. data/.github/workflows/docs.yml +64 -0
  4. data/.gitignore +4 -0
  5. data/.pre-commit-config.yaml +3 -1
  6. data/.rubocop.yml +16 -9
  7. data/.rubocop_todo.yml +177 -31
  8. data/.yardopts +9 -0
  9. data/CLAUDE.md +141 -0
  10. data/Gemfile +15 -2
  11. data/Gemfile.lock +76 -34
  12. data/README.md +39 -23
  13. data/bin/irb +3 -0
  14. data/docs/connection_pooling.md +317 -0
  15. data/familia.gemspec +9 -5
  16. data/lib/familia/base.rb +19 -9
  17. data/lib/familia/connection.rb +232 -65
  18. data/lib/familia/core_ext.rb +1 -1
  19. data/lib/familia/datatype/commands.rb +59 -0
  20. data/lib/familia/{redistype → datatype}/serialization.rb +9 -13
  21. data/lib/familia/{redistype → datatype}/types/hashkey.rb +25 -25
  22. data/lib/familia/{redistype → datatype}/types/list.rb +13 -13
  23. data/lib/familia/{redistype → datatype}/types/sorted_set.rb +20 -20
  24. data/lib/familia/{redistype → datatype}/types/string.rb +22 -21
  25. data/lib/familia/{redistype → datatype}/types/unsorted_set.rb +11 -11
  26. data/lib/familia/datatype.rb +243 -0
  27. data/lib/familia/errors.rb +5 -2
  28. data/lib/familia/features/expiration.rb +33 -34
  29. data/lib/familia/features/quantization.rb +9 -3
  30. data/lib/familia/features/safe_dump.rb +2 -3
  31. data/lib/familia/features.rb +2 -2
  32. data/lib/familia/horreum/class_methods.rb +97 -110
  33. data/lib/familia/horreum/commands.rb +46 -51
  34. data/lib/familia/horreum/connection.rb +82 -0
  35. data/lib/familia/horreum/{relations_management.rb → related_fields_management.rb} +37 -35
  36. data/lib/familia/horreum/serialization.rb +61 -198
  37. data/lib/familia/horreum/settings.rb +6 -17
  38. data/lib/familia/horreum/utils.rb +11 -10
  39. data/lib/familia/horreum.rb +69 -60
  40. data/lib/familia/logging.rb +12 -12
  41. data/lib/familia/multi_result.rb +72 -0
  42. data/lib/familia/refinements.rb +7 -44
  43. data/lib/familia/settings.rb +11 -11
  44. data/lib/familia/utils.rb +123 -90
  45. data/lib/familia/version.rb +4 -21
  46. data/lib/familia.rb +17 -12
  47. data/lib/middleware/database_middleware.rb +150 -0
  48. data/try/configuration/scenarios_try.rb +65 -0
  49. data/try/core/connection_try.rb +58 -0
  50. data/try/core/errors_try.rb +93 -0
  51. data/try/core/extensions_try.rb +26 -0
  52. data/try/{10_familia_try.rb → core/familia_extended_try.rb} +11 -10
  53. data/try/{00_familia_try.rb → core/familia_try.rb} +5 -3
  54. data/try/core/middleware_try.rb +68 -0
  55. data/try/core/refinements_try.rb +39 -0
  56. data/try/core/settings_try.rb +76 -0
  57. data/try/core/tools_try.rb +54 -0
  58. data/try/core/utils_try.rb +189 -0
  59. data/try/{26_redis_bool_try.rb → datatypes/boolean_try.rb} +4 -2
  60. data/try/datatypes/datatype_base_try.rb +69 -0
  61. data/try/{25_redis_type_hash_try.rb → datatypes/hash_try.rb} +5 -3
  62. data/try/{23_redis_type_list_try.rb → datatypes/list_try.rb} +5 -3
  63. data/try/{22_redis_type_set_try.rb → datatypes/set_try.rb} +5 -3
  64. data/try/{21_redis_type_zset_try.rb → datatypes/sorted_set_try.rb} +6 -4
  65. data/try/{24_redis_type_string_try.rb → datatypes/string_try.rb} +8 -8
  66. data/try/edge_cases/empty_identifiers_try.rb +48 -0
  67. data/try/{92_symbolize_try.rb → edge_cases/hash_symbolization_try.rb} +12 -7
  68. data/try/edge_cases/json_serialization_try.rb +85 -0
  69. data/try/edge_cases/race_conditions_try.rb +60 -0
  70. data/try/edge_cases/reserved_keywords_try.rb +59 -0
  71. data/try/{93_string_coercion_try.rb → edge_cases/string_coercion_try.rb} +60 -59
  72. data/try/edge_cases/ttl_side_effects_try.rb +51 -0
  73. data/try/features/expiration_try.rb +86 -0
  74. data/try/features/quantization_try.rb +90 -0
  75. data/try/{35_feature_safedump_try.rb → features/safe_dump_advanced_try.rb} +7 -6
  76. data/try/features/safe_dump_try.rb +137 -0
  77. data/try/{test_helpers.rb → helpers/test_helpers.rb} +25 -60
  78. data/try/{27_redis_horreum_try.rb → horreum/base_try.rb} +39 -14
  79. data/try/horreum/class_methods_try.rb +41 -0
  80. data/try/horreum/commands_try.rb +49 -0
  81. data/try/{29_redis_horreum_initialization_try.rb → horreum/initialization_try.rb} +9 -7
  82. data/try/horreum/relations_try.rb +146 -0
  83. data/try/{28_redis_horreum_serialization_try.rb → horreum/serialization_try.rb} +13 -11
  84. data/try/horreum/settings_try.rb +43 -0
  85. data/try/integration/cross_component_try.rb +46 -0
  86. data/try/{41_customer_safedump_try.rb → models/customer_safe_dump_try.rb} +9 -7
  87. data/try/{40_customer_try.rb → models/customer_try.rb} +20 -17
  88. data/try/models/datatype_base_try.rb +101 -0
  89. data/try/{30_familia_object_try.rb → models/familia_object_try.rb} +18 -16
  90. data/try/performance/benchmarks_try.rb +55 -0
  91. data/try/pooling/README.md +20 -0
  92. data/try/pooling/configurable_stress_test_try.rb +435 -0
  93. data/try/pooling/connection_pool_test_try.rb +273 -0
  94. data/try/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +192 -0
  95. data/try/pooling/lib/connection_pool_metrics.rb +372 -0
  96. data/try/pooling/lib/connection_pool_stress_test.rb +959 -0
  97. data/try/pooling/lib/connection_pool_threading_models.rb +421 -0
  98. data/try/pooling/lib/visualize_stress_results.rb +434 -0
  99. data/try/pooling/pool_siege_try.rb +509 -0
  100. data/try/pooling/run_stress_tests_try.rb +482 -0
  101. data/try/prototypes/atomic_saves_v1_context_proxy.rb +121 -0
  102. data/try/prototypes/atomic_saves_v2_connection_switching.rb +161 -0
  103. data/try/prototypes/atomic_saves_v3_connection_pool.rb +189 -0
  104. data/try/prototypes/atomic_saves_v4.rb +105 -0
  105. data/try/prototypes/lib/atomic_saves_v2_connection_switching_helpers.rb +124 -0
  106. data/try/prototypes/lib/atomic_saves_v3_connection_pool_helpers.rb +192 -0
  107. metadata +140 -43
  108. data/.github/workflows/ruby.yml +0 -71
  109. data/VERSION.yml +0 -4
  110. data/lib/familia/redistype/commands.rb +0 -59
  111. data/lib/familia/redistype.rb +0 -228
  112. data/lib/familia/tools.rb +0 -68
  113. data/lib/redis_middleware.rb +0 -109
  114. data/try/20_redis_type_try.rb +0 -70
  115. data/try/91_json_bug_try.rb +0 -86
@@ -1,62 +1,61 @@
1
- # frozen_string_literal: true
1
+ # lib/familia/horreum/class_methods.rb
2
2
 
3
- require_relative 'relations_management'
3
+ require_relative 'related_fields_management'
4
4
 
5
5
  module Familia
6
6
  class Horreum
7
7
  # Class-level instance variables
8
8
  # These are set up as nil initially and populated later
9
- @redis = nil
10
- @identifier = nil
11
- @ttl = nil
12
- @db = nil
9
+ @dbclient = nil # TODO
10
+ @identifier_field = nil
11
+ @default_expiration = nil
12
+ @logical_database = nil
13
13
  @uri = nil
14
14
  @suffix = nil
15
15
  @prefix = nil
16
16
  @fields = nil # []
17
- @class_redis_types = nil # {}
18
- @redis_types = nil # {}
17
+ @class_related_fields = nil # {}
18
+ @related_fields = nil # {}
19
19
  @dump_method = nil
20
20
  @load_method = nil
21
21
 
22
22
  # ClassMethods: Provides class-level functionality for Horreum
23
23
  #
24
24
  # This module is extended into classes that include Familia::Horreum,
25
- # providing methods for Redis operations and object management.
25
+ # providing methods for Database operations and object management.
26
26
  #
27
27
  # Key features:
28
- # * Includes RelationsManagement for Redis-type field handling
29
- # * Defines methods for managing fields, identifiers, and Redis keys
30
- # * Provides utility methods for working with Redis objects
28
+ # * Includes RelatedFieldsManagement for DataType field handling
29
+ # * Defines methods for managing fields, identifiers, and dbkeys
30
+ # * Provides utility methods for working with Database objects
31
31
  #
32
32
  module ClassMethods
33
33
  include Familia::Settings
34
- include Familia::Horreum::RelationsManagement
35
-
36
- # Returns the Redis connection for the class.
37
- #
38
- # This method retrieves the Redis connection instance for the class. If no
39
- # connection is set, it initializes a new connection using the provided URI
40
- # or database configuration.
41
- #
42
- # @return [Redis] the Redis connection instance.
43
- #
44
- def redis
45
- @redis || Familia.redis(uri || db)
46
- end
47
-
48
- # Sets or retrieves the unique identifier for the class.
49
- #
50
- # This method defines or returns the unique identifier used to generate the
51
- # Redis key for the object. If a value is provided, it sets the identifier;
52
- # otherwise, it returns the current identifier.
53
- #
54
- # @param [Object] val the value to set as the identifier (optional).
55
- # @return [Object] the current identifier.
56
- #
57
- def identifier(val = nil)
58
- @identifier = val if val
59
- @identifier
34
+ include Familia::Horreum::RelatedFieldsManagement
35
+
36
+ # Sets or retrieves the unique identifier field for the class.
37
+ #
38
+ # This method defines or returns the field or method that contains the unique
39
+ # identifier used to generate the dbkey for the object. If a value is provided,
40
+ # it sets the identifier field; otherwise, it returns the current identifier field.
41
+ #
42
+ # @param [Object] val the field name or method to set as the identifier field (optional).
43
+ # @return [Object] the current identifier field.
44
+ #
45
+ def identifier_field(val = nil)
46
+ if val
47
+ # Validate identifier field definition at class definition time
48
+ case val
49
+ when Symbol, String, Proc
50
+ @identifier_field = val
51
+ else
52
+ raise Problem, <<~ERROR
53
+ Invalid identifier field definition: #{val.inspect}.
54
+ Use a field name (Symbol/String) or Proc.
55
+ ERROR
56
+ end
57
+ end
58
+ @identifier_field
60
59
  end
61
60
 
62
61
  # Defines a field for the class and creates accessor methods.
@@ -84,12 +83,12 @@ module Familia
84
83
  # The dynamically defined method performs the following:
85
84
  # - Acts as both a reader and a writer method.
86
85
  # - When called without arguments, retrieves the current value from Redis.
87
- # - When called with an argument, persists the value to Redis immediately.
86
+ # - When called with an argument, persists the value to Database immediately.
88
87
  # - Checks if the correct number of arguments is provided (zero or one).
89
- # - Converts the provided value to a format suitable for Redis storage.
88
+ # - Converts the provided value to a format suitable for Database storage.
90
89
  # - Uses the existing accessor method to set the attribute value when
91
90
  # writing.
92
- # - Persists the value to Redis immediately using the hset command when
91
+ # - Persists the value to Database immediately using the hset command when
93
92
  # writing.
94
93
  # - Includes custom error handling to raise an ArgumentError if the wrong
95
94
  # number of arguments is given.
@@ -145,21 +144,21 @@ module Familia
145
144
  val = args.first
146
145
 
147
146
  # If no value is provided to this fast attribute method, make a call
148
- # to redis to return the current stored value of the hash field.
147
+ # to the db to return the current stored value of the hash field.
149
148
  return hget name if val.nil?
150
149
 
151
150
  begin
152
151
  # Trace the operation if debugging is enabled.
153
- Familia.trace :FAST_WRITER, redis, "#{name}: #{val.inspect}", caller(1..1) if Familia.debug?
152
+ Familia.trace :FAST_WRITER, dbclient, "#{name}: #{val.inspect}", caller(1..1) if Familia.debug?
154
153
 
155
- # Convert the provided value to a format suitable for Redis storage.
154
+ # Convert the provided value to a format suitable for Database storage.
156
155
  prepared = serialize_value(val)
157
156
  Familia.ld "[.fast_attribute!] #{name} val: #{val.class} prepared: #{prepared.class}"
158
157
 
159
158
  # Use the existing accessor method to set the attribute value.
160
159
  send :"#{name}=", val
161
160
 
162
- # Persist the value to Redis immediately using the hset command.
161
+ # Persist the value to Database immediately using the hset command.
163
162
  hset name, prepared
164
163
  rescue Familia::Problem => e
165
164
  # Raise a custom error message if an exception occurs during the execution of the method.
@@ -175,36 +174,24 @@ module Familia
175
174
  @fields
176
175
  end
177
176
 
178
- def class_redis_types
179
- @class_redis_types ||= {}
180
- @class_redis_types
177
+ def class_related_fields
178
+ @class_related_fields ||= {}
179
+ @class_related_fields
181
180
  end
182
181
 
183
- def class_redis_types?(name)
184
- class_redis_types.key? name.to_s.to_sym
185
- end
186
-
187
- def redis_object?(name)
188
- redis_types.key? name.to_s.to_sym
189
- end
190
-
191
- def redis_types
192
- @redis_types ||= {}
193
- @redis_types
182
+ def related_fields
183
+ @related_fields ||= {}
184
+ @related_fields
194
185
  end
195
186
 
196
187
  def has_relations?
197
188
  @has_relations ||= false
198
189
  end
199
190
 
200
- def db(v = nil)
201
- @db = v unless v.nil?
202
- @db || parent&.db
203
- end
204
-
205
- def uri(v = nil)
206
- @uri = v unless v.nil?
207
- @uri || parent&.uri
191
+ def logical_database(v = nil)
192
+ Familia.trace :DB, Familia.dbclient, "#{@logical_database} #{v}", caller(1..1) if Familia.debug?
193
+ @logical_database = v unless v.nil?
194
+ @logical_database || parent&.logical_database
208
195
  end
209
196
 
210
197
  def all(suffix = nil)
@@ -217,11 +204,11 @@ module Familia
217
204
  matching_keys_count(filter) > 0
218
205
  end
219
206
 
220
- # Returns the number of Redis keys matching the given filter pattern
221
- # @param filter [String] Redis key pattern to match (default: '*')
207
+ # Returns the number of dbkeys matching the given filter pattern
208
+ # @param filter [String] dbkey pattern to match (default: '*')
222
209
  # @return [Integer] Number of matching keys
223
210
  def matching_keys_count(filter = '*')
224
- redis.keys(rediskey(filter)).compact.size
211
+ dbclient.keys(dbkey(filter)).compact.size
225
212
  end
226
213
  alias size matching_keys_count # For backwards compatibility
227
214
 
@@ -273,7 +260,7 @@ module Familia
273
260
  #
274
261
  def create *args, **kwargs
275
262
  fobj = new(*args, **kwargs)
276
- raise Familia::Problem, "#{self} already exists: #{fobj.rediskey}" if fobj.exists?
263
+ raise Familia::Problem, "#{self} already exists: #{fobj.dbkey}" if fobj.exists?
277
264
 
278
265
  fobj.save
279
266
  fobj
@@ -285,17 +272,17 @@ module Familia
285
272
  end
286
273
 
287
274
  def rawmultiget(*ids)
288
- ids.collect! { |objid| rediskey(objid) }
275
+ ids.collect! { |objid| dbkey(objid) }
289
276
  return [] if ids.compact.empty?
290
277
 
291
- Familia.trace :MULTIGET, redis, "#{ids.size}: #{ids}", caller(1..1) if Familia.debug?
292
- redis.mget(*ids)
278
+ Familia.trace :MULTIGET, dbclient, "#{ids.size}: #{ids}", caller(1..1) if Familia.debug?
279
+ dbclient.mget(*ids)
293
280
  end
294
281
 
295
- # Retrieves and instantiates an object from Redis using the full object
282
+ # Retrieves and instantiates an object from Database using the full object
296
283
  # key.
297
284
  #
298
- # @param objkey [String] The full Redis key for the object.
285
+ # @param objkey [String] The full dbkey for the object.
299
286
  # @return [Object, nil] An instance of the class if the key exists, nil
300
287
  # otherwise.
301
288
  # @raise [ArgumentError] If the provided key is empty.
@@ -325,10 +312,10 @@ module Familia
325
312
 
326
313
  # We use a lower-level method here b/c we're working with the
327
314
  # full key and not just the identifier.
328
- does_exist = redis.exists(objkey).positive?
315
+ does_exist = dbclient.exists(objkey).positive?
329
316
 
330
317
  Familia.ld "[.find_by_key] #{self} from key #{objkey} (exists: #{does_exist})"
331
- Familia.trace :FROM_KEY, redis, objkey, caller(1..1) if Familia.debug?
318
+ Familia.trace :FROM_KEY, dbclient, objkey, caller(1..1) if Familia.debug?
332
319
 
333
320
  # This is the reason for calling exists first. We want to definitively
334
321
  # and without any ambiguity know if the object exists in Redis. If it
@@ -337,22 +324,22 @@ module Familia
337
324
  # the constructor, which will then be annoying to debug.
338
325
  return unless does_exist
339
326
 
340
- obj = redis.hgetall(objkey) # horreum objects are persisted as redis hashes
341
- Familia.trace :FROM_KEY2, redis, "#{objkey}: #{obj.inspect}", caller(1..1) if Familia.debug?
327
+ obj = dbclient.hgetall(objkey) # horreum objects are persisted as database hashes
328
+ Familia.trace :FROM_KEY2, dbclient, "#{objkey}: #{obj.inspect}", caller(1..1) if Familia.debug?
342
329
 
343
330
  new(**obj)
344
331
  end
345
- alias from_rediskey find_by_key # deprecated
332
+ alias from_dbkey find_by_key # deprecated
346
333
 
347
- # Retrieves and instantiates an object from Redis using its identifier.
334
+ # Retrieves and instantiates an object from Database using its identifier.
348
335
  #
349
336
  # @param identifier [String, Integer] The unique identifier for the
350
337
  # object.
351
- # @param suffix [Symbol] The suffix to use in the Redis key (default:
338
+ # @param suffix [Symbol] The suffix to use in the dbkey (default:
352
339
  # :object).
353
340
  # @return [Object, nil] An instance of the class if found, nil otherwise.
354
341
  #
355
- # This method constructs the full Redis key using the provided identifier
342
+ # This method constructs the full dbkey using the provided identifier
356
343
  # and suffix, then delegates to `find_by_key` for the actual retrieval and
357
344
  # instantiation.
358
345
  #
@@ -367,10 +354,10 @@ module Familia
367
354
  suffix ||= self.suffix
368
355
  return nil if identifier.to_s.empty?
369
356
 
370
- objkey = rediskey(identifier, suffix)
357
+ objkey = dbkey(identifier, suffix)
371
358
 
372
359
  Familia.ld "[.find_by_id] #{self} from key #{objkey})"
373
- Familia.trace :FIND_BY_ID, Familia.redis(uri), objkey, caller(1..1).first if Familia.debug?
360
+ Familia.trace :FIND_BY_ID, Familia.dbclient(uri), objkey, caller(1..1).first if Familia.debug?
374
361
  find_by_key objkey
375
362
  end
376
363
  alias find find_by_id
@@ -380,10 +367,10 @@ module Familia
380
367
  # Checks if an object with the given identifier exists in Redis.
381
368
  #
382
369
  # @param identifier [String, Integer] The unique identifier for the object.
383
- # @param suffix [Symbol, nil] The suffix to use in the Redis key (default: class suffix).
370
+ # @param suffix [Symbol, nil] The suffix to use in the dbkey (default: class suffix).
384
371
  # @return [Boolean] true if the object exists, false otherwise.
385
372
  #
386
- # This method constructs the full Redis key using the provided identifier and suffix,
373
+ # This method constructs the full dbkey using the provided identifier and suffix,
387
374
  # then checks if the key exists in Redis.
388
375
  #
389
376
  # @example
@@ -393,24 +380,24 @@ module Familia
393
380
  suffix ||= self.suffix
394
381
  return false if identifier.to_s.empty?
395
382
 
396
- objkey = rediskey identifier, suffix
383
+ objkey = dbkey identifier, suffix
397
384
 
398
- ret = redis.exists objkey
399
- Familia.trace :EXISTS, redis, "#{objkey} #{ret.inspect}", caller(1..1) if Familia.debug?
385
+ ret = dbclient.exists objkey
386
+ Familia.trace :EXISTS, dbclient, "#{objkey} #{ret.inspect}", caller(1..1) if Familia.debug?
400
387
 
401
- ret.positive? # differs from redis API but I think it's okay bc `exists?` is a predicate method.
388
+ ret.positive? # differs from Valkey API but I think it's okay bc `exists?` is a predicate method.
402
389
  end
403
390
 
404
- # Destroys an object in Redis with the given identifier.
391
+ # Destroys an object in Database with the given identifier.
405
392
  #
406
393
  # @param identifier [String, Integer] The unique identifier for the object to destroy.
407
- # @param suffix [Symbol, nil] The suffix to use in the Redis key (default: class suffix).
394
+ # @param suffix [Symbol, nil] The suffix to use in the dbkey (default: class suffix).
408
395
  # @return [Boolean] true if the object was successfully destroyed, false otherwise.
409
396
  #
410
397
  # This method is part of Familia's high-level object lifecycle management. While `delete!`
411
- # operates directly on Redis keys, `destroy!` operates at the object level and is used for
398
+ # operates directly on dbkeys, `destroy!` operates at the object level and is used for
412
399
  # ORM-style operations. Use `destroy!` when removing complete objects from the system, and
413
- # `delete!` when working directly with Redis keys.
400
+ # `delete!` when working directly with dbkeys.
414
401
  #
415
402
  # @example
416
403
  # User.destroy!(123) # Removes user:123:object from Redis
@@ -419,27 +406,27 @@ module Familia
419
406
  suffix ||= self.suffix
420
407
  return false if identifier.to_s.empty?
421
408
 
422
- objkey = rediskey identifier, suffix
409
+ objkey = dbkey identifier, suffix
423
410
 
424
- ret = redis.del objkey
425
- Familia.trace :DESTROY!, redis, "#{objkey} #{ret.inspect}", caller(1..1) if Familia.debug?
411
+ ret = dbclient.del objkey
412
+ Familia.trace :DESTROY!, dbclient, "#{objkey} #{ret.inspect}", caller(1..1) if Familia.debug?
426
413
  ret.positive?
427
414
  end
428
415
 
429
- # Finds all keys in Redis matching the given suffix pattern.
416
+ # Finds all keys in Database matching the given suffix pattern.
430
417
  #
431
418
  # @param suffix [String] The suffix pattern to match (default: '*').
432
- # @return [Array<String>] An array of matching Redis keys.
419
+ # @return [Array<String>] An array of matching dbkeys.
433
420
  #
434
- # This method searches for all Redis keys that match the given suffix pattern.
435
- # It uses the class's rediskey method to construct the search pattern.
421
+ # This method searches for all dbkeys that match the given suffix pattern.
422
+ # It uses the class's dbkey method to construct the search pattern.
436
423
  #
437
424
  # @example
438
425
  # User.find # Returns all keys matching user:*:object
439
426
  # User.find('active') # Returns all keys matching user:*:active
440
427
  #
441
428
  def find_keys(suffix = '*')
442
- redis.keys(rediskey('*', suffix)) || []
429
+ dbclient.keys(dbkey('*', suffix)) || []
443
430
  end
444
431
 
445
432
  # +identifier+ can be a value or an Array of values used to create the index.
@@ -449,15 +436,15 @@ module Familia
449
436
  # +suffix+ If a nil value is explicitly passed in, it won't appear in the redis
450
437
  # key that's returned. If no suffix is passed in, the class' suffix is used
451
438
  # as the default (via the class method self.suffix). It's an important
452
- # distinction b/c passing in an explicitly nil is how RedisType objects
439
+ # distinction b/c passing in an explicitly nil is how DataType objects
453
440
  # at the class level are created without the global default 'object'
454
- # suffix. See RedisType#rediskey "parent_class?" for more details.
455
- def rediskey(identifier, suffix = self.suffix)
456
- # Familia.ld "[.rediskey] #{identifier} for #{self} (suffix:#{suffix})"
441
+ # suffix. See DataType#dbkey "parent_class?" for more details.
442
+ def dbkey(identifier, suffix = self.suffix)
443
+ # Familia.ld "[.dbkey] #{identifier} for #{self} (suffix:#{suffix})"
457
444
  raise NoIdentifier, self if identifier.to_s.empty?
458
445
 
459
446
  identifier &&= identifier.to_s
460
- Familia.rediskey(prefix, identifier, suffix)
447
+ Familia.dbkey(prefix, identifier, suffix)
461
448
  end
462
449
 
463
450
  def dump_method
@@ -468,6 +455,6 @@ module Familia
468
455
  @load_method || :from_json # Familia.load_method
469
456
  end
470
457
  end
471
- # End of ClassMethods module
458
+
472
459
  end
473
460
  end
@@ -1,25 +1,25 @@
1
- # rubocop:disable all
2
- #
1
+ # lib/familia/horreum/commands.rb
2
+
3
3
  module Familia
4
4
  # InstanceMethods - Module containing instance-level methods for Familia
5
5
  #
6
6
  # This module is included in classes that include Familia, providing
7
- # instance-level functionality for Redis operations and object management.
7
+ # instance-level functionality for Database operations and object management.
8
8
  #
9
9
  class Horreum
10
10
 
11
- # Methods that call Redis commands (InstanceMethods)
11
+ # Methods that call Database commands (InstanceMethods)
12
12
  #
13
13
  # NOTE: There is no hgetall for Horreum. This is because Horreum
14
- # is a single hash in Redis that we aren't meant to have be working
14
+ # is a single hash in Database that we aren't meant to have be working
15
15
  # on in memory for more than, making changes -> committing. To
16
16
  # emphasize this, instead of "refreshing" the object with hgetall,
17
17
  # just load the object again.
18
18
  #
19
19
  module Commands
20
20
 
21
- def move(db)
22
- redis.move rediskey, db
21
+ def move(logical_database)
22
+ dbclient.move dbkey, logical_database
23
23
  end
24
24
 
25
25
  # Checks if the calling object's key exists in Redis.
@@ -39,7 +39,7 @@ module Familia
39
39
  # @note The default behavior maintains backward compatibility by treating empty hashes
40
40
  # as non-existent. Use `check_size: false` for pure key existence checking.
41
41
  def exists?(check_size: true)
42
- key_exists = self.class.redis.exists?(rediskey)
42
+ key_exists = self.class.dbclient.exists?(dbkey)
43
43
  return key_exists unless check_size
44
44
  key_exists && !size.zero?
45
45
  end
@@ -47,7 +47,7 @@ module Familia
47
47
  # Returns the number of fields in the main object hash
48
48
  # @return [Integer] number of fields
49
49
  def field_count
50
- redis.hlen rediskey
50
+ dbclient.hlen dbkey
51
51
  end
52
52
  alias size field_count
53
53
 
@@ -55,44 +55,39 @@ module Familia
55
55
  # automatically be deleted. Returns 1 if the timeout was set, 0 if key
56
56
  # does not exist or the timeout could not be set.
57
57
  #
58
- def expire(ttl = nil)
59
- ttl ||= self.class.ttl
60
- Familia.trace :EXPIRE, redis, ttl, caller(1..1) if Familia.debug?
61
- redis.expire rediskey, ttl.to_i
58
+ def expire(default_expiration = nil)
59
+ default_expiration ||= self.class.default_expiration
60
+ Familia.trace :EXPIRE, dbclient, default_expiration, caller(1..1) if Familia.debug?
61
+ dbclient.expire dbkey, default_expiration.to_i
62
62
  end
63
63
 
64
- # Retrieves the remaining time to live (TTL) for the object's Redis key.
64
+ # Retrieves the remaining time to live (TTL) for the object's dbkey.
65
65
  #
66
- # This method accesses the ovjects Redis client to obtain the TTL of `rediskey`.
66
+ # This method accesses the ovjects Database client to obtain the TTL of `dbkey`.
67
67
  # If debugging is enabled, it logs the TTL retrieval operation using `Familia.trace`.
68
68
  #
69
69
  # @return [Integer] The TTL of the key in seconds. Returns -1 if the key does not exist
70
70
  # or has no associated expire time.
71
- def realttl
72
- Familia.trace :REALTTL, redis, redisuri, caller(1..1) if Familia.debug?
73
- redis.ttl rediskey
71
+ def current_expiration
72
+ Familia.trace :CURRENT_EXPIRATION, dbclient, uri, caller(1..1) if Familia.debug?
73
+ dbclient.ttl dbkey
74
74
  end
75
75
 
76
- # Removes a field from the hash stored at the Redis key.
76
+ # Removes a field from the hash stored at the dbkey.
77
77
  #
78
78
  # @param field [String] The field to remove from the hash.
79
79
  # @return [Integer] The number of fields that were removed from the hash (0 or 1).
80
80
  def remove_field(field)
81
- Familia.trace :HDEL, redis, field, caller(1..1) if Familia.debug?
82
- redis.hdel rediskey, field
81
+ Familia.trace :HDEL, dbclient, field, caller(1..1) if Familia.debug?
82
+ dbclient.hdel dbkey, field
83
83
  end
84
84
  alias remove remove_field # deprecated
85
85
 
86
- def redistype
87
- Familia.trace :REDISTYPE, redis, redisuri, caller(1..1) if Familia.debug?
88
- redis.type rediskey(suffix)
86
+ def datatype
87
+ Familia.trace :DATATYPE, dbclient, uri, caller(1..1) if Familia.debug?
88
+ dbclient.type dbkey(suffix)
89
89
  end
90
90
 
91
- # Parity with RedisType#rename
92
- def rename(newkey)
93
- Familia.trace :RENAME, redis, "#{rediskey} -> #{newkey}", caller(1..1) if Familia.debug?
94
- redis.rename rediskey, newkey
95
- end
96
91
 
97
92
  # Retrieves the prefix for the current instance by delegating to its class.
98
93
  #
@@ -103,80 +98,80 @@ module Familia
103
98
  self.class.prefix
104
99
  end
105
100
 
106
- # For parity with RedisType#hgetall
101
+ # For parity with DataType#hgetall
107
102
  def hgetall
108
- Familia.trace :HGETALL, redis, redisuri, caller(1..1) if Familia.debug?
109
- redis.hgetall rediskey(suffix)
103
+ Familia.trace :HGETALL, dbclient, uri, caller(1..1) if Familia.debug?
104
+ dbclient.hgetall dbkey(suffix)
110
105
  end
111
106
  alias all hgetall
112
107
 
113
108
  def hget(field)
114
- Familia.trace :HGET, redis, field, caller(1..1) if Familia.debug?
115
- redis.hget rediskey(suffix), field
109
+ Familia.trace :HGET, dbclient, field, caller(1..1) if Familia.debug?
110
+ dbclient.hget dbkey(suffix), field
116
111
  end
117
112
 
118
113
  # @return The number of fields that were added to the hash. If the
119
114
  # field already exists, this will return 0.
120
115
  def hset(field, value)
121
- Familia.trace :HSET, redis, field, caller(1..1) if Familia.debug?
122
- redis.hset rediskey, field, value
116
+ Familia.trace :HSET, dbclient, field, caller(1..1) if Familia.debug?
117
+ dbclient.hset dbkey, field, value
123
118
  end
124
119
 
125
120
  def hmset(hsh={})
126
121
  hsh ||= self.to_h
127
- Familia.trace :HMSET, redis, hsh, caller(1..1) if Familia.debug?
128
- redis.hmset rediskey(suffix), hsh
122
+ Familia.trace :HMSET, dbclient, hsh, caller(1..1) if Familia.debug?
123
+ dbclient.hmset dbkey(suffix), hsh
129
124
  end
130
125
 
131
126
  def hkeys
132
- Familia.trace :HKEYS, redis, 'redisuri', caller(1..1) if Familia.debug?
133
- redis.hkeys rediskey(suffix)
127
+ Familia.trace :HKEYS, dbclient, 'uri', caller(1..1) if Familia.debug?
128
+ dbclient.hkeys dbkey(suffix)
134
129
  end
135
130
 
136
131
  def hvals
137
- redis.hvals rediskey(suffix)
132
+ dbclient.hvals dbkey(suffix)
138
133
  end
139
134
 
140
135
  def incr(field)
141
- redis.hincrby rediskey(suffix), field, 1
136
+ dbclient.hincrby dbkey(suffix), field, 1
142
137
  end
143
138
  alias increment incr
144
139
 
145
140
  def incrby(field, increment)
146
- redis.hincrby rediskey(suffix), field, increment
141
+ dbclient.hincrby dbkey(suffix), field, increment
147
142
  end
148
143
  alias incrementby incrby
149
144
 
150
145
  def incrbyfloat(field, increment)
151
- redis.hincrbyfloat rediskey(suffix), field, increment
146
+ dbclient.hincrbyfloat dbkey(suffix), field, increment
152
147
  end
153
148
  alias incrementbyfloat incrbyfloat
154
149
 
155
150
  def decrby(field, decrement)
156
- redis.decrby rediskey(suffix), field, decrement
151
+ dbclient.decrby dbkey(suffix), field, decrement
157
152
  end
158
153
  alias decrementby decrby
159
154
 
160
155
  def decr(field)
161
- redis.hdecr field
156
+ dbclient.hdecr field
162
157
  end
163
158
  alias decrement decr
164
159
 
165
160
  def hstrlen(field)
166
- redis.hstrlen rediskey(suffix), field
161
+ dbclient.hstrlen dbkey(suffix), field
167
162
  end
168
163
  alias hstrlength hstrlen
169
164
 
170
165
  def key?(field)
171
- redis.hexists rediskey(suffix), field
166
+ dbclient.hexists dbkey(suffix), field
172
167
  end
173
168
  alias has_key? key?
174
169
 
175
- # Deletes the entire Redis key
170
+ # Deletes the entire dbkey
176
171
  # @return [Boolean] true if the key was deleted, false otherwise
177
172
  def delete!
178
- Familia.trace :DELETE!, redis, redisuri, caller(1..1) if Familia.debug?
179
- ret = redis.del rediskey
173
+ Familia.trace :DELETE!, dbclient, uri, caller(1..1) if Familia.debug?
174
+ ret = dbclient.del dbkey
180
175
  ret.positive?
181
176
  end
182
177
  alias clear delete!