familia 2.0.0.pre15 → 2.0.0.pre16

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 (274) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/code-quality.yml +138 -0
  3. data/.github/workflows/code-smellage.yml +145 -0
  4. data/.github/workflows/docs.yml +31 -8
  5. data/.gitignore +1 -1
  6. data/.pre-commit-config.yaml +7 -1
  7. data/.reek.yml +98 -0
  8. data/.rubocop.yml +48 -10
  9. data/.talismanrc +9 -0
  10. data/.yardopts +18 -13
  11. data/CHANGELOG.rst +64 -4
  12. data/CLAUDE.md +1 -1
  13. data/Gemfile +6 -5
  14. data/Gemfile.lock +99 -23
  15. data/LICENSE.txt +1 -1
  16. data/README.md +285 -85
  17. data/changelog.d/README.md +2 -2
  18. data/docs/archive/FAMILIA_RELATIONSHIPS.md +22 -22
  19. data/docs/archive/FAMILIA_TECHNICAL.md +41 -41
  20. data/docs/archive/FAMILIA_UPDATE.md +3 -3
  21. data/docs/archive/README.md +3 -2
  22. data/docs/{guides/API-Reference.md → archive/api-reference.md} +87 -101
  23. data/docs/conf.py +29 -0
  24. data/docs/guides/{Field-System-Guide.md → core-field-system.md} +9 -9
  25. data/docs/guides/feature-encrypted-fields.md +785 -0
  26. data/docs/guides/{Expiration-Feature-Guide.md → feature-expiration.md} +11 -2
  27. data/docs/guides/feature-external-identifiers.md +637 -0
  28. data/docs/guides/feature-object-identifiers.md +435 -0
  29. data/docs/guides/{Quantization-Feature-Guide.md → feature-quantization.md} +94 -29
  30. data/docs/guides/feature-relationships-methods.md +684 -0
  31. data/docs/guides/feature-relationships.md +200 -0
  32. data/docs/guides/{Features-System-Developer-Guide.md → feature-system-devs.md} +4 -4
  33. data/docs/guides/{Feature-System-Guide.md → feature-system.md} +5 -5
  34. data/docs/guides/{Transient-Fields-Guide.md → feature-transient-fields.md} +2 -2
  35. data/docs/guides/{Implementation-Guide.md → implementation.md} +3 -3
  36. data/docs/guides/index.md +176 -0
  37. data/docs/guides/{Security-Model.md → security-model.md} +1 -1
  38. data/docs/migrating/v2.0.0-pre.md +1 -1
  39. data/docs/migrating/v2.0.0-pre11.md +2 -2
  40. data/docs/migrating/v2.0.0-pre12.md +2 -2
  41. data/docs/migrating/v2.0.0-pre5.md +33 -12
  42. data/docs/migrating/v2.0.0-pre6.md +2 -2
  43. data/docs/migrating/v2.0.0-pre7.md +8 -8
  44. data/docs/overview.md +623 -19
  45. data/docs/reference/api-technical.md +1365 -0
  46. data/examples/autoloader/mega_customer/features/deprecated_fields.rb +7 -0
  47. data/examples/autoloader/mega_customer/safe_dump_fields.rb +1 -1
  48. data/examples/autoloader/mega_customer.rb +3 -1
  49. data/examples/encrypted_fields.rb +378 -0
  50. data/examples/json_usage_patterns.rb +144 -0
  51. data/examples/relationships.rb +13 -13
  52. data/examples/safe_dump.rb +6 -6
  53. data/examples/single_connection_transaction_confusions.rb +379 -0
  54. data/lib/familia/base.rb +49 -10
  55. data/lib/familia/connection/handlers.rb +223 -0
  56. data/lib/familia/connection/individual_command_proxy.rb +64 -0
  57. data/lib/familia/connection/middleware.rb +75 -0
  58. data/lib/familia/connection/operation_core.rb +93 -0
  59. data/lib/familia/connection/operations.rb +277 -0
  60. data/lib/familia/connection/pipeline_core.rb +87 -0
  61. data/lib/familia/connection/transaction_core.rb +100 -0
  62. data/lib/familia/connection.rb +60 -186
  63. data/lib/familia/data_type/commands.rb +53 -51
  64. data/lib/familia/data_type/serialization.rb +108 -107
  65. data/lib/familia/data_type/types/counter.rb +1 -1
  66. data/lib/familia/data_type/types/hashkey.rb +13 -10
  67. data/lib/familia/data_type/types/{list.rb → listkey.rb} +13 -5
  68. data/lib/familia/data_type/types/lock.rb +3 -2
  69. data/lib/familia/data_type/types/sorted_set.rb +26 -15
  70. data/lib/familia/data_type/types/{string.rb → stringkey.rb} +7 -5
  71. data/lib/familia/data_type/types/unsorted_set.rb +20 -27
  72. data/lib/familia/data_type.rb +75 -47
  73. data/lib/familia/distinguisher.rb +85 -0
  74. data/lib/familia/encryption/encrypted_data.rb +15 -24
  75. data/lib/familia/encryption/manager.rb +6 -4
  76. data/lib/familia/encryption/providers/aes_gcm_provider.rb +1 -1
  77. data/lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb +7 -9
  78. data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +4 -5
  79. data/lib/familia/encryption/request_cache.rb +7 -7
  80. data/lib/familia/encryption.rb +2 -3
  81. data/lib/familia/errors.rb +9 -3
  82. data/lib/familia/features/autoloader.rb +30 -12
  83. data/lib/familia/features/encrypted_fields/concealed_string.rb +3 -4
  84. data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +13 -14
  85. data/lib/familia/features/encrypted_fields.rb +66 -64
  86. data/lib/familia/features/expiration/extensions.rb +1 -1
  87. data/lib/familia/features/expiration.rb +31 -26
  88. data/lib/familia/features/external_identifier.rb +9 -12
  89. data/lib/familia/features/object_identifier.rb +56 -19
  90. data/lib/familia/features/quantization.rb +16 -21
  91. data/lib/familia/features/relationships/README.md +97 -0
  92. data/lib/familia/features/relationships/collection_operations.rb +104 -0
  93. data/lib/familia/features/relationships/indexing/multi_index_generators.rb +202 -0
  94. data/lib/familia/features/relationships/indexing/unique_index_generators.rb +301 -0
  95. data/lib/familia/features/relationships/indexing.rb +176 -256
  96. data/lib/familia/features/relationships/indexing_relationship.rb +35 -0
  97. data/lib/familia/features/relationships/participation/participant_methods.rb +160 -0
  98. data/lib/familia/features/relationships/participation/target_methods.rb +225 -0
  99. data/lib/familia/features/relationships/participation.rb +656 -0
  100. data/lib/familia/features/relationships/participation_relationship.rb +31 -0
  101. data/lib/familia/features/relationships/score_encoding.rb +20 -20
  102. data/lib/familia/features/relationships.rb +65 -266
  103. data/lib/familia/features/safe_dump.rb +127 -130
  104. data/lib/familia/features/transient_fields/redacted_string.rb +6 -6
  105. data/lib/familia/features/transient_fields/transient_field_type.rb +5 -5
  106. data/lib/familia/features/transient_fields.rb +3 -5
  107. data/lib/familia/features.rb +4 -13
  108. data/lib/familia/field_type.rb +24 -4
  109. data/lib/familia/horreum/core/connection.rb +229 -26
  110. data/lib/familia/horreum/core/database_commands.rb +27 -17
  111. data/lib/familia/horreum/core/serialization.rb +40 -20
  112. data/lib/familia/horreum/core/utils.rb +2 -1
  113. data/lib/familia/horreum/shared/settings.rb +2 -1
  114. data/lib/familia/horreum/subclass/definition.rb +33 -45
  115. data/lib/familia/horreum/subclass/management.rb +72 -24
  116. data/lib/familia/horreum/subclass/related_fields_management.rb +82 -21
  117. data/lib/familia/horreum.rb +196 -114
  118. data/lib/familia/json_serializer.rb +0 -1
  119. data/lib/familia/logging.rb +11 -114
  120. data/lib/familia/refinements/dear_json.rb +122 -0
  121. data/lib/familia/refinements/logger_trace.rb +20 -17
  122. data/lib/familia/refinements/stylize_words.rb +65 -0
  123. data/lib/familia/refinements/time_literals.rb +60 -52
  124. data/lib/familia/refinements.rb +2 -1
  125. data/lib/familia/secure_identifier.rb +60 -28
  126. data/lib/familia/settings.rb +83 -7
  127. data/lib/familia/utils.rb +5 -87
  128. data/lib/familia/verifiable_identifier.rb +4 -4
  129. data/lib/familia/version.rb +1 -1
  130. data/lib/familia.rb +72 -14
  131. data/lib/middleware/database_middleware.rb +56 -14
  132. data/lib/{familia/multi_result.rb → multi_result.rb} +23 -16
  133. data/try/configuration/scenarios_try.rb +1 -1
  134. data/try/connection/fiber_context_preservation_try.rb +250 -0
  135. data/try/connection/handler_constraints_try.rb +59 -0
  136. data/try/connection/operation_mode_guards_try.rb +208 -0
  137. data/try/connection/pipeline_fallback_integration_try.rb +128 -0
  138. data/try/connection/responsibility_chain_tracking_try.rb +72 -0
  139. data/try/connection/transaction_fallback_integration_try.rb +288 -0
  140. data/try/connection/transaction_mode_permissive_try.rb +153 -0
  141. data/try/connection/transaction_mode_strict_try.rb +98 -0
  142. data/try/connection/transaction_mode_warn_try.rb +131 -0
  143. data/try/connection/transaction_modes_try.rb +249 -0
  144. data/try/core/autoloader_try.rb +120 -2
  145. data/try/core/connection_try.rb +7 -7
  146. data/try/core/conventional_inheritance_try.rb +130 -0
  147. data/try/core/create_method_try.rb +15 -23
  148. data/try/core/database_consistency_try.rb +10 -10
  149. data/try/core/errors_try.rb +8 -11
  150. data/try/core/familia_extended_try.rb +2 -2
  151. data/try/core/familia_members_methods_try.rb +76 -0
  152. data/try/core/isolated_dbclient_try.rb +165 -0
  153. data/try/core/middleware_try.rb +16 -16
  154. data/try/core/persistence_operations_try.rb +4 -4
  155. data/try/core/pools_try.rb +42 -26
  156. data/try/core/secure_identifier_try.rb +28 -24
  157. data/try/core/time_utils_try.rb +10 -10
  158. data/try/core/tools_try.rb +1 -1
  159. data/try/core/utils_try.rb +2 -2
  160. data/try/data_types/boolean_try.rb +4 -4
  161. data/try/data_types/datatype_base_try.rb +0 -2
  162. data/try/data_types/list_try.rb +10 -10
  163. data/try/data_types/sorted_set_try.rb +5 -5
  164. data/try/data_types/string_try.rb +12 -12
  165. data/try/data_types/unsortedset_try.rb +33 -0
  166. data/try/debugging/cache_behavior_tracer.rb +7 -7
  167. data/try/debugging/debug_aad_process.rb +1 -1
  168. data/try/debugging/debug_concealed_internal.rb +1 -1
  169. data/try/debugging/debug_cross_context.rb +1 -1
  170. data/try/debugging/debug_fresh_cross_context.rb +1 -1
  171. data/try/debugging/encryption_method_tracer.rb +10 -10
  172. data/try/edge_cases/hash_symbolization_try.rb +1 -1
  173. data/try/edge_cases/ttl_side_effects_try.rb +1 -1
  174. data/try/encryption/config_persistence_try.rb +2 -2
  175. data/try/encryption/encryption_core_try.rb +19 -19
  176. data/try/encryption/instance_variable_scope_try.rb +1 -1
  177. data/try/encryption/module_loading_try.rb +2 -2
  178. data/try/encryption/providers/aes_gcm_provider_try.rb +1 -1
  179. data/try/encryption/providers/xchacha20_poly1305_provider_try.rb +1 -1
  180. data/try/encryption/secure_memory_handling_try.rb +1 -1
  181. data/try/features/encrypted_fields/concealed_string_core_try.rb +11 -7
  182. data/try/features/encrypted_fields/encrypted_fields_core_try.rb +1 -1
  183. data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +3 -3
  184. data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +10 -10
  185. data/try/features/encrypted_fields/encrypted_fields_security_try.rb +14 -14
  186. data/try/features/encrypted_fields/error_conditions_try.rb +7 -7
  187. data/try/features/encrypted_fields/fresh_key_try.rb +1 -1
  188. data/try/features/encrypted_fields/nonce_uniqueness_try.rb +1 -1
  189. data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +7 -7
  190. data/try/features/encrypted_fields/universal_serialization_safety_try.rb +13 -20
  191. data/try/features/external_identifier/external_identifier_try.rb +1 -1
  192. data/try/features/feature_dependencies_try.rb +3 -3
  193. data/try/features/object_identifier/object_identifier_integration_try.rb +28 -34
  194. data/try/features/object_identifier/object_identifier_try.rb +10 -0
  195. data/try/features/quantization/quantization_try.rb +1 -1
  196. data/try/features/relationships/indexing_commands_verification_try.rb +136 -0
  197. data/try/features/relationships/indexing_try.rb +433 -0
  198. data/try/features/relationships/participation_commands_verification_spec.rb +102 -0
  199. data/try/features/relationships/participation_commands_verification_try.rb +105 -0
  200. data/try/features/relationships/participation_performance_improvements_try.rb +124 -0
  201. data/try/features/relationships/participation_reverse_index_try.rb +196 -0
  202. data/try/features/relationships/relationships_api_changes_try.rb +72 -71
  203. data/try/features/relationships/relationships_edge_cases_try.rb +15 -18
  204. data/try/features/relationships/relationships_performance_minimal_try.rb +2 -2
  205. data/try/features/relationships/relationships_performance_simple_try.rb +8 -8
  206. data/try/features/relationships/relationships_performance_try.rb +20 -20
  207. data/try/features/relationships/relationships_try.rb +27 -38
  208. data/try/features/safe_dump/safe_dump_advanced_try.rb +2 -2
  209. data/try/features/transient_fields/refresh_reset_try.rb +1 -1
  210. data/try/features/transient_fields/simple_refresh_test.rb +1 -1
  211. data/try/helpers/test_cleanup.rb +86 -0
  212. data/try/helpers/test_helpers.rb +3 -3
  213. data/try/horreum/base_try.rb +3 -2
  214. data/try/horreum/commands_try.rb +1 -1
  215. data/try/horreum/destroy_related_fields_cleanup_try.rb +330 -0
  216. data/try/horreum/initialization_try.rb +11 -7
  217. data/try/horreum/relations_try.rb +21 -13
  218. data/try/horreum/serialization_try.rb +12 -11
  219. data/try/integration/cross_component_try.rb +3 -3
  220. data/try/memory/memory_basic_test.rb +1 -1
  221. data/try/memory/memory_docker_ruby_dump.sh +1 -1
  222. data/try/models/customer_safe_dump_try.rb +1 -1
  223. data/try/models/customer_try.rb +8 -10
  224. data/try/models/datatype_base_try.rb +3 -3
  225. data/try/models/familia_object_try.rb +9 -8
  226. data/try/performance/benchmarks_try.rb +2 -2
  227. data/try/prototypes/atomic_saves_v1_context_proxy.rb +2 -2
  228. data/try/prototypes/atomic_saves_v3_connection_pool.rb +3 -3
  229. data/try/prototypes/atomic_saves_v4.rb +1 -1
  230. data/try/prototypes/lib/atomic_saves_v2_connection_switching_helpers.rb +4 -4
  231. data/try/prototypes/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -4
  232. data/try/prototypes/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -4
  233. data/try/prototypes/pooling/lib/connection_pool_metrics.rb +5 -5
  234. data/try/prototypes/pooling/lib/connection_pool_stress_test.rb +26 -26
  235. data/try/prototypes/pooling/lib/connection_pool_threading_models.rb +7 -7
  236. data/try/prototypes/pooling/lib/visualize_stress_results.rb +1 -1
  237. data/try/prototypes/pooling/pool_siege.rb +11 -11
  238. data/try/prototypes/pooling/run_stress_tests.rb +7 -7
  239. data/try/refinements/dear_json_array_methods_try.rb +53 -0
  240. data/try/refinements/dear_json_hash_methods_try.rb +54 -0
  241. data/try/refinements/logger_trace_methods_try.rb +44 -0
  242. data/try/refinements/time_literals_numeric_methods_try.rb +141 -0
  243. data/try/refinements/time_literals_string_methods_try.rb +80 -0
  244. metadata +75 -43
  245. data/.rubocop_todo.yml +0 -208
  246. data/docs/connection_pooling.md +0 -192
  247. data/docs/guides/Connection-Pooling-Guide.md +0 -437
  248. data/docs/guides/Encrypted-Fields-Overview.md +0 -101
  249. data/docs/guides/Feature-System-Autoloading.md +0 -198
  250. data/docs/guides/Home.md +0 -116
  251. data/docs/guides/Relationships-Guide.md +0 -737
  252. data/docs/guides/relationships-methods.md +0 -266
  253. data/docs/reference/auditing_database_commands.rb +0 -228
  254. data/examples/permissions.rb +0 -240
  255. data/lib/familia/features/relationships/cascading.rb +0 -437
  256. data/lib/familia/features/relationships/membership.rb +0 -497
  257. data/lib/familia/features/relationships/permission_management.rb +0 -264
  258. data/lib/familia/features/relationships/querying.rb +0 -615
  259. data/lib/familia/features/relationships/redis_operations.rb +0 -274
  260. data/lib/familia/features/relationships/tracking.rb +0 -418
  261. data/lib/familia/refinements/snake_case.rb +0 -40
  262. data/lib/familia/validation/command_recorder.rb +0 -336
  263. data/lib/familia/validation/expectations.rb +0 -519
  264. data/lib/familia/validation/validation_helpers.rb +0 -443
  265. data/lib/familia/validation/validator.rb +0 -412
  266. data/lib/familia/validation.rb +0 -140
  267. data/try/data_types/set_try.rb +0 -33
  268. data/try/features/relationships/categorical_permissions_try.rb +0 -515
  269. data/try/features/safe_dump/module_based_extensions_try.rb +0 -100
  270. data/try/features/safe_dump/safe_dump_autoloading_try.rb +0 -107
  271. data/try/validation/atomic_operations_try.rb.disabled +0 -320
  272. data/try/validation/command_validation_try.rb.disabled +0 -207
  273. data/try/validation/performance_validation_try.rb.disabled +0 -324
  274. data/try/validation/real_world_scenarios_try.rb.disabled +0 -390
