familia 2.0.0.pre15 → 2.0.0.pre17

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 (288) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +2 -2
  3. data/.github/workflows/code-quality.yml +138 -0
  4. data/.github/workflows/code-smells.yml +85 -0
  5. data/.github/workflows/docs.yml +31 -8
  6. data/.gitignore +3 -1
  7. data/.pre-commit-config.yaml +7 -1
  8. data/.reek.yml +98 -0
  9. data/.rubocop.yml +54 -10
  10. data/.talismanrc +9 -0
  11. data/.yardopts +18 -13
  12. data/CHANGELOG.rst +86 -4
  13. data/CLAUDE.md +39 -1
  14. data/Gemfile +6 -5
  15. data/Gemfile.lock +99 -23
  16. data/LICENSE.txt +1 -1
  17. data/README.md +285 -85
  18. data/changelog.d/README.md +2 -2
  19. data/docs/archive/FAMILIA_RELATIONSHIPS.md +22 -22
  20. data/docs/archive/FAMILIA_TECHNICAL.md +42 -42
  21. data/docs/archive/FAMILIA_UPDATE.md +3 -3
  22. data/docs/archive/README.md +3 -2
  23. data/docs/{guides/API-Reference.md → archive/api-reference.md} +87 -101
  24. data/docs/conf.py +29 -0
  25. data/docs/guides/{Field-System-Guide.md → core-field-system.md} +9 -9
  26. data/docs/guides/feature-encrypted-fields.md +785 -0
  27. data/docs/guides/{Expiration-Feature-Guide.md → feature-expiration.md} +11 -2
  28. data/docs/guides/feature-external-identifiers.md +637 -0
  29. data/docs/guides/feature-object-identifiers.md +435 -0
  30. data/docs/guides/{Quantization-Feature-Guide.md → feature-quantization.md} +94 -29
  31. data/docs/guides/feature-relationships-methods.md +684 -0
  32. data/docs/guides/feature-relationships.md +200 -0
  33. data/docs/guides/{Features-System-Developer-Guide.md → feature-system-devs.md} +4 -4
  34. data/docs/guides/{Feature-System-Guide.md → feature-system.md} +5 -5
  35. data/docs/guides/{Transient-Fields-Guide.md → feature-transient-fields.md} +2 -2
  36. data/docs/guides/{Implementation-Guide.md → implementation.md} +3 -3
  37. data/docs/guides/index.md +176 -0
  38. data/docs/guides/{Security-Model.md → security-model.md} +1 -1
  39. data/docs/migrating/v2.0.0-pre.md +1 -1
  40. data/docs/migrating/v2.0.0-pre11.md +2 -2
  41. data/docs/migrating/v2.0.0-pre12.md +2 -2
  42. data/docs/migrating/v2.0.0-pre5.md +33 -12
  43. data/docs/migrating/v2.0.0-pre6.md +2 -2
  44. data/docs/migrating/v2.0.0-pre7.md +8 -8
  45. data/docs/overview.md +624 -20
  46. data/docs/reference/api-technical.md +1365 -0
  47. data/examples/autoloader/mega_customer/features/deprecated_fields.rb +7 -0
  48. data/examples/autoloader/mega_customer/safe_dump_fields.rb +1 -1
  49. data/examples/autoloader/mega_customer.rb +3 -1
  50. data/examples/encrypted_fields.rb +378 -0
  51. data/examples/json_usage_patterns.rb +144 -0
  52. data/examples/relationships.rb +13 -13
  53. data/examples/safe_dump.rb +7 -7
  54. data/examples/single_connection_transaction_confusions.rb +379 -0
  55. data/lib/familia/base.rb +51 -10
  56. data/lib/familia/connection/handlers.rb +223 -0
  57. data/lib/familia/connection/individual_command_proxy.rb +64 -0
  58. data/lib/familia/connection/middleware.rb +75 -0
  59. data/lib/familia/connection/operation_core.rb +93 -0
  60. data/lib/familia/connection/operations.rb +277 -0
  61. data/lib/familia/connection/pipeline_core.rb +87 -0
  62. data/lib/familia/connection/transaction_core.rb +100 -0
  63. data/lib/familia/connection.rb +60 -186
  64. data/lib/familia/data_type/class_methods.rb +63 -0
  65. data/lib/familia/data_type/commands.rb +53 -51
  66. data/lib/familia/data_type/connection.rb +83 -0
  67. data/lib/familia/data_type/serialization.rb +108 -107
  68. data/lib/familia/data_type/settings.rb +96 -0
  69. data/lib/familia/data_type/types/counter.rb +1 -1
  70. data/lib/familia/data_type/types/hashkey.rb +15 -11
  71. data/lib/familia/data_type/types/{list.rb → listkey.rb} +13 -5
  72. data/lib/familia/data_type/types/lock.rb +3 -2
  73. data/lib/familia/data_type/types/sorted_set.rb +128 -14
  74. data/lib/familia/data_type/types/{string.rb → stringkey.rb} +7 -9
  75. data/lib/familia/data_type/types/unsorted_set.rb +20 -27
  76. data/lib/familia/data_type.rb +12 -171
  77. data/lib/familia/distinguisher.rb +85 -0
  78. data/lib/familia/encryption/encrypted_data.rb +15 -24
  79. data/lib/familia/encryption/manager.rb +6 -4
  80. data/lib/familia/encryption/providers/aes_gcm_provider.rb +1 -1
  81. data/lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb +7 -9
  82. data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +4 -5
  83. data/lib/familia/encryption/request_cache.rb +7 -7
  84. data/lib/familia/encryption.rb +2 -3
  85. data/lib/familia/errors.rb +9 -3
  86. data/lib/familia/features/autoloader.rb +30 -12
  87. data/lib/familia/features/encrypted_fields/concealed_string.rb +3 -4
  88. data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +13 -14
  89. data/lib/familia/features/encrypted_fields.rb +71 -66
  90. data/lib/familia/features/expiration/extensions.rb +1 -1
  91. data/lib/familia/features/expiration.rb +31 -26
  92. data/lib/familia/features/external_identifier.rb +57 -19
  93. data/lib/familia/features/object_identifier.rb +134 -25
  94. data/lib/familia/features/quantization.rb +16 -21
  95. data/lib/familia/features/relationships/README.md +97 -0
  96. data/lib/familia/features/relationships/collection_operations.rb +104 -0
  97. data/lib/familia/features/relationships/indexing/multi_index_generators.rb +202 -0
  98. data/lib/familia/features/relationships/indexing/unique_index_generators.rb +306 -0
  99. data/lib/familia/features/relationships/indexing.rb +182 -256
  100. data/lib/familia/features/relationships/indexing_relationship.rb +35 -0
  101. data/lib/familia/features/relationships/participation/participant_methods.rb +164 -0
  102. data/lib/familia/features/relationships/participation/target_methods.rb +225 -0
  103. data/lib/familia/features/relationships/participation.rb +656 -0
  104. data/lib/familia/features/relationships/participation_relationship.rb +31 -0
  105. data/lib/familia/features/relationships/score_encoding.rb +20 -20
  106. data/lib/familia/features/relationships.rb +65 -266
  107. data/lib/familia/features/safe_dump.rb +127 -130
  108. data/lib/familia/features/transient_fields/redacted_string.rb +6 -6
  109. data/lib/familia/features/transient_fields/transient_field_type.rb +5 -5
  110. data/lib/familia/features/transient_fields.rb +10 -7
  111. data/lib/familia/features.rb +10 -14
  112. data/lib/familia/field_type.rb +6 -4
  113. data/lib/familia/horreum/connection.rb +297 -0
  114. data/lib/familia/horreum/{core/database_commands.rb → database_commands.rb} +27 -17
  115. data/lib/familia/horreum/{subclass/definition.rb → definition.rb} +139 -74
  116. data/lib/familia/horreum/{subclass/management.rb → management.rb} +73 -27
  117. data/lib/familia/horreum/{core/serialization.rb → persistence.rb} +108 -185
  118. data/lib/familia/horreum/{subclass/related_fields_management.rb → related_fields.rb} +104 -23
  119. data/lib/familia/horreum/serialization.rb +172 -0
  120. data/lib/familia/horreum/{shared/settings.rb → settings.rb} +2 -1
  121. data/lib/familia/horreum/{core/utils.rb → utils.rb} +2 -1
  122. data/lib/familia/horreum.rb +222 -119
  123. data/lib/familia/json_serializer.rb +0 -1
  124. data/lib/familia/logging.rb +11 -114
  125. data/lib/familia/refinements/dear_json.rb +122 -0
  126. data/lib/familia/refinements/logger_trace.rb +20 -17
  127. data/lib/familia/refinements/stylize_words.rb +65 -0
  128. data/lib/familia/refinements/time_literals.rb +60 -52
  129. data/lib/familia/refinements.rb +2 -1
  130. data/lib/familia/secure_identifier.rb +60 -28
  131. data/lib/familia/settings.rb +83 -7
  132. data/lib/familia/utils.rb +5 -87
  133. data/lib/familia/verifiable_identifier.rb +4 -4
  134. data/lib/familia/version.rb +1 -1
  135. data/lib/familia.rb +72 -14
  136. data/lib/middleware/database_middleware.rb +56 -14
  137. data/lib/{familia/multi_result.rb → multi_result.rb} +23 -16
  138. data/try/configuration/scenarios_try.rb +2 -2
  139. data/try/connection/fiber_context_preservation_try.rb +250 -0
  140. data/try/connection/handler_constraints_try.rb +59 -0
  141. data/try/connection/operation_mode_guards_try.rb +208 -0
  142. data/try/connection/pipeline_fallback_integration_try.rb +128 -0
  143. data/try/connection/responsibility_chain_tracking_try.rb +72 -0
  144. data/try/connection/transaction_fallback_integration_try.rb +288 -0
  145. data/try/connection/transaction_mode_permissive_try.rb +153 -0
  146. data/try/connection/transaction_mode_strict_try.rb +98 -0
  147. data/try/connection/transaction_mode_warn_try.rb +131 -0
  148. data/try/connection/transaction_modes_try.rb +249 -0
  149. data/try/core/autoloader_try.rb +120 -2
  150. data/try/core/connection_try.rb +10 -10
  151. data/try/core/conventional_inheritance_try.rb +130 -0
  152. data/try/core/create_method_try.rb +15 -23
  153. data/try/core/database_consistency_try.rb +11 -10
  154. data/try/core/errors_try.rb +11 -14
  155. data/try/core/familia_extended_try.rb +2 -2
  156. data/try/core/familia_members_methods_try.rb +76 -0
  157. data/try/core/familia_try.rb +1 -1
  158. data/try/core/isolated_dbclient_try.rb +165 -0
  159. data/try/core/middleware_try.rb +16 -16
  160. data/try/core/persistence_operations_try.rb +4 -4
  161. data/try/core/pools_try.rb +42 -26
  162. data/try/core/secure_identifier_try.rb +28 -24
  163. data/try/core/time_utils_try.rb +10 -10
  164. data/try/core/tools_try.rb +3 -3
  165. data/try/core/utils_try.rb +2 -2
  166. data/try/data_types/boolean_try.rb +4 -4
  167. data/try/data_types/datatype_base_try.rb +0 -2
  168. data/try/data_types/list_try.rb +10 -10
  169. data/try/data_types/sorted_set_try.rb +5 -5
  170. data/try/data_types/sorted_set_zadd_options_try.rb +625 -0
  171. data/try/data_types/string_try.rb +12 -12
  172. data/try/data_types/unsortedset_try.rb +33 -0
  173. data/try/debugging/cache_behavior_tracer.rb +7 -7
  174. data/try/debugging/debug_aad_process.rb +1 -1
  175. data/try/debugging/debug_concealed_internal.rb +1 -1
  176. data/try/debugging/debug_cross_context.rb +1 -1
  177. data/try/debugging/debug_fresh_cross_context.rb +1 -1
  178. data/try/debugging/encryption_method_tracer.rb +10 -10
  179. data/try/edge_cases/hash_symbolization_try.rb +1 -1
  180. data/try/edge_cases/ttl_side_effects_try.rb +1 -1
  181. data/try/encryption/config_persistence_try.rb +2 -2
  182. data/try/encryption/encryption_core_try.rb +19 -19
  183. data/try/encryption/instance_variable_scope_try.rb +1 -1
  184. data/try/encryption/module_loading_try.rb +2 -2
  185. data/try/encryption/providers/aes_gcm_provider_try.rb +1 -1
  186. data/try/encryption/providers/xchacha20_poly1305_provider_try.rb +1 -1
  187. data/try/encryption/secure_memory_handling_try.rb +1 -1
  188. data/try/features/encrypted_fields/concealed_string_core_try.rb +11 -7
  189. data/try/features/encrypted_fields/encrypted_fields_core_try.rb +1 -1
  190. data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +3 -3
  191. data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +10 -10
  192. data/try/features/encrypted_fields/encrypted_fields_security_try.rb +14 -14
  193. data/try/features/encrypted_fields/error_conditions_try.rb +7 -7
  194. data/try/features/encrypted_fields/fresh_key_try.rb +1 -1
  195. data/try/features/encrypted_fields/nonce_uniqueness_try.rb +1 -1
  196. data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +7 -7
  197. data/try/features/encrypted_fields/universal_serialization_safety_try.rb +13 -20
  198. data/try/features/external_identifier/external_identifier_try.rb +1 -1
  199. data/try/features/feature_dependencies_try.rb +3 -3
  200. data/try/features/field_groups_try.rb +244 -0
  201. data/try/features/object_identifier/object_identifier_integration_try.rb +28 -34
  202. data/try/features/object_identifier/object_identifier_try.rb +10 -0
  203. data/try/features/quantization/quantization_try.rb +1 -1
  204. data/try/features/relationships/indexing_commands_verification_try.rb +136 -0
  205. data/try/features/relationships/indexing_try.rb +443 -0
  206. data/try/features/relationships/participation_commands_verification_spec.rb +102 -0
  207. data/try/features/relationships/participation_commands_verification_try.rb +105 -0
  208. data/try/features/relationships/participation_performance_improvements_try.rb +124 -0
  209. data/try/features/relationships/participation_reverse_index_try.rb +196 -0
  210. data/try/features/relationships/relationships_api_changes_try.rb +72 -71
  211. data/try/features/relationships/relationships_edge_cases_try.rb +15 -18
  212. data/try/features/relationships/relationships_performance_minimal_try.rb +2 -2
  213. data/try/features/relationships/relationships_performance_simple_try.rb +8 -8
  214. data/try/features/relationships/relationships_performance_try.rb +20 -20
  215. data/try/features/relationships/relationships_try.rb +27 -38
  216. data/try/features/safe_dump/safe_dump_advanced_try.rb +2 -2
  217. data/try/features/transient_fields/refresh_reset_try.rb +3 -1
  218. data/try/features/transient_fields/simple_refresh_test.rb +1 -1
  219. data/try/helpers/test_cleanup.rb +86 -0
  220. data/try/helpers/test_helpers.rb +6 -7
  221. data/try/horreum/auto_indexing_on_save_try.rb +212 -0
  222. data/try/horreum/base_try.rb +3 -2
  223. data/try/horreum/commands_try.rb +3 -1
  224. data/try/horreum/defensive_initialization_try.rb +86 -0
  225. data/try/horreum/destroy_related_fields_cleanup_try.rb +332 -0
  226. data/try/horreum/initialization_try.rb +11 -7
  227. data/try/horreum/relations_try.rb +21 -13
  228. data/try/horreum/serialization_try.rb +12 -11
  229. data/try/horreum/settings_try.rb +2 -0
  230. data/try/integration/cross_component_try.rb +3 -3
  231. data/try/memory/memory_basic_test.rb +1 -1
  232. data/try/memory/memory_docker_ruby_dump.sh +2 -2
  233. data/try/models/customer_safe_dump_try.rb +1 -1
  234. data/try/models/customer_try.rb +13 -15
  235. data/try/models/datatype_base_try.rb +3 -3
  236. data/try/models/familia_object_try.rb +9 -8
  237. data/try/performance/benchmarks_try.rb +2 -2
  238. data/try/prototypes/atomic_saves_v1_context_proxy.rb +2 -2
  239. data/try/prototypes/atomic_saves_v3_connection_pool.rb +3 -3
  240. data/try/prototypes/atomic_saves_v4.rb +1 -1
  241. data/try/prototypes/lib/atomic_saves_v2_connection_switching_helpers.rb +4 -4
  242. data/try/prototypes/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -4
  243. data/try/prototypes/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -4
  244. data/try/prototypes/pooling/lib/connection_pool_metrics.rb +5 -5
  245. data/try/prototypes/pooling/lib/connection_pool_stress_test.rb +26 -26
  246. data/try/prototypes/pooling/lib/connection_pool_threading_models.rb +7 -7
  247. data/try/prototypes/pooling/lib/visualize_stress_results.rb +1 -1
  248. data/try/prototypes/pooling/pool_siege.rb +11 -11
  249. data/try/prototypes/pooling/run_stress_tests.rb +7 -7
  250. data/try/refinements/dear_json_array_methods_try.rb +53 -0
  251. data/try/refinements/dear_json_hash_methods_try.rb +54 -0
  252. data/try/refinements/logger_trace_methods_try.rb +44 -0
  253. data/try/refinements/time_literals_numeric_methods_try.rb +141 -0
  254. data/try/refinements/time_literals_string_methods_try.rb +80 -0
  255. data/try/valkey.conf +26 -0
  256. metadata +92 -52
  257. data/.rubocop_todo.yml +0 -208
  258. data/docs/connection_pooling.md +0 -192
  259. data/docs/guides/Connection-Pooling-Guide.md +0 -437
  260. data/docs/guides/Encrypted-Fields-Overview.md +0 -101
  261. data/docs/guides/Feature-System-Autoloading.md +0 -198
  262. data/docs/guides/Home.md +0 -116
  263. data/docs/guides/Relationships-Guide.md +0 -737
  264. data/docs/guides/relationships-methods.md +0 -266
  265. data/docs/reference/auditing_database_commands.rb +0 -228
  266. data/examples/permissions.rb +0 -240
  267. data/lib/familia/features/relationships/cascading.rb +0 -437
  268. data/lib/familia/features/relationships/membership.rb +0 -497
  269. data/lib/familia/features/relationships/permission_management.rb +0 -264
  270. data/lib/familia/features/relationships/querying.rb +0 -615
  271. data/lib/familia/features/relationships/redis_operations.rb +0 -274
  272. data/lib/familia/features/relationships/tracking.rb +0 -418
  273. data/lib/familia/horreum/core/connection.rb +0 -73
  274. data/lib/familia/horreum/core.rb +0 -21
  275. data/lib/familia/refinements/snake_case.rb +0 -40
  276. data/lib/familia/validation/command_recorder.rb +0 -336
  277. data/lib/familia/validation/expectations.rb +0 -519
  278. data/lib/familia/validation/validation_helpers.rb +0 -443
  279. data/lib/familia/validation/validator.rb +0 -412
  280. data/lib/familia/validation.rb +0 -140
  281. data/try/data_types/set_try.rb +0 -33
  282. data/try/features/relationships/categorical_permissions_try.rb +0 -515
  283. data/try/features/safe_dump/module_based_extensions_try.rb +0 -100
  284. data/try/features/safe_dump/safe_dump_autoloading_try.rb +0 -107
  285. data/try/validation/atomic_operations_try.rb.disabled +0 -320
  286. data/try/validation/command_validation_try.rb.disabled +0 -207
  287. data/try/validation/performance_validation_try.rb.disabled +0 -324
  288. data/try/validation/real_world_scenarios_try.rb.disabled +0 -390
