familia 2.0.0.pre16 → 2.0.0.pre18

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 (250) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +2 -2
  3. data/.github/workflows/{code-smellage.yml → code-smells.yml} +3 -63
  4. data/.gitignore +2 -0
  5. data/.rubocop.yml +6 -0
  6. data/CHANGELOG.rst +82 -0
  7. data/CLAUDE.md +47 -2
  8. data/Gemfile.lock +1 -1
  9. data/README.md +13 -0
  10. data/bin/irb +1 -1
  11. data/docs/archive/FAMILIA_TECHNICAL.md +1 -1
  12. data/docs/guides/core-field-system.md +48 -26
  13. data/docs/migrating/v2.0.0-pre18.md +58 -0
  14. data/docs/overview.md +2 -2
  15. data/docs/qodo-merge-compliance.md +96 -0
  16. data/docs/reference/api-technical.md +1 -1
  17. data/examples/encrypted_fields.rb +1 -1
  18. data/examples/safe_dump.rb +1 -1
  19. data/lib/familia/base.rb +6 -6
  20. data/lib/familia/connection/middleware.rb +58 -4
  21. data/lib/familia/connection.rb +1 -1
  22. data/lib/familia/data_type/class_methods.rb +63 -0
  23. data/lib/familia/data_type/connection.rb +83 -0
  24. data/lib/familia/data_type/{commands.rb → database_commands.rb} +2 -2
  25. data/lib/familia/data_type/serialization.rb +5 -5
  26. data/lib/familia/data_type/settings.rb +96 -0
  27. data/lib/familia/data_type/types/hashkey.rb +2 -1
  28. data/lib/familia/data_type/types/sorted_set.rb +113 -10
  29. data/lib/familia/data_type/types/stringkey.rb +0 -4
  30. data/lib/familia/data_type.rb +8 -195
  31. data/lib/familia/encryption/encrypted_data.rb +12 -2
  32. data/lib/familia/encryption/manager.rb +11 -4
  33. data/lib/familia/features/autoloader.rb +3 -1
  34. data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +11 -3
  35. data/lib/familia/features/encrypted_fields.rb +5 -2
  36. data/lib/familia/features/external_identifier.rb +49 -8
  37. data/lib/familia/features/object_identifier.rb +84 -12
  38. data/lib/familia/features/relationships/indexing/multi_index_generators.rb +9 -9
  39. data/lib/familia/features/relationships/indexing/unique_index_generators.rb +45 -26
  40. data/lib/familia/features/relationships/indexing.rb +7 -1
  41. data/lib/familia/features/relationships/participation/participant_methods.rb +6 -2
  42. data/lib/familia/features/safe_dump.rb +2 -3
  43. data/lib/familia/features/transient_fields.rb +7 -2
  44. data/lib/familia/features.rb +6 -1
  45. data/lib/familia/field_type.rb +0 -18
  46. data/lib/familia/horreum/{core/connection.rb → connection.rb} +21 -0
  47. data/lib/familia/horreum/{core/database_commands.rb → database_commands.rb} +1 -1
  48. data/lib/familia/horreum/{subclass/definition.rb → definition.rb} +102 -56
  49. data/lib/familia/horreum/{subclass/management.rb → management.rb} +18 -15
  50. data/lib/familia/horreum/{core/serialization.rb → persistence.rb} +73 -170
  51. data/lib/familia/horreum/{subclass/related_fields_management.rb → related_fields.rb} +22 -2
  52. data/lib/familia/horreum/serialization.rb +190 -0
  53. data/lib/familia/horreum.rb +39 -14
  54. data/lib/familia/identifier_extractor.rb +60 -0
  55. data/lib/familia/logging.rb +271 -112
  56. data/lib/familia/refinements.rb +0 -1
  57. data/lib/familia/version.rb +1 -1
  58. data/lib/familia.rb +2 -2
  59. data/lib/middleware/{database_middleware.rb → database_logger.rb} +47 -14
  60. data/pr_agent.toml +31 -0
  61. data/pr_compliance_checklist.yaml +45 -0
  62. data/try/edge_cases/empty_identifiers_try.rb +1 -1
  63. data/try/edge_cases/hash_symbolization_try.rb +31 -31
  64. data/try/edge_cases/json_serialization_try.rb +2 -2
  65. data/try/edge_cases/legacy_data_detection/deserialization_edge_cases_try.rb +170 -0
  66. data/try/edge_cases/race_conditions_try.rb +1 -1
  67. data/try/edge_cases/reserved_keywords_try.rb +1 -1
  68. data/try/edge_cases/string_coercion_try.rb +1 -1
  69. data/try/edge_cases/ttl_side_effects_try.rb +1 -1
  70. data/try/features/encrypted_fields/aad_protection_try.rb +1 -1
  71. data/try/features/encrypted_fields/concealed_string_core_try.rb +1 -1
  72. data/try/features/encrypted_fields/context_isolation_try.rb +1 -1
  73. data/try/features/encrypted_fields/encrypted_fields_core_try.rb +1 -1
  74. data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +1 -1
  75. data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +1 -1
  76. data/try/features/encrypted_fields/encrypted_fields_security_try.rb +1 -1
  77. data/try/features/encrypted_fields/error_conditions_try.rb +1 -1
  78. data/try/features/encrypted_fields/fresh_key_derivation_try.rb +1 -1
  79. data/try/features/encrypted_fields/fresh_key_try.rb +1 -1
  80. data/try/features/encrypted_fields/key_rotation_try.rb +1 -1
  81. data/try/features/encrypted_fields/memory_security_try.rb +1 -1
  82. data/try/features/encrypted_fields/missing_current_key_version_try.rb +1 -1
  83. data/try/features/encrypted_fields/nonce_uniqueness_try.rb +1 -1
  84. data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +1 -1
  85. data/try/features/encrypted_fields/thread_safety_try.rb +1 -1
  86. data/try/features/encrypted_fields/universal_serialization_safety_try.rb +1 -1
  87. data/try/{encryption → features/encryption}/config_persistence_try.rb +1 -1
  88. data/try/{encryption/encryption_core_try.rb → features/encryption/core_try.rb} +2 -2
  89. data/try/{encryption → features/encryption}/instance_variable_scope_try.rb +1 -1
  90. data/try/{encryption → features/encryption}/module_loading_try.rb +1 -1
  91. data/try/{encryption → features/encryption}/providers/aes_gcm_provider_try.rb +1 -1
  92. data/try/{encryption → features/encryption}/providers/xchacha20_poly1305_provider_try.rb +1 -1
  93. data/try/{encryption → features/encryption}/roundtrip_validation_try.rb +1 -1
  94. data/try/{encryption → features/encryption}/secure_memory_handling_try.rb +2 -2
  95. data/try/features/expiration/expiration_try.rb +1 -1
  96. data/try/features/external_identifier/external_identifier_try.rb +1 -1
  97. data/try/features/feature_dependencies_try.rb +1 -1
  98. data/try/features/feature_improvements_try.rb +1 -1
  99. data/try/features/field_groups_try.rb +244 -0
  100. data/try/features/object_identifier/object_identifier_integration_try.rb +1 -1
  101. data/try/features/object_identifier/object_identifier_try.rb +1 -1
  102. data/try/features/quantization/quantization_try.rb +1 -1
  103. data/try/features/real_feature_integration_try.rb +17 -14
  104. data/try/features/relationships/indexing_commands_verification_try.rb +8 -3
  105. data/try/features/relationships/indexing_try.rb +16 -1
  106. data/try/features/relationships/participation_commands_verification_spec.rb +1 -1
  107. data/try/features/relationships/participation_commands_verification_try.rb +4 -4
  108. data/try/features/relationships/participation_performance_improvements_try.rb +1 -1
  109. data/try/features/relationships/participation_reverse_index_try.rb +1 -1
  110. data/try/features/relationships/relationships_api_changes_try.rb +1 -1
  111. data/try/features/relationships/relationships_edge_cases_try.rb +3 -3
  112. data/try/features/relationships/relationships_performance_minimal_try.rb +1 -1
  113. data/try/features/relationships/relationships_performance_simple_try.rb +1 -1
  114. data/try/features/relationships/relationships_performance_try.rb +1 -1
  115. data/try/features/relationships/relationships_performance_working_try.rb +1 -1
  116. data/try/features/relationships/relationships_try.rb +1 -1
  117. data/try/features/safe_dump/safe_dump_advanced_try.rb +1 -1
  118. data/try/features/safe_dump/safe_dump_try.rb +1 -1
  119. data/try/features/transient_fields/redacted_string_try.rb +1 -1
  120. data/try/features/transient_fields/refresh_reset_try.rb +3 -1
  121. data/try/features/transient_fields/single_use_redacted_string_try.rb +1 -1
  122. data/try/features/transient_fields/transient_fields_core_try.rb +1 -1
  123. data/try/features/transient_fields/transient_fields_integration_try.rb +1 -1
  124. data/try/{connection → integration/connection}/fiber_context_preservation_try.rb +1 -1
  125. data/try/{connection → integration/connection}/handler_constraints_try.rb +1 -1
  126. data/try/{core → integration/connection}/isolated_dbclient_try.rb +3 -3
  127. data/try/integration/connection/middleware_reconnect_try.rb +87 -0
  128. data/try/{connection → integration/connection}/operation_mode_guards_try.rb +1 -1
  129. data/try/{connection → integration/connection}/pipeline_fallback_integration_try.rb +1 -1
  130. data/try/{core → integration/connection}/pools_try.rb +1 -1
  131. data/try/{connection → integration/connection}/responsibility_chain_tracking_try.rb +1 -1
  132. data/try/{connection → integration/connection}/transaction_fallback_integration_try.rb +1 -1
  133. data/try/{connection → integration/connection}/transaction_mode_permissive_try.rb +1 -1
  134. data/try/{connection → integration/connection}/transaction_mode_strict_try.rb +1 -1
  135. data/try/{connection → integration/connection}/transaction_mode_warn_try.rb +1 -1
  136. data/try/{connection → integration/connection}/transaction_modes_try.rb +1 -1
  137. data/try/{core → integration}/conventional_inheritance_try.rb +1 -1
  138. data/try/{core → integration}/create_method_try.rb +1 -1
  139. data/try/integration/cross_component_try.rb +1 -1
  140. data/try/{core → integration}/database_consistency_try.rb +12 -8
  141. data/try/{core → integration}/familia_extended_try.rb +1 -1
  142. data/try/{core → integration}/familia_members_methods_try.rb +1 -1
  143. data/try/{models → integration/models}/customer_safe_dump_try.rb +1 -1
  144. data/try/{models → integration/models}/customer_try.rb +6 -6
  145. data/try/{models → integration/models}/datatype_base_try.rb +1 -1
  146. data/try/{models → integration/models}/familia_object_try.rb +1 -1
  147. data/try/{core → integration}/persistence_operations_try.rb +1 -1
  148. data/try/integration/relationships_persistence_round_trip_try.rb +441 -0
  149. data/try/{configuration → integration}/scenarios_try.rb +2 -2
  150. data/try/{core → integration}/secure_identifier_try.rb +1 -1
  151. data/try/{core → integration}/verifiable_identifier_try.rb +1 -1
  152. data/try/performance/benchmarks_try.rb +2 -2
  153. data/try/support/benchmarks/deserialization_benchmark.rb +180 -0
  154. data/try/support/benchmarks/deserialization_correctness_test.rb +237 -0
  155. data/try/{helpers → support/helpers}/test_helpers.rb +15 -7
  156. data/try/{memory → support/memory}/memory_docker_ruby_dump.sh +1 -1
  157. data/try/{core → unit/core}/autoloader_try.rb +1 -1
  158. data/try/{core → unit/core}/base_enhancements_try.rb +1 -9
  159. data/try/{core → unit/core}/connection_try.rb +5 -5
  160. data/try/{core → unit/core}/errors_try.rb +4 -4
  161. data/try/{core → unit/core}/extensions_try.rb +1 -1
  162. data/try/unit/core/familia_logger_try.rb +110 -0
  163. data/try/{core → unit/core}/familia_try.rb +2 -2
  164. data/try/{core → unit/core}/middleware_try.rb +41 -1
  165. data/try/{core → unit/core}/settings_try.rb +1 -1
  166. data/try/{core → unit/core}/time_utils_try.rb +1 -1
  167. data/try/{core → unit/core}/tools_try.rb +3 -3
  168. data/try/{core → unit/core}/utils_try.rb +17 -14
  169. data/try/{data_types → unit/data_types}/boolean_try.rb +1 -1
  170. data/try/{data_types → unit/data_types}/counter_try.rb +1 -1
  171. data/try/{data_types → unit/data_types}/datatype_base_try.rb +1 -1
  172. data/try/{data_types → unit/data_types}/hash_try.rb +1 -1
  173. data/try/{data_types → unit/data_types}/list_try.rb +1 -1
  174. data/try/{data_types → unit/data_types}/lock_try.rb +1 -1
  175. data/try/{data_types → unit/data_types}/sorted_set_try.rb +1 -1
  176. data/try/unit/data_types/sorted_set_zadd_options_try.rb +625 -0
  177. data/try/{data_types → unit/data_types}/string_try.rb +1 -1
  178. data/try/{data_types → unit/data_types}/unsortedset_try.rb +1 -1
  179. data/try/unit/horreum/auto_indexing_on_save_try.rb +212 -0
  180. data/try/{horreum → unit/horreum}/base_try.rb +3 -3
  181. data/try/{horreum → unit/horreum}/class_methods_try.rb +1 -1
  182. data/try/{horreum → unit/horreum}/commands_try.rb +3 -1
  183. data/try/unit/horreum/defensive_initialization_try.rb +86 -0
  184. data/try/{horreum → unit/horreum}/destroy_related_fields_cleanup_try.rb +3 -1
  185. data/try/{horreum → unit/horreum}/enhanced_conflict_handling_try.rb +1 -1
  186. data/try/{horreum → unit/horreum}/field_categories_try.rb +27 -18
  187. data/try/{horreum → unit/horreum}/field_definition_try.rb +1 -1
  188. data/try/{horreum → unit/horreum}/initialization_try.rb +2 -2
  189. data/try/unit/horreum/json_type_preservation_try.rb +248 -0
  190. data/try/{horreum → unit/horreum}/relations_try.rb +1 -1
  191. data/try/{horreum → unit/horreum}/serialization_persistent_fields_try.rb +24 -18
  192. data/try/{horreum → unit/horreum}/serialization_try.rb +4 -4
  193. data/try/{horreum → unit/horreum}/settings_try.rb +3 -1
  194. data/try/{refinements → unit/refinements}/dear_json_array_methods_try.rb +1 -1
  195. data/try/{refinements → unit/refinements}/dear_json_hash_methods_try.rb +1 -1
  196. data/try/{refinements → unit/refinements}/time_literals_numeric_methods_try.rb +1 -1
  197. data/try/{refinements → unit/refinements}/time_literals_string_methods_try.rb +1 -1
  198. data/try/valkey.conf +26 -0
  199. metadata +149 -132
  200. data/lib/familia/distinguisher.rb +0 -85
  201. data/lib/familia/horreum/core.rb +0 -21
  202. data/lib/familia/refinements/logger_trace.rb +0 -60
  203. data/try/refinements/logger_trace_methods_try.rb +0 -44
  204. /data/lib/familia/horreum/{shared/settings.rb → settings.rb} +0 -0
  205. /data/lib/familia/horreum/{core/utils.rb → utils.rb} +0 -0
  206. /data/try/{debugging → support/debugging}/README.md +0 -0
  207. /data/try/{debugging → support/debugging}/cache_behavior_tracer.rb +0 -0
  208. /data/try/{debugging → support/debugging}/debug_aad_process.rb +0 -0
  209. /data/try/{debugging → support/debugging}/debug_concealed_internal.rb +0 -0
  210. /data/try/{debugging → support/debugging}/debug_concealed_reveal.rb +0 -0
  211. /data/try/{debugging → support/debugging}/debug_context_aad.rb +0 -0
  212. /data/try/{debugging → support/debugging}/debug_context_simple.rb +0 -0
  213. /data/try/{debugging → support/debugging}/debug_cross_context.rb +0 -0
  214. /data/try/{debugging → support/debugging}/debug_database_load.rb +0 -0
  215. /data/try/{debugging → support/debugging}/debug_encrypted_json_check.rb +0 -0
  216. /data/try/{debugging → support/debugging}/debug_encrypted_json_step_by_step.rb +0 -0
  217. /data/try/{debugging → support/debugging}/debug_exists_lifecycle.rb +0 -0
  218. /data/try/{debugging → support/debugging}/debug_field_decrypt.rb +0 -0
  219. /data/try/{debugging → support/debugging}/debug_fresh_cross_context.rb +0 -0
  220. /data/try/{debugging → support/debugging}/debug_load_path.rb +0 -0
  221. /data/try/{debugging → support/debugging}/debug_method_definition.rb +0 -0
  222. /data/try/{debugging → support/debugging}/debug_method_resolution.rb +0 -0
  223. /data/try/{debugging → support/debugging}/debug_minimal.rb +0 -0
  224. /data/try/{debugging → support/debugging}/debug_provider.rb +0 -0
  225. /data/try/{debugging → support/debugging}/debug_secure_behavior.rb +0 -0
  226. /data/try/{debugging → support/debugging}/debug_string_class.rb +0 -0
  227. /data/try/{debugging → support/debugging}/debug_test.rb +0 -0
  228. /data/try/{debugging → support/debugging}/debug_test_design.rb +0 -0
  229. /data/try/{debugging → support/debugging}/encryption_method_tracer.rb +0 -0
  230. /data/try/{debugging → support/debugging}/provider_diagnostics.rb +0 -0
  231. /data/try/{helpers → support/helpers}/test_cleanup.rb +0 -0
  232. /data/try/{memory → support/memory}/memory_basic_test.rb +0 -0
  233. /data/try/{memory → support/memory}/memory_detailed_test.rb +0 -0
  234. /data/try/{memory → support/memory}/memory_search_for_string.rb +0 -0
  235. /data/try/{memory → support/memory}/test_actual_redactedstring_protection.rb +0 -0
  236. /data/try/{prototypes → support/prototypes}/atomic_saves_v1_context_proxy.rb +0 -0
  237. /data/try/{prototypes → support/prototypes}/atomic_saves_v2_connection_switching.rb +0 -0
  238. /data/try/{prototypes → support/prototypes}/atomic_saves_v3_connection_pool.rb +0 -0
  239. /data/try/{prototypes → support/prototypes}/atomic_saves_v4.rb +0 -0
  240. /data/try/{prototypes → support/prototypes}/lib/atomic_saves_v2_connection_switching_helpers.rb +0 -0
  241. /data/try/{prototypes → support/prototypes}/lib/atomic_saves_v3_connection_pool_helpers.rb +0 -0
  242. /data/try/{prototypes → support/prototypes}/pooling/README.md +0 -0
  243. /data/try/{prototypes → support/prototypes}/pooling/configurable_stress_test.rb +0 -0
  244. /data/try/{prototypes → support/prototypes}/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +0 -0
  245. /data/try/{prototypes → support/prototypes}/pooling/lib/connection_pool_metrics.rb +0 -0
  246. /data/try/{prototypes → support/prototypes}/pooling/lib/connection_pool_stress_test.rb +0 -0
  247. /data/try/{prototypes → support/prototypes}/pooling/lib/connection_pool_threading_models.rb +0 -0
  248. /data/try/{prototypes → support/prototypes}/pooling/lib/visualize_stress_results.rb +0 -0
  249. /data/try/{prototypes → support/prototypes}/pooling/pool_siege.rb +0 -0
  250. /data/try/{prototypes → support/prototypes}/pooling/run_stress_tests.rb +0 -0