data/.rubocop_todo.yml DELETED
@@ -1,208 +0,0 @@
1
- # This configuration was generated by
2
- # `rubocop --auto-gen-config`
3
- # on 2025-07-20 01:49:27 UTC using RuboCop version 1.78.0.
4
- # The point is for the user to remove these configuration records
5
- # one by one as the offenses are removed from the code base.
6
- # Note that changes in the inspected code, or installation of new
7
- # versions of RuboCop, may require this file to be generated again.
8
-
9
- # Offense count: 2
10
- # This cop supports safe autocorrection (--autocorrect).
11
- # Configuration parameters: AutoCorrect, AllowBorderComment, AllowMarginComment.
12
- Layout/EmptyComment:
13
- Exclude:
14
- - "lib/familia/base.rb"
15
- - "lib/familia/connection.rb"
16
-
17
- # Offense count: 1
18
- # This cop supports safe autocorrection (--autocorrect).
19
- Layout/EmptyLines:
20
- Exclude:
21
- - "Gemfile"
22
-
23
- # Offense count: 2
24
- # This cop supports safe autocorrection (--autocorrect).
25
- # Configuration parameters: EnforcedStyle.
26
- # SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only
27
- Layout/EmptyLinesAroundClassBody:
28
- Exclude:
29
- - "lib/familia/data_type/types/list.rb"
30
- - "lib/familia/data_type/types/unsorted_set.rb"
31
-
32
- # Offense count: 1
33
- # This cop supports safe autocorrection (--autocorrect).
34
- Layout/SpaceAfterComma:
35
- Exclude:
36
- - "lib/familia/data_type/types/hashkey.rb"
37
-
38
- # Offense count: 4
39
- # This cop supports safe autocorrection (--autocorrect).
40
- # Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
41
- # NotImplementedExceptions: NotImplementedError
42
- Lint/UnusedMethodArgument:
43
- Exclude:
44
- - "lib/familia/base.rb"
45
- - "lib/middleware/database_middleware.rb"
46
-
47
- # Offense count: 1
48
- # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
49
- # AllowedMethods: refine
50
- Metrics/BlockLength:
51
- Max: 28
52
-
53
- # Offense count: 2
54
- # Configuration parameters: AllowedMethods, AllowedPatterns.
55
- Metrics/PerceivedComplexity:
56
- Max: 9
57
-
58
- # Offense count: 50
59
- # This cop supports safe autocorrection (--autocorrect).
60
- # Configuration parameters: EnforcedStyle, BlockForwardingName.
61
- # SupportedStyles: anonymous, explicit
62
- Naming/BlockForwarding:
63
- Exclude:
64
- - "lib/familia/data_type/types/list.rb"
65
- - "lib/familia/data_type/types/sorted_set.rb"
66
- - "lib/familia/data_type/types/unsorted_set.rb"
67
- - "lib/familia/refinements/logger_trace.rb"
68
-
69
- # Offense count: 8
70
- # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
71
- # AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
72
- Naming/MethodParameterName:
73
- Exclude:
74
- - "lib/familia/horreum/class_methods.rb"
75
- - "lib/familia/data_type/types/sorted_set.rb"
76
- - "lib/familia/data_type/types/unsorted_set.rb"
77
-
78
- # Offense count: 1
79
- # Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
80
- # AllowedMethods: call
81
- # WaywardPredicates: nonzero?
82
- Naming/PredicateMethod:
83
- Exclude:
84
- - "lib/familia/horreum/class_methods.rb"
85
-
86
- # Offense count: 1
87
- # Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs.
88
- # NamePrefix: is_, has_, have_, does_
89
- # ForbiddenPrefixes: is_, has_, have_, does_
90
- # AllowedMethods: is_a?
91
- # MethodDefinitionMacros: define_method, define_singleton_method
92
- Naming/PredicatePrefix:
93
- Exclude:
94
- - "spec/**/*"
95
- - "lib/familia/horreum/class_methods.rb"
96
-
97
- # Offense count: 54
98
- # This cop supports safe autocorrection (--autocorrect).
99
- # Configuration parameters: AllowOnlyRestArgument, UseAnonymousForwarding, RedundantRestArgumentNames, RedundantKeywordRestArgumentNames, RedundantBlockArgumentNames.
100
- # RedundantRestArgumentNames: args, arguments
101
- # RedundantKeywordRestArgumentNames: kwargs, options, opts
102
- # RedundantBlockArgumentNames: blk, block, proc
103
- Style/ArgumentsForwarding:
104
- Exclude:
105
- - "lib/familia/horreum/class_methods.rb"
106
- - "lib/familia/data_type/types/list.rb"
107
- - "lib/familia/data_type/types/sorted_set.rb"
108
- - "lib/familia/data_type/types/unsorted_set.rb"
109
- - "lib/familia/refinements/logger_trace.rb"
110
-
111
- # Offense count: 11
112
- # Configuration parameters: AllowedConstants.
113
- Style/Documentation:
114
- Exclude:
115
- - "spec/**/*"
116
- - "test/**/*"
117
- - "lib/familia/errors.rb"
118
- - "lib/familia/horreum/class_methods.rb"
119
- - "lib/familia/horreum/related_fields_management.rb"
120
- - "lib/familia/data_type/types/hashkey.rb"
121
- - "lib/familia/data_type/types/list.rb"
122
- - "lib/familia/data_type/types/sorted_set.rb"
123
- - "lib/familia/data_type/types/string.rb"
124
- - "lib/familia/data_type/types/unsorted_set.rb"
125
- - "lib/familia/version.rb"
126
-
127
- # Offense count: 1
128
- # This cop supports safe autocorrection (--autocorrect).
129
- # Configuration parameters: AutoCorrect, EnforcedStyle, AllowComments.
130
- # SupportedStyles: empty, nil, both
131
-
132
- # Offense count: 2
133
- # This cop supports safe autocorrection (--autocorrect).
134
- # Configuration parameters: MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns.
135
- # SupportedStyles: annotated, template, unannotated
136
- Style/FormatStringToken:
137
- EnforcedStyle: unannotated
138
-
139
- # Offense count: 1
140
- # This cop supports unsafe autocorrection (--autocorrect-all).
141
- # Configuration parameters: EnforcedStyle.
142
- # SupportedStyles: always, always_true, never
143
- Style/FrozenStringLiteralComment:
144
- Exclude:
145
- - "**/*.arb"
146
- - "lib/familia/horreum/related_fields_management.rb"
147
-
148
- # Offense count: 1
149
- # This cop supports unsafe autocorrection (--autocorrect-all).
150
- Style/HashTransformValues:
151
- Exclude:
152
- - "lib/familia/data_type/types/hashkey.rb"
153
-
154
- # Offense count: 1
155
- # This cop supports unsafe autocorrection (--autocorrect-all).
156
- # Configuration parameters: EnforcedStyle, Autocorrect.
157
- # SupportedStyles: module_function, extend_self, forbidden
158
-
159
- # Offense count: 1
160
- # This cop supports unsafe autocorrection (--autocorrect-all).
161
- # Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns.
162
- # SupportedStyles: predicate, comparison
163
- Style/NumericPredicate:
164
- Exclude:
165
- - "spec/**/*"
166
- - "lib/familia/horreum/class_methods.rb"
167
-
168
- # Offense count: 1
169
- # This cop supports unsafe autocorrection (--autocorrect-all).
170
-
171
- # Offense count: 1
172
- # This cop supports safe autocorrection (--autocorrect).
173
- # Configuration parameters: EnforcedStyle.
174
- # SupportedStyles: implicit, explicit
175
- Style/RescueStandardError:
176
- Exclude:
177
- - "lib/familia/horreum.rb"
178
-
179
- # Offense count: 1
180
- # This cop supports unsafe autocorrection (--autocorrect-all).
181
- # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength.
182
- # AllowedMethods: present?, blank?, presence, try, try!
183
- Style/SafeNavigation:
184
- Exclude:
185
- - "lib/familia/connection.rb"
186
-
187
- # Offense count: 4
188
- # Configuration parameters: ActiveSupportClassAttributeAllowed.
189
- ThreadSafety/ClassAndModuleAttributes:
190
- Exclude:
191
- - "lib/familia/base.rb"
192
- - "lib/familia/horreum.rb"
193
- - "lib/middleware/database_middleware.rb"
194
-
195
- # Offense count: 29
196
- ThreadSafety/ClassInstanceVariable:
197
- Exclude:
198
- - "lib/familia/base.rb"
199
- - "lib/familia/horreum/class_methods.rb"
200
- - "lib/familia/version.rb"
201
-
202
- # Offense count: 2
203
- # This cop supports unsafe autocorrection (--autocorrect-all).
204
- # Configuration parameters: EnforcedStyle.
205
- # SupportedStyles: literals, strict
206
- ThreadSafety/MutableClassInstanceVariable:
207
- Exclude:
208
- - "lib/familia/connection.rb"
@@ -1,192 +0,0 @@
1
- # Connection Pooling with Familia
2
-
3
- Familia uses a connection provider pattern for efficient connection pooling. This guide shows how to configure pools for optimal performance with multiple logical databases.
4
-
5
- ## Key Concepts
6
-
7
- - **Connection Provider Contract**: Your provider MUST return connections already on the correct logical database. Familia will NOT issue SELECT commands.
8
- - **URI-based Selection**: Familia passes normalized URIs (e.g., `redis://localhost:6379/2`) encoding the logical database.
9
- - **One Pool Per Database**: Each unique logical database requires its own connection pool.
10
-
11
- ## Basic Setup
12
-
13
- ### Simple Connection Pool
14
-
15
- ```ruby
16
- require 'connection_pool'
17
-
18
- class MyApp
19
- @pools = {}
20
-
21
- Familia.connection_provider = lambda do |uri|
22
- parsed = URI.parse(uri)
23
- pool_key = "#{parsed.host}:#{parsed.port}/#{parsed.db || 0}"
24
-
25
- @pools[pool_key] ||= ConnectionPool.new(size: 10, timeout: 5) do
26
- Redis.new(
27
- host: parsed.host,
28
- port: parsed.port,
29
- db: parsed.db || 0
30
- )
31
- end
32
-
33
- @pools[pool_key].with { |conn| conn }
34
- end
35
- end
36
- ```
37
-
38
- ### Multi-Database Configuration
39
-
40
- ```ruby
41
- class MyApp
42
- POOL_CONFIGS = {
43
- 0 => { size: 20 }, # Main database
44
- 1 => { size: 5 }, # Analytics
45
- 2 => { size: 10 } # Cache
46
- }.freeze
47
-
48
- @pools = {}
49
-
50
- Familia.connection_provider = lambda do |uri|
51
- parsed = URI.parse(uri)
52
- db = parsed.db || 0
53
- pool_key = "#{parsed.host}:#{parsed.port}/#{db}"
54
-
55
- @pools[pool_key] ||= begin
56
- config = POOL_CONFIGS[db] || { size: 5 }
57
- ConnectionPool.new(timeout: 5, **config) do
58
- Redis.new(host: parsed.host, port: parsed.port, db: db)
59
- end
60
- end
61
-
62
- @pools[pool_key].with { |conn| conn }
63
- end
64
- end
65
- ```
66
-
67
- ### Production Setup with Roda
68
-
69
- ```ruby
70
- # config/familia.rb
71
- class FamiliaPoolManager
72
- include Singleton
73
-
74
- def initialize
75
- @pools = {}
76
- end
77
-
78
- def get_connection(uri)
79
- parsed = URI.parse(uri)
80
- pool_key = "#{parsed.host}:#{parsed.port}/#{parsed.db || 0}"
81
-
82
- @pools[pool_key] ||= ConnectionPool.new(
83
- size: pool_size_for_environment,
84
- timeout: 5
85
- ) do
86
- Redis.new(
87
- host: parsed.host,
88
- port: parsed.port,
89
- db: parsed.db || 0,
90
- timeout: 1,
91
- reconnect_attempts: 3
92
- )
93
- end
94
-
95
- @pools[pool_key].with { |conn| conn }
96
- end
97
-
98
- private
99
-
100
- def pool_size_for_environment
101
- if defined?(Sidekiq)
102
- Sidekiq.options[:concurrency] + 2
103
- else
104
- ENV.fetch('WEB_CONCURRENCY', 5).to_i + 2
105
- end
106
- end
107
- end
108
-
109
- # Configure at application startup
110
- Familia.connection_provider = lambda do |uri|
111
- FamiliaPoolManager.instance.get_connection(uri)
112
- end
113
-
114
- # In your Roda app
115
- class App < Roda
116
- plugin :hooks
117
-
118
- before do
119
- # Familia pools are automatically used via connection_provider
120
- end
121
- end
122
- ```
123
-
124
- ## Model Configuration
125
-
126
- Configure models to use different logical databases:
127
-
128
- ```ruby
129
- class Customer < Familia::Horreum
130
- self.logical_database = 0 # Main application data
131
- field :name, :email
132
- end
133
-
134
- class Analytics < Familia::Horreum
135
- self.logical_database = 1 # Analytics data
136
- field :event_type, :timestamp
137
- end
138
-
139
- class Session < Familia::Horreum
140
- self.logical_database = 2 # Session/cache data
141
- feature :expiration
142
- default_expiration 1.hour
143
- field :user_id, :data
144
- end
145
- ```
146
-
147
- ## Performance Benefits
148
-
149
- Without connection pooling, each operation triggers database switches:
150
- ```
151
- SET key value # Connection on DB 0
152
- SELECT 2 # Switch to DB 2
153
- SET key2 value2 # Now on DB 2
154
- SELECT 0 # Switch back
155
- ```
156
-
157
- With proper pooling, connections stay on the correct database:
158
- ```
159
- SET key value # Connection already on DB 0
160
- SET key2 value2 # Different connection, already on DB 2
161
- ```
162
-
163
- ## Pool Sizing Guidelines
164
-
165
- - **Web Applications**: `threads + 2`
166
- - **Background Jobs**: `concurrency + 2`
167
- - **High Traffic DBs**: Scale up based on usage patterns
168
-
169
- ## Testing and Debugging
170
-
171
- Enable debug mode to verify correct database selection:
172
- ```ruby
173
- Familia.debug = true
174
- ```
175
-
176
- Test concurrent access:
177
- ```ruby
178
- threads = 10.times.map do |i|
179
- Thread.new do
180
- 100.times { |j| MyModel.create(value: "test-#{i}-#{j}") }
181
- end
182
- end
183
- threads.each(&:join)
184
- ```
185
-
186
- ## Best Practices
187
-
188
- - Return connections already on the correct database
189
- - Use one pool per unique logical database
190
- - Implement thread-safe pool creation
191
- - Monitor pool usage and adjust sizes accordingly
192
- - Use the `connection_pool` gem for production reliability