@@ -0,0 +1,53 @@
1
+ # try/refinements/dear_json_array_methods_try.rb
2
+
3
+ require_relative '../helpers/test_helpers'
4
+
5
+ class TestArrayWithDearJson < Array
6
+ include Familia::Refinements::DearJsonArrayMethods
7
+ end
8
+
9
+ class TestObjectWithAsJson
10
+ def initialize(name)
11
+ @name = name
12
+ end
13
+
14
+ def as_json(options = nil)
15
+ { name: @name, type: 'test_object' }
16
+ end
17
+ end
18
+
19
+ ## Can create an array with DearJson methods
20
+ test_array = TestArrayWithDearJson.new
21
+ test_array << 'value'
22
+ test_array.respond_to?(:to_json)
23
+ #=> true
24
+
25
+ ## to_json converts array to JSON string using JsonSerializer
26
+ test_array = TestArrayWithDearJson.new
27
+ test_array << 'simple'
28
+ test_array << 42
29
+ json_result = test_array.to_json
30
+ json_result
31
+ #=:> String
32
+
33
+ ## to_json handles objects with as_json methods
34
+ test_array = TestArrayWithDearJson.new
35
+ test_obj = TestObjectWithAsJson.new('test')
36
+ test_array << test_obj
37
+ test_array << 'simple'
38
+ json_result = test_array.to_json
39
+ #=~> /test_object/
40
+
41
+ ## as_json returns the array itself
42
+ test_array = TestArrayWithDearJson.new
43
+ test_array << 'value'
44
+ result = test_array.as_json
45
+ result == test_array
46
+ #=> true
47
+
48
+ ## as_json accepts options parameter
49
+ test_array = TestArrayWithDearJson.new
50
+ test_array << 'value'
51
+ result = test_array.as_json(some_option: true)
52
+ result == test_array
53
+ #=> true
@@ -0,0 +1,54 @@
1
+ # try/refinements/dear_json_hash_methods_try.rb
2
+
3
+ require_relative '../helpers/test_helpers'
4
+
5
+ class TestHashWithDearJson < Hash
6
+ include Familia::Refinements::DearJsonHashMethods
7
+ end
8
+
9
+ class TestObjectWithAsJson
10
+ def initialize(name)
11
+ @name = name
12
+ end
13
+
14
+ def as_json(options = nil)
15
+ { name: @name, type: 'test_object' }
16
+ end
17
+ end
18
+
19
+ ## Can create a hash with DearJson methods
20
+ test_hash = TestHashWithDearJson.new
21
+ test_hash[:key] = 'value'
22
+ test_hash.respond_to?(:to_json)
23
+ #=> true
24
+
25
+ ## to_json converts hash to JSON string using JsonSerializer
26
+ test_hash = TestHashWithDearJson.new
27
+ test_hash[:simple] = 'value'
28
+ test_hash[:number] = 42
29
+ json_result = test_hash.to_json
30
+ json_result
31
+ #=:> String
32
+
33
+ ## to_json handles objects with as_json methods
34
+ test_hash = TestHashWithDearJson.new
35
+ test_obj = TestObjectWithAsJson.new('test')
36
+ test_hash[:object] = test_obj
37
+ test_hash[:simple] = 'value'
38
+ json_result = test_hash.to_json
39
+ json_result
40
+ #=~> /test_object/
41
+
42
+ ## as_json returns the hash itself
43
+ test_hash = TestHashWithDearJson.new
44
+ test_hash[:key] = 'value'
45
+ result = test_hash.as_json
46
+ result == test_hash
47
+ #=> true
48
+
49
+ ## as_json accepts options parameter
50
+ test_hash = TestHashWithDearJson.new
51
+ test_hash[:key] = 'value'
52
+ result = test_hash.as_json(some_option: true)
53
+ result == test_hash
54
+ #=> true
@@ -0,0 +1,44 @@
1
+ # try/refinements/logger_trace_methods_try.rb
2
+
3
+ require_relative '../helpers/test_helpers'
4
+ require 'logger'
5
+ require 'stringio'
6
+
7
+ class TestLoggerWithTrace < Logger
8
+ include Familia::Refinements::LoggerTraceMethods
9
+ end
10
+
11
+ ## Can create a logger with trace methods
12
+ output = StringIO.new
13
+ logger = TestLoggerWithTrace.new(output)
14
+ logger.respond_to?(:trace)
15
+ #=> true
16
+
17
+ ## trace method logs with TRACE level
18
+ output = StringIO.new
19
+ logger = TestLoggerWithTrace.new(output)
20
+ logger.trace('Test message')
21
+ output.string
22
+ #=~> /Test message/
23
+
24
+ ## trace method sets and clears severity letter
25
+ output = StringIO.new
26
+ logger = TestLoggerWithTrace.new(output)
27
+ logger.trace('Test message')
28
+ Fiber[:severity_letter]
29
+ #=> nil
30
+
31
+ ## trace method accepts progname parameter
32
+ output = StringIO.new
33
+ logger = TestLoggerWithTrace.new(output)
34
+ logger.trace('MyApp') { 'Test message' }
35
+ output.string
36
+ #=~> /MyApp/
37
+ #=~> /Test message/
38
+
39
+ ## trace method accepts block for message
40
+ output = StringIO.new
41
+ logger = TestLoggerWithTrace.new(output)
42
+ logger.trace { 'Block message' }
43
+ output.string
44
+ #=~> /Block message/
@@ -0,0 +1,141 @@
1
+ # try/refinements/time_literals_numeric_methods_try.rb
2
+
3
+ require_relative '../helpers/test_helpers'
4
+
5
+ class TestNumericWithTimeLiterals
6
+ include Familia::Refinements::TimeLiterals::NumericMethods
7
+
8
+ def initialize(value)
9
+ @value = value
10
+ end
11
+
12
+ def to_f
13
+ @value.to_f
14
+ end
15
+
16
+ def to_i
17
+ @value.to_i
18
+ end
19
+
20
+ def positive?
21
+ @value.positive?
22
+ end
23
+
24
+ def zero?
25
+ @value.zero?
26
+ end
27
+
28
+ def abs
29
+ @value.abs
30
+ end
31
+
32
+ def <(other)
33
+ @value < other
34
+ end
35
+
36
+ def >(other)
37
+ @value > other
38
+ end
39
+
40
+ def -(other)
41
+ @value - other
42
+ end
43
+
44
+ def +(other)
45
+ @value + other
46
+ end
47
+
48
+ def *(other)
49
+ @value * other
50
+ end
51
+
52
+ def /(other)
53
+ @value / other
54
+ end
55
+ end
56
+
57
+ ## Can create numeric with time literal methods
58
+ test_num = TestNumericWithTimeLiterals.new(5)
59
+ test_num.respond_to?(:minutes)
60
+ #=> true
61
+ #=:> TrueClass
62
+
63
+ ## Basic time unit conversions work
64
+ test_num = TestNumericWithTimeLiterals.new(5)
65
+ test_num.minutes
66
+ #=> 300.0
67
+ #=:> Float
68
+
69
+ ## Minutes conversion
70
+ test_num = TestNumericWithTimeLiterals.new(2)
71
+ test_num.minutes
72
+ #=> 120.0
73
+ #=:> Float
74
+
75
+ ## Hours conversion
76
+ test_num = TestNumericWithTimeLiterals.new(2)
77
+ test_num.hours
78
+ #=> 7200.0
79
+ #=:> Float
80
+
81
+ ## Days conversion
82
+ test_num = TestNumericWithTimeLiterals.new(1)
83
+ test_num.days
84
+ #=> 86400.0
85
+ #=:> Float
86
+
87
+ ## Conversion from seconds to other units
88
+ test_num = TestNumericWithTimeLiterals.new(3600)
89
+ test_num.in_hours
90
+ #=> 1.0
91
+ #=:> Float
92
+
93
+ ## Conversion from seconds to days
94
+ test_num = TestNumericWithTimeLiterals.new(86400)
95
+ test_num.in_days
96
+ #=> 1.0
97
+ #=:> Float
98
+
99
+ ## to_ms conversion
100
+ test_num = TestNumericWithTimeLiterals.new(5)
101
+ test_num.to_ms
102
+ #=> 5000.0
103
+ #=:> Float
104
+
105
+ ## humanize for seconds
106
+ test_num = TestNumericWithTimeLiterals.new(30)
107
+ test_num.humanize
108
+ #=> "30 seconds"
109
+ #=:> String
110
+
111
+ ## humanize for minutes
112
+ test_num = TestNumericWithTimeLiterals.new(120)
113
+ test_num.humanize
114
+ #=> "2 minutes"
115
+ #=:> String
116
+
117
+ ## to_bytes conversion
118
+ test_num = TestNumericWithTimeLiterals.new(1024)
119
+ test_num.to_bytes
120
+ #=> "1.00 KiB"
121
+ #=:> String
122
+
123
+ ## age_in with days
124
+ old_time = Familia.now.to_f - 86400
125
+ test_num = TestNumericWithTimeLiterals.new(old_time)
126
+ age = test_num.age_in(:days)
127
+ age.round
128
+ #=> 1
129
+ #=:> Integer
130
+
131
+ ## older_than? check
132
+ old_timestamp = TestNumericWithTimeLiterals.new(Familia.now.to_f - 7200) # 2 hours ago
133
+ old_timestamp.older_than?(3600) # 1 hour
134
+ #=> true
135
+ #=:> TrueClass
136
+
137
+ ## within? check for recent timestamp
138
+ recent_timestamp = TestNumericWithTimeLiterals.new(Familia.now.to_f - 30) # 30 seconds ago
139
+ recent_timestamp.within?(60) # within 1 minute
140
+ #=> true
141
+ #=:> TrueClass
@@ -0,0 +1,80 @@
1
+ # try/refinements/time_literals_string_methods_try.rb
2
+
3
+ require_relative '../helpers/test_helpers'
4
+
5
+ class TestStringWithTimeLiterals < String
6
+ include Familia::Refinements::TimeLiterals::StringMethods
7
+ end
8
+
9
+ ## Can create string with time literal methods
10
+ test_str = TestStringWithTimeLiterals.new("5m")
11
+ test_str.respond_to?(:in_seconds)
12
+ #=> true
13
+ #=:> TrueClass
14
+
15
+ ## Parse minutes to seconds
16
+ test_str = TestStringWithTimeLiterals.new("5m")
17
+ test_str.in_seconds
18
+ #=> 300.0
19
+ #=:> Float
20
+
21
+ ## Parse hours to seconds
22
+ test_str = TestStringWithTimeLiterals.new("2h")
23
+ test_str.in_seconds
24
+ #=> 7200.0
25
+ #=:> Float
26
+
27
+ ## Parse days to seconds
28
+ test_str = TestStringWithTimeLiterals.new("1d")
29
+ test_str.in_seconds
30
+ #=> 86400.0
31
+ #=:> Float
32
+
33
+ ## Parse decimal values
34
+ test_str = TestStringWithTimeLiterals.new("2.5h")
35
+ test_str.in_seconds
36
+ #=> 9000.0
37
+ #=:> Float
38
+
39
+ ## Parse years to seconds
40
+ test_str = TestStringWithTimeLiterals.new("1y")
41
+ result = test_str.in_seconds
42
+ result > 31_000_000 && result < 32_000_000
43
+ #=> true
44
+ #=:> TrueClass
45
+
46
+ ## Parse microseconds
47
+ test_str = TestStringWithTimeLiterals.new("500μs")
48
+ test_str.in_seconds
49
+ #=> 0.0005
50
+ #=:> Float
51
+
52
+ ## Parse milliseconds
53
+ test_str = TestStringWithTimeLiterals.new("500ms")
54
+ test_str.in_seconds
55
+ #=> 0.5
56
+ #=:> Float
57
+
58
+ ## Parse weeks
59
+ test_str = TestStringWithTimeLiterals.new("2w")
60
+ test_str.in_seconds
61
+ #=> 1209600.0
62
+ #=:> Float
63
+
64
+ ## Default unit is seconds when no unit specified
65
+ test_str = TestStringWithTimeLiterals.new("30")
66
+ test_str.in_seconds
67
+ #=> 30.0
68
+ #=:> Float
69
+
70
+ ## Invalid format returns nil
71
+ test_str = TestStringWithTimeLiterals.new("invalid")
72
+ test_str.in_seconds
73
+ #=> nil
74
+ #=:> NilClass
75
+
76
+ ## Empty string returns nil
77
+ test_str = TestStringWithTimeLiterals.new("")
78
+ test_str.in_seconds
79
+ #=> nil
80
+ #=:> NilClass
data/try/valkey.conf ADDED
@@ -0,0 +1,26 @@
1
+ # try/test-valkey.conf
2
+
3
+ # Familia - Tryouts Valkey Config
4
+ # 2025-10-01
5
+ #
6
+ # Usage:
7
+ #
8
+ # $ valkey-server try/valkey.conf
9
+ #
10
+
11
+ dir ./data
12
+
13
+ enable-debug-command yes
14
+
15
+ #requirepass CHANGEME
16
+
17
+ bind 127.0.0.1
18
+ port 2525
19
+ databases 10
20
+
21
+ timeout 4
22
+ daemonize no
23
+ loglevel notice
24
+
25
+ # Disable RDB persistence for tests DB
26
+ save ""
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: familia
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre15
4
+ version: 2.0.0.pre17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum
@@ -137,11 +137,14 @@ files:
137
137
  - ".github/workflows/ci.yml"