@@ -1,6 +1,6 @@
1
1
  # try/features/transient_fields_integration_try.rb
2
2
 
3
- require_relative '../../helpers/test_helpers'
3
+ require_relative '../../support/helpers/test_helpers'
4
4
 
5
5
  class SecretService < Familia::Horreum
6
6
  feature :transient_fields
@@ -12,7 +12,7 @@
12
12
  # - Operation guards prevent unsafe scenarios before fiber issues arise
13
13
  # - Method aliases work correctly
14
14
 
15
- require_relative '../helpers/test_helpers'
15
+ require_relative '../../support/helpers/test_helpers'
16
16
 
17
17
  ## Transaction method works without previous_conn preservation
18
18
  customer = Customer.new(custid: 'tx_test')
@@ -8,7 +8,7 @@
8
8
  # - Fresh connections (provider/create) → safe for all operations
9
9
  # - Transaction connections → safe for reentrant transactions only
10
10
 
11
- require_relative '../helpers/test_helpers'
11
+ require_relative '../../support/helpers/test_helpers'
12
12
 
13
13
  ## FiberTransactionHandler constraints
14
14
  Familia::Connection::FiberTransactionHandler.allows_transaction
@@ -5,10 +5,10 @@
5
5
  # Tests for isolated database connections that don't interfere