138
138
  - ".github/workflows/claude-code-review.yml"
139
139
  - ".github/workflows/claude.yml"
140
+ - ".github/workflows/code-quality.yml"
141
+ - ".github/workflows/code-smells.yml"
140
142
  - ".github/workflows/docs.yml"
141
143
  - ".gitignore"
142
144
  - ".pre-commit-config.yaml"
145
+ - ".reek.yml"
143
146
  - ".rubocop.yml"
144
- - ".rubocop_todo.yml"
147
+ - ".talismanrc"
145
148
  - ".yardopts"
146
149
  - CHANGELOG.rst
147
150
  - CLAUDE.md
@@ -157,23 +160,23 @@ files:
157
160
  - docs/archive/FAMILIA_TECHNICAL.md
158
161
  - docs/archive/FAMILIA_UPDATE.md
159
162
  - docs/archive/README.md
160
- - docs/connection_pooling.md
163
+ - docs/archive/api-reference.md
164
+ - docs/conf.py
161
165
  - docs/guides/.gitignore
162
- - docs/guides/API-Reference.md
163
- - docs/guides/Connection-Pooling-Guide.md
164
- - docs/guides/Encrypted-Fields-Overview.md
165
- - docs/guides/Expiration-Feature-Guide.md
166
- - docs/guides/Feature-System-Autoloading.md
167
- - docs/guides/Feature-System-Guide.md
168
- - docs/guides/Features-System-Developer-Guide.md
169
- - docs/guides/Field-System-Guide.md
170
- - docs/guides/Home.md
171
- - docs/guides/Implementation-Guide.md
172
- - docs/guides/Quantization-Feature-Guide.md
173
- - docs/guides/Relationships-Guide.md
174
- - docs/guides/Security-Model.md
175
- - docs/guides/Transient-Fields-Guide.md
176
- - docs/guides/relationships-methods.md
166
+ - docs/guides/core-field-system.md
167
+ - docs/guides/feature-encrypted-fields.md
168
+ - docs/guides/feature-expiration.md
169
+ - docs/guides/feature-external-identifiers.md
170
+ - docs/guides/feature-object-identifiers.md
171
+ - docs/guides/feature-quantization.md
172
+ - docs/guides/feature-relationships-methods.md
173
+ - docs/guides/feature-relationships.md
174
+ - docs/guides/feature-system-devs.md
175
+ - docs/guides/feature-system.md
176
+ - docs/guides/feature-transient-fields.md
177
+ - docs/guides/implementation.md
178
+ - docs/guides/index.md
179
+ - docs/guides/security-model.md
177
180
  - docs/guides/time-utilities.md
178
181
  - docs/migrating/.gitignore
179
182
  - docs/migrating/v2.0.0-pre.md
@@ -185,26 +188,40 @@ files:
185
188
  - docs/migrating/v2.0.0-pre6.md
186
189
  - docs/migrating/v2.0.0-pre7.md
187
190
  - docs/overview.md
188
- - docs/reference/auditing_database_commands.rb
191
+ - docs/reference/api-technical.md
189
192
  - examples/autoloader/mega_customer.rb
193
+ - examples/autoloader/mega_customer/features/deprecated_fields.rb
190
194
  - examples/autoloader/mega_customer/safe_dump_fields.rb
191
- - examples/permissions.rb
195
+ - examples/encrypted_fields.rb
196
+ - examples/json_usage_patterns.rb
192
197
  - examples/relationships.rb
193
198
  - examples/safe_dump.rb
199
+ - examples/single_connection_transaction_confusions.rb
194
200
  - familia.gemspec
195
201
  - lib/familia.rb
196
202
  - lib/familia/base.rb
197
203
  - lib/familia/connection.rb
204
+ - lib/familia/connection/handlers.rb
205
+ - lib/familia/connection/individual_command_proxy.rb
206
+ - lib/familia/connection/middleware.rb
207
+ - lib/familia/connection/operation_core.rb
208
+ - lib/familia/connection/operations.rb
209
+ - lib/familia/connection/pipeline_core.rb
210
+ - lib/familia/connection/transaction_core.rb
198
211
  - lib/familia/data_type.rb