6
6
  # with the cached connection pool or existing model connections.
7
7
 
8
- require_relative '../helpers/test_helpers'
8
+ require_relative '../../support/helpers/test_helpers'
9
9
 
10
10
  # Clean up any existing test data in all test databases
11
- (0..15).each do |db|
11
+ (0..2).each do |db|
12
12
  Familia.with_isolated_dbclient(db) do |client|
13
13
  client.flushdb
14
14
  end
@@ -143,7 +143,7 @@ result
143
143
  #=> "seven"
144
144
 
145
145
  ## isolated_dbclient with String URI argument
146
- client = Familia.isolated_dbclient("redis://localhost:6379/8")
146
+ client = Familia.isolated_dbclient("redis://localhost:2525/8")
147
147
  client.set("uri_test", "eight")
148
148
  result = client.get("uri_test")
149
149
  client.close
@@ -0,0 +1,87 @@
1
+ # try/integration/connection/middleware_reconnect_try.rb
2
+ #
3
+ # Tests for Familia.reconnect! method that refreshes connection pools
4
+ # with current middleware configuration
5
+
6
+ require_relative '../../support/helpers/test_helpers'
7
+ require 'connection_pool'
8
+
9
+ # Disable logging for cleaner test output
10
+ Familia.enable_database_logging = false
11
+
12
+ # Test model for middleware reconnection testing
13
+ class ReconnectTestUser < Familia::Horreum
14
+ identifier_field :user_id
15
+ field :user_id
16
+ field :name
17
+
18
+ def init
19
+ @user_id ||= SecureRandom.hex(4)
20
+ end
21
+ end
22
+
23
+ ## Test 5: Middleware re-registration flag is reset and re-set
24
+ Familia.enable_database_logging = true
25
+ Familia.instance_variable_set(:@middleware_registered, true)
26
+ Familia.reconnect!
27
+ was_registered = Familia.instance_variable_get(:@middleware_registered)
28
+ was_registered
29
+ #=> true
30
+
31
+ ## Test 6: reconnect! safely handles no middleware enabled
32
+ Familia.enable_database_logging = false
33
+ Familia.enable_database_counter = false
34
+ Familia.reconnect!
35
+ chain_cleared = Familia.instance_variable_get(:@connection_chain).nil?
36
+ chain_cleared
37
+ #=> true
38
+
39
+
40
+
41
+ ## Setup: Clean database
42
+ ReconnectTestUser.dbclient.flushdb
43
+ #=> "OK"
44
+
45
+ ## Test 1: Basic reconnect functionality clears chain and increments version
46
+ Familia.enable_database_logging = true
47
+ initial = Familia.middleware_version
48
+ Familia.reconnect!
49
+ chain_cleared = Familia.instance_variable_get(:@connection_chain).nil?
50
+ version_incremented = Familia.middleware_version > initial
51
+ [chain_cleared, version_incremented]
52
+ #=> [true, true]
53
+
54
+ ## Test 2: Reconnect works with connection providers
55
+
56
+ # Create a simple connection provider
57
+ Familia.connection_provider = ->(uri) { Redis.new(url: uri) }
58
+
59
+ ## Reconnect clears chain even with provider
60
+ Familia.reconnect!
61
+ Familia.instance_variable_get(:@connection_chain)
62
+ #=> nil
63
+
64
+ ## Test 3: Verify new connections work after reconnect
65
+
66
+ # Create user to trigger connection
67
+ @user = ReconnectTestUser.new(name: "Bob")
68
+ @user.save
69
+ #=> true
70
+
71
+ ## User should be retrievable
72
+ @retrieved = ReconnectTestUser.find(@user.identifier)
73
+ @retrieved.name
74
+ #=> "Bob"
75
+
76
+ ## Test 4: Multiple reconnects are safe
77
+ Familia.reconnect!
78
+ Familia.reconnect!
79
+ Familia.reconnect!
80
+
81
+ ## Connection chain should still be cleared (will rebuild on next use)
82
+ Familia.instance_variable_get(:@connection_chain)
83
+ #=> nil
84
+
85
+ ## Cleanup
86
+ Familia.enable_database_logging = false
87
+ Familia.connection_provider = nil
@@ -12,7 +12,7 @@
12
12
  # This prevents bugs where middleware/cached connections return "QUEUED" instead
13
13
  # of actual values, breaking conditional logic and business rules.
14
14
 
15
- require_relative '../helpers/test_helpers'
15
+ require_relative '../../support/helpers/test_helpers'
16
16
 
17
17
  ## FiberConnectionHandler blocks transactions in strict mode
18
18
  begin
@@ -4,7 +4,7 @@
4
4
  # and that the fallback behavior matches transaction fallback patterns.
5
5
  #
6
6
 
7
- require_relative '../helpers/test_helpers'
7
+ require_relative '../../support/helpers/test_helpers'
8
8
 
9
9
  # Store original values
10
10
  $original_pipeline_mode = Familia.pipeline_mode
@@ -5,7 +5,7 @@
5
5
  require 'bundler/setup'
6
6
  require 'securerandom'
7
7
  require 'thread'
8
- require_relative '../helpers/test_helpers'
8
+ require_relative '../../support/helpers/test_helpers'
9
9
 
10
10
  # Configure connection pooling via connection_provider
11
11
  require 'connection_pool'
@@ -10,7 +10,7 @@
10
10
  # - Return the connection from the successful handler
11
11
  # - Return nil if no handler provides a connection
12
12
 
13
- require_relative '../helpers/test_helpers'
13
+ require_relative '../../support/helpers/test_helpers'
14
14
 