212
+ - lib/familia/data_type/class_methods.rb
199
213
  - lib/familia/data_type/commands.rb
214
+ - lib/familia/data_type/connection.rb
200
215
  - lib/familia/data_type/serialization.rb
216
+ - lib/familia/data_type/settings.rb
201
217
  - lib/familia/data_type/types/counter.rb
202
218
  - lib/familia/data_type/types/hashkey.rb
203
- - lib/familia/data_type/types/list.rb
219
+ - lib/familia/data_type/types/listkey.rb
204
220
  - lib/familia/data_type/types/lock.rb
205
221
  - lib/familia/data_type/types/sorted_set.rb
206
- - lib/familia/data_type/types/string.rb
222
+ - lib/familia/data_type/types/stringkey.rb
207
223
  - lib/familia/data_type/types/unsorted_set.rb
224
+ - lib/familia/distinguisher.rb
208
225
  - lib/familia/encryption.rb
209
226
  - lib/familia/encryption/encrypted_data.rb
210
227
  - lib/familia/encryption/manager.rb
@@ -226,14 +243,17 @@ files:
226
243
  - lib/familia/features/object_identifier.rb
227
244
  - lib/familia/features/quantization.rb
228
245
  - lib/familia/features/relationships.rb
229
- - lib/familia/features/relationships/cascading.rb
246
+ - lib/familia/features/relationships/README.md
247
+ - lib/familia/features/relationships/collection_operations.rb
230
248
  - lib/familia/features/relationships/indexing.rb
231
- - lib/familia/features/relationships/membership.rb
232
- - lib/familia/features/relationships/permission_management.rb
233
- - lib/familia/features/relationships/querying.rb
234
- - lib/familia/features/relationships/redis_operations.rb
249
+ - lib/familia/features/relationships/indexing/multi_index_generators.rb
250
+ - lib/familia/features/relationships/indexing/unique_index_generators.rb
251
+ - lib/familia/features/relationships/indexing_relationship.rb
252
+ - lib/familia/features/relationships/participation.rb
253
+ - lib/familia/features/relationships/participation/participant_methods.rb
254
+ - lib/familia/features/relationships/participation/target_methods.rb
255
+ - lib/familia/features/relationships/participation_relationship.rb
235
256
  - lib/familia/features/relationships/score_encoding.rb
236
- - lib/familia/features/relationships/tracking.rb
237
257
  - lib/familia/features/safe_dump.rb
238
258
  - lib/familia/features/transient_fields.rb
239
259
  - lib/familia/features/transient_fields/redacted_string.rb
@@ -241,43 +261,52 @@ files:
241
261
  - lib/familia/features/transient_fields/transient_field_type.rb
242
262
  - lib/familia/field_type.rb
243
263
  - lib/familia/horreum.rb
244
- - lib/familia/horreum/core.rb
245
- - lib/familia/horreum/core/connection.rb
246
- - lib/familia/horreum/core/database_commands.rb
247
- - lib/familia/horreum/core/serialization.rb
248
- - lib/familia/horreum/core/utils.rb
249
- - lib/familia/horreum/shared/settings.rb
250
- - lib/familia/horreum/subclass/definition.rb
251
- - lib/familia/horreum/subclass/management.rb
252
- - lib/familia/horreum/subclass/related_fields_management.rb
264
+ - lib/familia/horreum/connection.rb
265
+ - lib/familia/horreum/database_commands.rb
266
+ - lib/familia/horreum/definition.rb
267
+ - lib/familia/horreum/management.rb
268
+ - lib/familia/horreum/persistence.rb
269
+ - lib/familia/horreum/related_fields.rb
270
+ - lib/familia/horreum/serialization.rb
271
+ - lib/familia/horreum/settings.rb
272
+ - lib/familia/horreum/utils.rb
253
273
  - lib/familia/json_serializer.rb