15
15
  # Setup - clear any existing fiber state
16
16
  Fiber[:familia_connection_handler_class] = nil
@@ -8,7 +8,7 @@
8
8
  # with Familia's existing features when connection handlers don't support
9
9
  # transactions (e.g., cached connections, middleware connections).
10
10
 
11
- require_relative '../helpers/test_helpers'
11
+ require_relative '../../support/helpers/test_helpers'
12
12
 
13
13
  # Setup - store original values
14
14
  $original_transaction_mode = Familia.transaction_mode
@@ -5,7 +5,7 @@
5
5
  #
6
6
  # Permissive mode: Silently uses IndividualCommandProxy for fallback
7
7
 
8
- require_relative '../helpers/test_helpers'
8
+ require_relative '../../support/helpers/test_helpers'
9
9
 
10
10
  # Test class for permissive mode testing
11
11
  class PermissiveModeTestCustomer < Familia::Horreum
@@ -5,7 +5,7 @@
5
5
  #
6
6
  # Strict mode: Raises OperationModeError when transaction unavailable
7
7
 
8
- require_relative '../helpers/test_helpers'
8
+ require_relative '../../support/helpers/test_helpers'
9
9
 
10
10
  # Test class for strict mode testing
11
11
  class StrictModeTestCustomer < Familia::Horreum