254
274
  - lib/familia/logging.rb
255
- - lib/familia/multi_result.rb
256
275
  - lib/familia/refinements.rb
276
+ - lib/familia/refinements/dear_json.rb
257
277
  - lib/familia/refinements/logger_trace.rb
258
- - lib/familia/refinements/snake_case.rb
278
+ - lib/familia/refinements/stylize_words.rb
259
279
  - lib/familia/refinements/time_literals.rb
260
280
  - lib/familia/secure_identifier.rb
261
281
  - lib/familia/settings.rb
262
282
  - lib/familia/utils.rb
263
- - lib/familia/validation.rb
264
- - lib/familia/validation/command_recorder.rb
265
- - lib/familia/validation/expectations.rb
266
- - lib/familia/validation/validation_helpers.rb
267
- - lib/familia/validation/validator.rb
268
283
  - lib/familia/verifiable_identifier.rb
269
284
  - lib/familia/version.rb
270
285
  - lib/middleware/database_middleware.rb
286
+ - lib/multi_result.rb
271
287
  - try/configuration/scenarios_try.rb
288
+ - try/connection/fiber_context_preservation_try.rb
289
+ - try/connection/handler_constraints_try.rb
290
+ - try/connection/operation_mode_guards_try.rb
291
+ - try/connection/pipeline_fallback_integration_try.rb
292
+ - try/connection/responsibility_chain_tracking_try.rb
293
+ - try/connection/transaction_fallback_integration_try.rb
294
+ - try/connection/transaction_mode_permissive_try.rb
295
+ - try/connection/transaction_mode_strict_try.rb
296
+ - try/connection/transaction_mode_warn_try.rb
297
+ - try/connection/transaction_modes_try.rb
272
298
  - try/core/autoloader_try.rb
273
299
  - try/core/base_enhancements_try.rb
274
300
  - try/core/connection_try.rb
301
+ - try/core/conventional_inheritance_try.rb
275
302
  - try/core/create_method_try.rb
276
303
  - try/core/database_consistency_try.rb
277
304
  - try/core/errors_try.rb
278
305
  - try/core/extensions_try.rb
279
306
  - try/core/familia_extended_try.rb
307
+ - try/core/familia_members_methods_try.rb
280
308
  - try/core/familia_try.rb
309
+ - try/core/isolated_dbclient_try.rb
281
310
  - try/core/middleware_try.rb
282
311
  - try/core/persistence_operations_try.rb
283
312
  - try/core/pools_try.rb
@@ -293,9 +322,10 @@ files:
293
322
  - try/data_types/hash_try.rb
294
323
  - try/data_types/list_try.rb
295
324
  - try/data_types/lock_try.rb
296
- - try/data_types/set_try.rb
297
325
  - try/data_types/sorted_set_try.rb
326
+ - try/data_types/sorted_set_zadd_options_try.rb
298
327
  - try/data_types/string_try.rb
328
+ - try/data_types/unsortedset_try.rb
299
329
  - try/debugging/README.md
300
330
  - try/debugging/cache_behavior_tracer.rb
301
331
  - try/debugging/debug_aad_process.rb
@@ -357,11 +387,17 @@ files:
357
387
  - try/features/external_identifier/external_identifier_try.rb
358
388
  - try/features/feature_dependencies_try.rb
359
389
  - try/features/feature_improvements_try.rb
390
+ - try/features/field_groups_try.rb
360
391
  - try/features/object_identifier/object_identifier_integration_try.rb
361
392
  - try/features/object_identifier/object_identifier_try.rb
362
393
  - try/features/quantization/quantization_try.rb
363
394
  - try/features/real_feature_integration_try.rb
364
- - try/features/relationships/categorical_permissions_try.rb
395
+ - try/features/relationships/indexing_commands_verification_try.rb
396
+ - try/features/relationships/indexing_try.rb
397
+ - try/features/relationships/participation_commands_verification_spec.rb
398
+ - try/features/relationships/participation_commands_verification_try.rb
399
+ - try/features/relationships/participation_performance_improvements_try.rb
400
+ - try/features/relationships/participation_reverse_index_try.rb
365
401
  - try/features/relationships/relationships_api_changes_try.rb
366
402
  - try/features/relationships/relationships_edge_cases_try.rb
367
403
  - try/features/relationships/relationships_performance_minimal_try.rb
@@ -369,9 +405,7 @@ files:
369
405
  - try/features/relationships/relationships_performance_try.rb
370
406
  - try/features/relationships/relationships_performance_working_try.rb
371
407
  - try/features/relationships/relationships_try.rb
372
- - try/features/safe_dump/module_based_extensions_try.rb
373
408
  - try/features/safe_dump/safe_dump_advanced_try.rb
374
- - try/features/safe_dump/safe_dump_autoloading_try.rb
375
409
  - try/features/safe_dump/safe_dump_try.rb
376
410
  - try/features/transient_fields/redacted_string_try.rb
377
411
  - try/features/transient_fields/refresh_reset_try.rb
@@ -379,10 +413,14 @@ files:
379
413
  - try/features/transient_fields/single_use_redacted_string_try.rb
380
414
  - try/features/transient_fields/transient_fields_core_try.rb
381
415
  - try/features/transient_fields/transient_fields_integration_try.rb
416
+ - try/helpers/test_cleanup.rb
382
417
  - try/helpers/test_helpers.rb
418
+ - try/horreum/auto_indexing_on_save_try.rb
383
419
  - try/horreum/base_try.rb
384
420
  - try/horreum/class_methods_try.rb
385
421
  - try/horreum/commands_try.rb
422
+ - try/horreum/defensive_initialization_try.rb
423
+ - try/horreum/destroy_related_fields_cleanup_try.rb
386
424
  - try/horreum/enhanced_conflict_handling_try.rb
387
425
  - try/horreum/field_categories_try.rb
388
426
  - try/horreum/field_definition_try.rb
@@ -417,10 +455,12 @@ files:
417
455
  - try/prototypes/pooling/lib/visualize_stress_results.rb
418
456
  - try/prototypes/pooling/pool_siege.rb
419
457
  - try/prototypes/pooling/run_stress_tests.rb
420
- - try/validation/atomic_operations_try.rb.disabled
421
- - try/validation/command_validation_try.rb.disabled
422
- - try/validation/performance_validation_try.rb.disabled
423
- - try/validation/real_world_scenarios_try.rb.disabled
458
+ - try/refinements/dear_json_array_methods_try.rb
459
+ - try/refinements/dear_json_hash_methods_try.rb
460
+ - try/refinements/logger_trace_methods_try.rb
461
+ - try/refinements/time_literals_numeric_methods_try.rb
462
+ - try/refinements/time_literals_string_methods_try.rb
463
+ - try/valkey.conf
424
464
  homepage: https://github.com/delano/familia
425
465
  licenses:
426
466
  - MIT