@@ -5,7 +5,7 @@
5
5
  #
6
6
  # Warn mode: Logs warning and uses IndividualCommandProxy for fallback
7
7
 
8
- require_relative '../helpers/test_helpers'
8
+ require_relative '../../support/helpers/test_helpers'
9
9
 
10
10
  # Test class for warn mode testing
11
11
  class WarnModeTestCustomer < Familia::Horreum
@@ -10,7 +10,7 @@
10
10
  # The IndividualCommandProxy executes Redis commands immediately instead of queuing
11
11
  # them in a transaction, maintaining the same MultiResult interface for consistency.
12
12
 
13
- require_relative '../helpers/test_helpers'
13
+ require_relative '../../support/helpers/test_helpers'
14
14
 
15
15
  # Setup - ensure clean state
16
16
  @original_transaction_mode = Familia.transaction_mode
@@ -1,4 +1,4 @@
1
- require_relative '../helpers/test_helpers'
1
+ require_relative '../support/helpers/test_helpers'
2
2
 
3
3
  # Define test classes in global namespace
4
4
  class ::TestVehicle < Familia::Horreum
@@ -3,7 +3,7 @@
3
3
  # Comprehensive test coverage for the create method
4
4
  # Tests the correct exception type and error message handling
5
5
 
6
- require_relative '../helpers/test_helpers'
6
+ require_relative '../support/helpers/test_helpers'
7
7
 
8
8
  # Test class for create method behavior
9
9
  class CreateTestModel < Familia::Horreum
@@ -1,6 +1,6 @@
1
1
  # Test cross-component integration scenarios
2
2
 
3
- require_relative '../helpers/test_helpers'
3
+ require_relative '../support/helpers/test_helpers'
4
4
 
5
5
  class TestUser < Familia::Horreum
6
6
  using Familia::Refinements::StylizeWords
@@ -3,7 +3,7 @@
3
3
  # Database consistency verification and edge case testing
4
4
  # Complements persistence_operations_try.rb with deeper consistency checks
5
5
 
6
- require_relative '../helpers/test_helpers'
6
+ require_relative '../support/helpers/test_helpers'
7
7
 
8
8
  # Test class with different field types for consistency verification
9
9
  class ConsistencyTestModel < Familia::Horreum
@@ -55,15 +55,18 @@ key_parts = dbkey.split(':')
55
55
  # Refresh and verify data integrity
56
56
  @serial_test.refresh!
57
57
  [@serial_test.name, @serial_test.active, @serial_test.metadata]
58
- #=> ['Serialization Test', 'true', {:key=>'value', :array=>[1, 2, 3]}]
58
+ #=> ["Serialization Test", true, {"key"=>"value", "array"=>[1, 2, 3]}]
59
59
 
60
60
  ## Hash field count matches object field count
61
+ @serial_test = ConsistencyTestModel.new(id: next_test_id)
62
+ @serial_test.save
61
63
  expected_fields = @serial_test.class.persistent_fields.length
62
64
  redis_field_count = Familia.dbclient.hlen(@serial_test.dbkey)
63
65
  actual_object_fields = @serial_test.to_h.keys.length
64
- # All should match (redis may have fewer due to nil exclusion)
65
- [expected_fields >= redis_field_count, redis_field_count, actual_object_fields]
66
- #=> [true, 5, 5]
66
+ # The JSON Serializer stores all fields (including nil as "null")
67
+ # Expected fields (5) >= redis count (5) >= to_h count (5, even though email is nil)
68
+ [expected_fields, redis_field_count, actual_object_fields]
69
+ #=> [5, 5, 5]
67
70
 
68
71
  ## Memory vs persistence state consistency after save
69
72
  @consistency_obj = ConsistencyTestModel.new(id: next_test_id, name: 'Memory Test', email: 'test@example.com')
@@ -73,9 +76,9 @@ actual_object_fields = @serial_test.to_h.keys.length
73
76
  memory_name = @consistency_obj.name
74
77
  memory_email = @consistency_obj.email
75
78
 
76
- # Get persistence state
77
- redis_name = Familia.dbclient.hget(@consistency_obj.dbkey, 'name')
78
- redis_email = Familia.dbclient.hget(@consistency_obj.dbkey, 'email')
79
+ # Get persistence state (deserialize from JSON storage)
80
+ redis_name = @consistency_obj.deserialize_value(Familia.dbclient.hget(@consistency_obj.dbkey, 'name'))
81
+ redis_email = @consistency_obj.deserialize_value(Familia.dbclient.hget(@consistency_obj.dbkey, 'email'))
79
82
 
80
83
  [memory_name == redis_name, memory_email == redis_email]
81
84
  #=> [true, true]
@@ -214,6 +217,7 @@ exists_after_batch = @batch_obj.exists?
214
217
 
215
218
  ## Transient fields don't affect exists? behavior
216
219
  class TransientConsistencyTest < Familia::Horreum
220
+ feature :transient_fields
217
221
  identifier_field :id
218
222
  field :id
219
223
  field :name
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'time'
4
4
 
5
- require_relative '../helpers/test_helpers'
5
+ require_relative '../support/helpers/test_helpers'
6
6
 
7
7
  ## Has all datatype relativess
8
8
  registered_types = Familia::DataType.registered_types.keys
@@ -1,6 +1,6 @@
1
1
  # try/core/familia_members_methods_try.rb
2
2
 
3
- require_relative '../helpers/test_helpers'
3
+ require_relative '../support/helpers/test_helpers'
4
4
 
5
5
  # Tests for new methods: demodularize, familia_name, and resolve_class
6
6
 
@@ -1,6 +1,6 @@
1
1
  # try/models/customer_safedump_try.rb
2
2
 
3
- require_relative '../helpers/test_helpers'
3
+ require_relative '../../support/helpers/test_helpers'
4
4
 
5
5
  # Setup
6
6
  @now = Familia.now.to_i
@@ -1,7 +1,7 @@
1
1
  # try/models/customer_try.rb
2
2
 
3
3
  # Customer Tryouts
4
- require_relative '../helpers/test_helpers'
4
+ require_relative '../../support/helpers/test_helpers'
5
5
 
6
6
  # Setup
7
7
  @now = Time.now.to_f
@@ -103,15 +103,15 @@ exists = Customer.exists?('test@example.com')
103
103
 
104
104
  ## Customer.logical_database returns the correct database number
105
105
  Customer.logical_database
106
- #=> 15
106
+ #=> 3
107
107
 
108
108
  ## Customer.logical_database returns the correct database number
109
109
  @customer.logical_database
110
- #=> 15
110
+ #=> 3
111
111
 
112
112
  ## @customer.dbclient.connection returns the correct database URI
113
113
  @customer.dbclient.connection
114
- #=> {:host=>"127.0.0.1", :port=>6379, :db=>15, :id=>"redis://127.0.0.1:6379/15", :location=>"127.0.0.1:6379"}
114
+ #=> {:host=>"127.0.0.1", :port=>2525, :db=>3, :id=>"redis://127.0.0.1:2525/3", :location=>"127.0.0.1:2525"}
115
115
 
116
116
  ## @customer.dbclient.uri returns the correct database URI
117
117
  @customer.secrets_created.logical_database
@@ -119,7 +119,7 @@ Customer.logical_database
119
119
 
120
120
  ## @customer.dbclient.uri returns the correct database URI
121
121
  @customer.secrets_created.dbclient.connection
122
- #=> {:host=>"127.0.0.1", :port=>6379, :db=>15, :id=>"redis://127.0.0.1:6379/15", :location=>"127.0.0.1:6379"}
122
+ #=> {:host=>"127.0.0.1", :port=>2525, :db=>3, :id=>"redis://127.0.0.1:2525/3", :location=>"127.0.0.1:2525"}
123
123
 
124
124
  ## Customer.url is nil by default
125
125
  Customer.uri
@@ -131,7 +131,7 @@ Customer.instances.logical_database
131
131
 
132
132
  ## Customer.logical_database returns the correct database number
133
133
  Customer.instances.uri.to_s
134
- #=> 'redis://127.0.0.1/15'
134
+ #=> 'redis://127.0.0.1/3'
135
135
 
136
136
  # Teardown
137
137
  Customer.instances.delete!
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Test DataType base functionality
4
4
 
5
- require_relative '../helpers/test_helpers'
5
+ require_relative '../../support/helpers/test_helpers'
6
6
 
7
7
  Familia.debug = false
8
8
 
@@ -1,6 +1,6 @@
1
1
  # try/models/familia_object_try.rb
2
2
 
3
- require_relative '../helpers/test_helpers'
3
+ require_relative '../../support/helpers/test_helpers'
4
4
 
5
5
  Familia.debug = false
6
6
 
@@ -3,7 +3,7 @@
3
3
  # Comprehensive test coverage for core persistence methods: exists?, save, save_if_not_exists, create
4
4
  # This test addresses gaps that allowed the exists? bug to go undetected
5
5
 
6
- require_relative '../helpers/test_helpers'
6
+ require_relative '../support/helpers/test_helpers'
7
7
 
8
8
  # Use a simple test class to isolate persistence behavior
9
9
  class PersistenceTestModel < Familia::Horreum