familia 2.0.0.pre19 → 2.0.0.pre22

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 (370) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/claude-code-review.yml +4 -9
  3. data/.github/workflows/code-smells.yml +64 -3
  4. data/.pre-commit-config.yaml +8 -6
  5. data/.reek.yml +10 -9
  6. data/.rubocop.yml +4 -0
  7. data/.talismanrc +5 -1
  8. data/CHANGELOG.rst +220 -112
  9. data/CLAUDE.md +28 -1
  10. data/Gemfile +1 -1
  11. data/Gemfile.lock +20 -17
  12. data/bin/try +16 -0
  13. data/bin/tryouts +16 -0
  14. data/docs/1106-participates_in-bidirectional-solution.md +129 -0
  15. data/docs/guides/encryption.md +486 -0
  16. data/docs/guides/feature-encrypted-fields.md +123 -7
  17. data/docs/guides/feature-expiration.md +161 -117
  18. data/docs/guides/feature-external-identifiers.md +415 -443
  19. data/docs/guides/feature-object-identifiers.md +400 -269
  20. data/docs/guides/feature-quantization.md +120 -6
  21. data/docs/guides/feature-relationships-indexing.md +318 -0
  22. data/docs/guides/feature-relationships-methods.md +146 -604
  23. data/docs/guides/feature-relationships-participation.md +263 -0
  24. data/docs/guides/feature-relationships.md +118 -136
  25. data/docs/guides/feature-system-devs.md +176 -693
  26. data/docs/guides/feature-system.md +119 -6
  27. data/docs/guides/feature-transient-fields.md +81 -0
  28. data/docs/guides/field-system.md +778 -0
  29. data/docs/guides/index.md +32 -15
  30. data/docs/guides/logging.md +187 -0
  31. data/docs/guides/optimized-loading.md +674 -0
  32. data/docs/guides/thread-safety-monitoring.md +61 -0
  33. data/docs/guides/{time-utilities.md → time-literals.md} +12 -12
  34. data/docs/migrating/v2.0.0-pre22.md +241 -0
  35. data/docs/overview.md +7 -9
  36. data/docs/reference/api-technical.md +267 -320
  37. data/examples/autoloader/mega_customer/features/deprecated_fields.rb +2 -0
  38. data/examples/autoloader/mega_customer/safe_dump_fields.rb +2 -0
  39. data/examples/autoloader/mega_customer.rb +2 -0
  40. data/examples/datatype_standalone.rb +4 -3
  41. data/examples/encrypted_fields.rb +2 -1
  42. data/examples/json_usage_patterns.rb +2 -0
  43. data/examples/relationships.rb +3 -0
  44. data/examples/safe_dump.rb +2 -1
  45. data/examples/sampling_demo.rb +53 -0
  46. data/examples/single_connection_transaction_confusions.rb +2 -1
  47. data/familia.gemspec +2 -1
  48. data/lib/familia/base.rb +2 -0
  49. data/lib/familia/connection/behavior.rb +2 -0
  50. data/lib/familia/connection/handlers.rb +2 -0
  51. data/lib/familia/connection/individual_command_proxy.rb +2 -0
  52. data/lib/familia/connection/middleware.rb +34 -24
  53. data/lib/familia/connection/operation_core.rb +3 -2
  54. data/lib/familia/connection/operations.rb +2 -0
  55. data/lib/familia/connection/pipelined_core.rb +3 -3
  56. data/lib/familia/connection/transaction_core.rb +69 -2
  57. data/lib/familia/connection.rb +18 -3
  58. data/lib/familia/data_type/class_methods.rb +3 -1
  59. data/lib/familia/data_type/connection.rb +2 -0
  60. data/lib/familia/data_type/database_commands.rb +2 -0
  61. data/lib/familia/data_type/serialization.rb +79 -52
  62. data/lib/familia/data_type/settings.rb +2 -0
  63. data/lib/familia/data_type/types/counter.rb +2 -0
  64. data/lib/familia/data_type/types/hashkey.rb +7 -5
  65. data/lib/familia/data_type/types/listkey.rb +2 -0
  66. data/lib/familia/data_type/types/lock.rb +2 -0
  67. data/lib/familia/data_type/types/sorted_set.rb +7 -10
  68. data/lib/familia/data_type/types/stringkey.rb +24 -0
  69. data/lib/familia/data_type/types/unsorted_set.rb +2 -0
  70. data/lib/familia/data_type.rb +2 -0
  71. data/lib/familia/encryption/encrypted_data.rb +4 -2
  72. data/lib/familia/encryption/manager.rb +2 -0
  73. data/lib/familia/encryption/provider.rb +2 -0
  74. data/lib/familia/encryption/providers/aes_gcm_provider.rb +2 -0
  75. data/lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb +2 -0
  76. data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +2 -0
  77. data/lib/familia/encryption/registry.rb +2 -0
  78. data/lib/familia/encryption/request_cache.rb +2 -0
  79. data/lib/familia/encryption.rb +9 -2
  80. data/lib/familia/errors.rb +2 -0
  81. data/lib/familia/features/autoloader.rb +2 -0
  82. data/lib/familia/features/encrypted_fields/concealed_string.rb +2 -0
  83. data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +4 -0
  84. data/lib/familia/features/encrypted_fields.rb +2 -2
  85. data/lib/familia/features/expiration/extensions.rb +3 -1
  86. data/lib/familia/features/expiration.rb +12 -4
  87. data/lib/familia/features/external_identifier.rb +62 -7
  88. data/lib/familia/features/object_identifier.rb +49 -0
  89. data/lib/familia/features/quantization.rb +3 -1
  90. data/lib/familia/features/relationships/README.md +3 -1
  91. data/lib/familia/features/relationships/collection_operations.rb +2 -0
  92. data/lib/familia/features/relationships/indexing/multi_index_generators.rb +138 -9
  93. data/lib/familia/features/relationships/indexing/rebuild_strategies.rb +479 -0
  94. data/lib/familia/features/relationships/indexing/unique_index_generators.rb +97 -21
  95. data/lib/familia/features/relationships/indexing.rb +3 -0
  96. data/lib/familia/features/relationships/indexing_relationship.rb +3 -1
  97. data/lib/familia/features/relationships/participation/participant_methods.rb +131 -14
  98. data/lib/familia/features/relationships/participation/rebuild_strategies.md +41 -0
  99. data/lib/familia/features/relationships/participation/target_methods.rb +6 -6
  100. data/lib/familia/features/relationships/participation.rb +155 -69
  101. data/lib/familia/features/relationships/participation_membership.rb +69 -0
  102. data/lib/familia/features/relationships/participation_relationship.rb +34 -6
  103. data/lib/familia/features/relationships/score_encoding.rb +2 -0
  104. data/lib/familia/features/relationships.rb +5 -3
  105. data/lib/familia/features/safe_dump.rb +2 -0
  106. data/lib/familia/features/transient_fields/redacted_string.rb +2 -0
  107. data/lib/familia/features/transient_fields/single_use_redacted_string.rb +2 -0
  108. data/lib/familia/features/transient_fields/transient_field_type.rb +5 -3
  109. data/lib/familia/features/transient_fields.rb +2 -0
  110. data/lib/familia/features.rb +2 -0
  111. data/lib/familia/field_type.rb +3 -1
  112. data/lib/familia/horreum/connection.rb +17 -1
  113. data/lib/familia/horreum/database_commands.rb +8 -1
  114. data/lib/familia/horreum/definition.rb +16 -6
  115. data/lib/familia/horreum/management.rb +353 -52
  116. data/lib/familia/horreum/persistence.rb +179 -108
  117. data/lib/familia/horreum/related_fields.rb +2 -0
  118. data/lib/familia/horreum/serialization.rb +23 -4
  119. data/lib/familia/horreum/settings.rb +2 -0
  120. data/lib/familia/horreum/utils.rb +2 -0
  121. data/lib/familia/horreum.rb +15 -1
  122. data/lib/familia/identifier_extractor.rb +3 -1
  123. data/lib/familia/instrumentation.rb +156 -0
  124. data/lib/familia/json_serializer.rb +2 -0
  125. data/lib/familia/logging.rb +92 -32
  126. data/lib/familia/refinements/dear_json.rb +2 -0
  127. data/lib/familia/refinements/stylize_words.rb +2 -14
  128. data/lib/familia/refinements/time_literals.rb +2 -0
  129. data/lib/familia/refinements.rb +2 -0
  130. data/lib/familia/secure_identifier.rb +10 -2
  131. data/lib/familia/settings.rb +2 -0
  132. data/lib/familia/thread_safety/instrumented_mutex.rb +166 -0
  133. data/lib/familia/thread_safety/monitor.rb +328 -0
  134. data/lib/familia/utils.rb +13 -0
  135. data/lib/familia/verifiable_identifier.rb +3 -1
  136. data/lib/familia/version.rb +3 -1
  137. data/lib/familia.rb +31 -4
  138. data/lib/middleware/database_command_counter.rb +152 -0
  139. data/lib/middleware/database_logger.rb +295 -170
  140. data/lib/multi_result.rb +61 -31
  141. data/try/edge_cases/empty_identifiers_try.rb +2 -0
  142. data/try/edge_cases/hash_symbolization_try.rb +2 -0
  143. data/try/edge_cases/json_serialization_try.rb +2 -0
  144. data/try/edge_cases/legacy_data_detection/deserialization_edge_cases_try.rb +4 -0
  145. data/try/edge_cases/race_conditions_try.rb +4 -0
  146. data/try/edge_cases/reserved_keywords_try.rb +4 -0
  147. data/try/edge_cases/string_coercion_try.rb +2 -0
  148. data/try/edge_cases/ttl_side_effects_try.rb +4 -0
  149. data/try/features/count_any_edge_cases_try.rb +486 -0
  150. data/try/features/count_any_methods_try.rb +197 -0
  151. data/try/features/encrypted_fields/aad_protection_try.rb +4 -0
  152. data/try/features/encrypted_fields/concealed_string_core_try.rb +4 -0
  153. data/try/features/encrypted_fields/context_isolation_try.rb +4 -0
  154. data/try/features/encrypted_fields/encrypted_fields_core_try.rb +33 -0
  155. data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +4 -0
  156. data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +4 -0
  157. data/try/features/encrypted_fields/encrypted_fields_security_try.rb +4 -0
  158. data/try/features/encrypted_fields/error_conditions_try.rb +4 -0
  159. data/try/features/encrypted_fields/fresh_key_derivation_try.rb +4 -0
  160. data/try/features/encrypted_fields/fresh_key_try.rb +4 -0
  161. data/try/features/encrypted_fields/key_rotation_try.rb +4 -0
  162. data/try/features/encrypted_fields/memory_security_try.rb +4 -0
  163. data/try/features/encrypted_fields/missing_current_key_version_try.rb +4 -0
  164. data/try/features/encrypted_fields/nonce_uniqueness_try.rb +4 -0
  165. data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +4 -0
  166. data/try/features/encrypted_fields/thread_safety_try.rb +4 -0
  167. data/try/features/encrypted_fields/universal_serialization_safety_try.rb +4 -0
  168. data/try/features/encryption/config_persistence_try.rb +4 -0
  169. data/try/features/encryption/core_try.rb +4 -0
  170. data/try/features/encryption/instance_variable_scope_try.rb +4 -0
  171. data/try/features/encryption/module_loading_try.rb +4 -0
  172. data/try/features/encryption/providers/aes_gcm_provider_try.rb +4 -0
  173. data/try/features/encryption/providers/xchacha20_poly1305_provider_try.rb +4 -0
  174. data/try/features/encryption/roundtrip_validation_try.rb +4 -0
  175. data/try/features/encryption/secure_memory_handling_try.rb +4 -0
  176. data/try/features/expiration/expiration_try.rb +4 -0
  177. data/try/features/external_identifier/external_identifier_try.rb +305 -8
  178. data/try/features/feature_dependencies_try.rb +2 -0
  179. data/try/features/feature_improvements_try.rb +2 -0
  180. data/try/features/field_groups_try.rb +2 -0
  181. data/try/features/object_identifier/object_identifier_integration_try.rb +12 -9
  182. data/try/features/object_identifier/object_identifier_try.rb +140 -0
  183. data/try/features/quantization/quantization_try.rb +4 -0
  184. data/try/features/real_feature_integration_try.rb +2 -0
  185. data/try/features/relationships/indexing_commands_verification_try.rb +2 -0
  186. data/try/features/relationships/indexing_rebuild_try.rb +606 -0
  187. data/try/features/relationships/indexing_try.rb +2 -0
  188. data/try/features/relationships/participation_bidirectional_try.rb +242 -0
  189. data/try/features/relationships/participation_commands_verification_spec.rb +4 -0
  190. data/try/features/relationships/participation_commands_verification_try.rb +2 -0
  191. data/try/features/relationships/participation_performance_improvements_try.rb +11 -9
  192. data/try/features/relationships/participation_reverse_index_try.rb +15 -13
  193. data/try/features/relationships/participation_target_class_resolution_try.rb +209 -0
  194. data/try/features/relationships/participation_unresolved_target_try.rb +109 -0
  195. data/try/features/relationships/relationships_api_changes_try.rb +2 -0
  196. data/try/features/relationships/relationships_edge_cases_try.rb +4 -0
  197. data/try/features/relationships/relationships_performance_minimal_try.rb +4 -0
  198. data/try/features/relationships/relationships_performance_simple_try.rb +4 -0
  199. data/try/features/relationships/relationships_performance_try.rb +4 -0
  200. data/try/features/relationships/relationships_performance_working_try.rb +4 -0
  201. data/try/features/relationships/relationships_try.rb +6 -4
  202. data/try/features/safe_dump/safe_dump_advanced_try.rb +4 -0
  203. data/try/features/safe_dump/safe_dump_try.rb +4 -0
  204. data/try/features/transient_fields/redacted_string_try.rb +2 -0
  205. data/try/features/transient_fields/refresh_reset_try.rb +3 -0
  206. data/try/features/transient_fields/simple_refresh_test.rb +3 -0
  207. data/try/features/transient_fields/single_use_redacted_string_try.rb +2 -0
  208. data/try/features/transient_fields/transient_fields_core_try.rb +4 -0
  209. data/try/features/transient_fields/transient_fields_integration_try.rb +4 -0
  210. data/try/integration/connection/fiber_context_preservation_try.rb +4 -0
  211. data/try/integration/connection/handler_constraints_try.rb +4 -0
  212. data/try/integration/connection/isolated_dbclient_try.rb +4 -0
  213. data/try/integration/connection/middleware_reconnect_try.rb +2 -0
  214. data/try/integration/connection/operation_mode_guards_try.rb +4 -0
  215. data/try/integration/connection/pipeline_fallback_integration_try.rb +3 -0
  216. data/try/integration/connection/pools_try.rb +4 -0
  217. data/try/integration/connection/responsibility_chain_tracking_try.rb +4 -0
  218. data/try/integration/connection/transaction_fallback_integration_try.rb +4 -0
  219. data/try/integration/connection/transaction_mode_permissive_try.rb +4 -0
  220. data/try/integration/connection/transaction_mode_strict_try.rb +4 -0
  221. data/try/integration/connection/transaction_mode_warn_try.rb +4 -0
  222. data/try/integration/connection/transaction_modes_try.rb +4 -0
  223. data/try/integration/conventional_inheritance_try.rb +4 -0
  224. data/try/integration/create_method_try.rb +4 -0
  225. data/try/integration/cross_component_try.rb +4 -0
  226. data/try/integration/data_types/datatype_pipelines_try.rb +9 -3
  227. data/try/integration/data_types/datatype_transactions_try.rb +17 -7
  228. data/try/integration/database_consistency_try.rb +4 -0
  229. data/try/integration/familia_extended_try.rb +4 -0
  230. data/try/integration/familia_members_methods_try.rb +4 -0
  231. data/try/integration/models/customer_safe_dump_try.rb +4 -0
  232. data/try/integration/models/customer_try.rb +7 -3
  233. data/try/integration/models/datatype_base_try.rb +4 -0
  234. data/try/integration/models/familia_object_try.rb +4 -0
  235. data/try/integration/persistence_operations_try.rb +4 -0
  236. data/try/integration/relationships_persistence_round_trip_try.rb +17 -14
  237. data/try/integration/save_methods_consistency_try.rb +241 -0
  238. data/try/integration/scenarios_try.rb +4 -0
  239. data/try/integration/secure_identifier_try.rb +4 -0
  240. data/try/integration/transaction_safety_core_try.rb +176 -0
  241. data/try/integration/transaction_safety_workflow_try.rb +291 -0
  242. data/try/integration/verifiable_identifier_try.rb +4 -0
  243. data/try/investigation/pipeline_routing/README.md +228 -0
  244. data/try/performance/benchmarks_try.rb +4 -0
  245. data/try/performance/transaction_safety_benchmark_try.rb +238 -0
  246. data/try/support/benchmarks/deserialization_benchmark.rb +3 -1
  247. data/try/support/benchmarks/deserialization_correctness_test.rb +3 -1
  248. data/try/support/debugging/cache_behavior_tracer.rb +4 -0
  249. data/try/support/debugging/debug_aad_process.rb +3 -0
  250. data/try/support/debugging/debug_concealed_internal.rb +3 -0
  251. data/try/support/debugging/debug_concealed_reveal.rb +3 -0
  252. data/try/support/debugging/debug_context_aad.rb +3 -0
  253. data/try/support/debugging/debug_context_simple.rb +3 -0
  254. data/try/support/debugging/debug_cross_context.rb +3 -0
  255. data/try/support/debugging/debug_database_load.rb +3 -0
  256. data/try/support/debugging/debug_encrypted_json_check.rb +3 -0
  257. data/try/support/debugging/debug_encrypted_json_step_by_step.rb +3 -0
  258. data/try/support/debugging/debug_exists_lifecycle.rb +3 -0
  259. data/try/support/debugging/debug_field_decrypt.rb +3 -0
  260. data/try/support/debugging/debug_fresh_cross_context.rb +3 -0
  261. data/try/support/debugging/debug_load_path.rb +3 -0
  262. data/try/support/debugging/debug_method_definition.rb +3 -0
  263. data/try/support/debugging/debug_method_resolution.rb +3 -0
  264. data/try/support/debugging/debug_minimal.rb +3 -0
  265. data/try/support/debugging/debug_provider.rb +3 -0
  266. data/try/support/debugging/debug_secure_behavior.rb +3 -0
  267. data/try/support/debugging/debug_string_class.rb +3 -0
  268. data/try/support/debugging/debug_test.rb +3 -0
  269. data/try/support/debugging/debug_test_design.rb +3 -0
  270. data/try/support/debugging/encryption_method_tracer.rb +4 -0
  271. data/try/support/debugging/provider_diagnostics.rb +4 -0
  272. data/try/support/helpers/test_cleanup.rb +4 -0
  273. data/try/support/helpers/test_helpers.rb +5 -0
  274. data/try/support/memory/memory_basic_test.rb +4 -0
  275. data/try/support/memory/memory_detailed_test.rb +4 -0
  276. data/try/support/memory/memory_search_for_string.rb +4 -0
  277. data/try/support/memory/test_actual_redactedstring_protection.rb +4 -0
  278. data/try/support/prototypes/atomic_saves_v1_context_proxy.rb +4 -0
  279. data/try/support/prototypes/atomic_saves_v2_connection_switching.rb +4 -0
  280. data/try/support/prototypes/atomic_saves_v3_connection_pool.rb +4 -0
  281. data/try/support/prototypes/atomic_saves_v4.rb +4 -0
  282. data/try/support/prototypes/lib/atomic_saves_v2_connection_switching_helpers.rb +4 -0
  283. data/try/support/prototypes/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -0
  284. data/try/support/prototypes/pooling/configurable_stress_test.rb +4 -0
  285. data/try/support/prototypes/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -0
  286. data/try/support/prototypes/pooling/lib/connection_pool_metrics.rb +4 -0
  287. data/try/support/prototypes/pooling/lib/connection_pool_stress_test.rb +4 -0
  288. data/try/support/prototypes/pooling/lib/connection_pool_threading_models.rb +4 -0
  289. data/try/support/prototypes/pooling/lib/visualize_stress_results.rb +4 -2
  290. data/try/support/prototypes/pooling/pool_siege.rb +4 -2
  291. data/try/support/prototypes/pooling/run_stress_tests.rb +4 -2
  292. data/try/thread_safety/README.md +496 -0
  293. data/try/thread_safety/class_connection_chain_race_try.rb +265 -0
  294. data/try/thread_safety/connection_chain_race_try.rb +148 -0
  295. data/try/thread_safety/encryption_manager_cache_race_try.rb +166 -0
  296. data/try/thread_safety/feature_registry_race_try.rb +226 -0
  297. data/try/thread_safety/fiber_pipeline_isolation_try.rb +235 -0
  298. data/try/thread_safety/fiber_transaction_isolation_try.rb +208 -0
  299. data/try/thread_safety/field_registration_race_try.rb +222 -0
  300. data/try/thread_safety/logger_initialization_race_try.rb +170 -0
  301. data/try/thread_safety/middleware_registration_race_try.rb +154 -0
  302. data/try/thread_safety/module_config_race_try.rb +175 -0
  303. data/try/thread_safety/secure_identifier_cache_race_try.rb +226 -0
  304. data/try/unit/core/autoloader_try.rb +4 -0
  305. data/try/unit/core/base_enhancements_try.rb +4 -0
  306. data/try/unit/core/connection_try.rb +4 -0
  307. data/try/unit/core/errors_try.rb +4 -0
  308. data/try/unit/core/extensions_try.rb +4 -0
  309. data/try/unit/core/familia_logger_try.rb +2 -0
  310. data/try/unit/core/familia_try.rb +4 -0
  311. data/try/unit/core/middleware_sampling_try.rb +335 -0
  312. data/try/unit/core/middleware_test_helpers_bug_try.rb +58 -0
  313. data/try/unit/core/middleware_thread_safety_try.rb +245 -0
  314. data/try/unit/core/middleware_try.rb +4 -0
  315. data/try/unit/core/settings_try.rb +4 -0
  316. data/try/unit/core/time_utils_try.rb +4 -0
  317. data/try/unit/core/tools_try.rb +4 -0
  318. data/try/unit/core/utils_try.rb +37 -0
  319. data/try/unit/data_types/boolean_try.rb +39 -22
  320. data/try/unit/data_types/counter_try.rb +4 -0
  321. data/try/unit/data_types/datatype_base_try.rb +4 -0
  322. data/try/unit/data_types/hash_try.rb +6 -2
  323. data/try/unit/data_types/list_try.rb +4 -0
  324. data/try/unit/data_types/lock_try.rb +4 -0
  325. data/try/unit/data_types/serialization_try.rb +386 -0
  326. data/try/unit/data_types/sorted_set_try.rb +4 -0
  327. data/try/unit/data_types/sorted_set_zadd_options_try.rb +4 -0
  328. data/try/unit/data_types/string_try.rb +4 -0
  329. data/try/unit/data_types/unsortedset_try.rb +4 -0
  330. data/try/unit/familia_resolve_class_try.rb +116 -0
  331. data/try/unit/horreum/auto_indexing_on_save_try.rb +5 -1
  332. data/try/unit/horreum/automatic_index_validation_try.rb +2 -0
  333. data/try/unit/horreum/base_try.rb +4 -0
  334. data/try/unit/horreum/class_methods_try.rb +4 -0
  335. data/try/unit/horreum/commands_try.rb +4 -0
  336. data/try/unit/horreum/defensive_initialization_try.rb +4 -0
  337. data/try/unit/horreum/destroy_related_fields_cleanup_try.rb +6 -1
  338. data/try/unit/horreum/enhanced_conflict_handling_try.rb +4 -0
  339. data/try/unit/horreum/field_categories_try.rb +4 -0
  340. data/try/unit/horreum/field_definition_try.rb +4 -0
  341. data/try/unit/horreum/initialization_try.rb +4 -0
  342. data/try/unit/horreum/json_type_preservation_try.rb +2 -0
  343. data/try/unit/horreum/optimized_loading_try.rb +156 -0
  344. data/try/unit/horreum/relations_try.rb +4 -0
  345. data/try/unit/horreum/serialization_persistent_fields_try.rb +4 -0
  346. data/try/unit/horreum/serialization_try.rb +4 -0
  347. data/try/unit/horreum/settings_try.rb +4 -0
  348. data/try/unit/horreum/unique_index_edge_cases_try.rb +4 -0
  349. data/try/unit/horreum/unique_index_guard_validation_try.rb +2 -0
  350. data/try/unit/middleware/database_command_counter_methods_try.rb +139 -0
  351. data/try/unit/middleware/database_logger_methods_try.rb +251 -0
  352. data/try/unit/refinements/dear_json_array_methods_try.rb +4 -0
  353. data/try/unit/refinements/dear_json_hash_methods_try.rb +4 -0
  354. data/try/unit/refinements/time_literals_numeric_methods_try.rb +4 -0
  355. data/try/unit/refinements/time_literals_string_methods_try.rb +4 -0
  356. data/try/unit/thread_safety_monitor_try.rb +149 -0
  357. metadata +69 -17
  358. data/.github/workflows/code-quality.yml +0 -138
  359. data/changelog.d/20251011_012003_delano_159_datatype_transaction_pipeline_support.rst +0 -91
  360. data/changelog.d/20251011_203905_delano_next.rst +0 -30
  361. data/changelog.d/20251011_212633_delano_next.rst +0 -13
  362. data/changelog.d/20251011_221253_delano_next.rst +0 -26
  363. data/docs/archive/FAMILIA_RELATIONSHIPS.md +0 -210
  364. data/docs/archive/FAMILIA_TECHNICAL.md +0 -823
  365. data/docs/archive/FAMILIA_UPDATE.md +0 -226
  366. data/docs/archive/README.md +0 -64
  367. data/docs/archive/api-reference.md +0 -333
  368. data/docs/guides/core-field-system.md +0 -806
  369. data/docs/guides/implementation.md +0 -276
  370. data/docs/guides/security-model.md +0 -183
@@ -0,0 +1,263 @@
1
+ # Relationships Participation Guide
2
+
3
+ Participation creates bidirectional associations between Familia objects with automatic reverse tracking, semantic scoring, and lifecycle management.
4
+
5
+ ## Core Concepts
6
+
7
+ Participation manages "belongs to" relationships where:
8
+ - **Membership has meaning** - Customer owns Domains, User belongs to Teams
9
+ - **Scores have semantic value** - Priority, timestamps, permissions
10
+ - **Bidirectional tracking** - Both sides know about the relationship
11
+ - **Lifecycle matters** - Automatic cleanup on destroy
12
+
13
+ ## Basic Usage
14
+
15
+ ```ruby
16
+ class Domain < Familia::Horreum
17
+ feature :relationships
18
+ field :created_at
19
+
20
+ participates_in Customer, :domains, score: :created_at
21
+ end
22
+
23
+ class Customer < Familia::Horreum
24
+ feature :relationships
25
+ # sorted_set :domains created automatically
26
+ end
27
+
28
+ # Bidirectional relationship management
29
+ customer.add_domains_instance(domain) # Add with timestamp score
30
+ domain.in_customer_domains?(customer) # => true
31
+ domain.customer_instances # => [customer]
32
+ ```
33
+
34
+ ## Collection Types
35
+
36
+ ### Sorted Set (Default)
37
+
38
+ Ordered collections with semantic scores:
39
+
40
+ ```ruby
41
+ participates_in Project, :tasks, score: :priority
42
+
43
+ project.tasks.range(0, 4, order: 'DESC') # Top 5 by priority
44
+ task.score_in_project_tasks(project) # Get current score
45
+ ```
46
+
47
+ ### Unsorted Set
48
+
49
+ Simple membership without ordering:
50
+
51
+ ```ruby
52
+ participates_in Team, :members, type: :set
53
+
54
+ team.members.member?(user.identifier) # Fast O(1) check
55
+ ```
56
+
57
+ ### List
58
+
59
+ Ordered sequences:
60
+
61
+ ```ruby
62
+ participates_in Playlist, :songs, type: :list
63
+
64
+ song.position_in_playlist_songs(playlist) # Get position
65
+ ```
66
+
67
+ ## Scoring Strategies
68
+
69
+ ### Field-Based
70
+
71
+ ```ruby
72
+ participates_in Category, :articles, score: :published_at
73
+ participates_in User, :bookmarks, score: :rating
74
+ ```
75
+
76
+ ### Lambda-Based
77
+
78
+ ```ruby
79
+ participates_in Department, :employees, score: -> {
80
+ performance_rating * 100 + tenure_years * 10
81
+ }
82
+ ```
83
+
84
+ ### Permission Encoding
85
+
86
+ ```ruby
87
+ participates_in Customer, :domains, score: -> {
88
+ permission_encode(created_at, permission_bits)
89
+ }
90
+
91
+ customer.domains_with_permission(:read) # Query by permission
92
+ ```
93
+
94
+ ## Class-Level Participation
95
+
96
+ Track all instances automatically:
97
+
98
+ ```ruby
99
+ class User < Familia::Horreum
100
+ class_participates_in :all_users, score: :created_at
101
+ class_participates_in :active_users,
102
+ score: ->(u) { u.active? ? u.last_activity : 0 }
103
+ end
104
+
105
+ User.all_users.size # Total count
106
+ User.active_users.range(0, 9) # Top 10 active
107
+ ```
108
+
109
+ ## Multiple Collections
110
+
111
+ Participants can belong to multiple collections:
112
+
113
+ ```ruby
114
+ class User < Familia::Horreum
115
+ participates_in Team, :members
116
+ participates_in Team, :admins
117
+ participates_in Organization, :employees, as: :employers
118
+ end
119
+
120
+ # Separate methods per collection
121
+ user.add_to_team_members(team)
122
+ user.add_to_team_admins(team)
123
+
124
+ # Reverse methods union collections
125
+ user.team_instances # Union of members + admins
126
+ user.employers_instances # Custom name via 'as:'
127
+ ```
128
+
129
+ ## Lifecycle Management
130
+
131
+ ### Automatic Tracking
132
+
133
+ Familia maintains a reverse index for cleanup:
134
+
135
+ ```ruby
136
+ domain.participations.members
137
+ # => ["customer:cust_123:domains", "customer:cust_456:domains"]
138
+
139
+ domain.current_participations
140
+ # => [
141
+ # { collection_key: "customer:cust_123:domains", score: 1640995200 },
142
+ # { collection_key: "customer:cust_456:domains", score: 1640995300 }
143
+ # ]
144
+ ```
145
+
146
+ ### Cleanup
147
+
148
+ ```ruby
149
+ class Domain < Familia::Horreum
150
+ before_destroy :cleanup_relationships
151
+
152
+ def cleanup_relationships
153
+ # Automatic removal from all collections
154
+ super
155
+ end
156
+ end
157
+ ```
158
+
159
+ ## Advanced Patterns
160
+
161
+ ### Conditional Scoring
162
+
163
+ ```ruby
164
+ participates_in Project, :tasks, score: -> {
165
+ status == 'active' ? priority : 0
166
+ }
167
+
168
+ # Filter by score
169
+ active_tasks = project.tasks.range_by_score(1, '+inf')
170
+ ```
171
+
172
+ ### Time-Based Expiration
173
+
174
+ ```ruby
175
+ participates_in User, :sessions, score: :expires_at
176
+
177
+ # Query active sessions
178
+ now = Time.now.to_i
179
+ active = user.sessions.range_by_score(now, '+inf')
180
+ ```
181
+
182
+ ### Validation
183
+
184
+ ```ruby
185
+ def add_members_instance(user, score = nil)
186
+ raise "Team is full" if members.size >= max_members
187
+ raise "User not active" unless user.status == 'active'
188
+ super
189
+ end
190
+ ```
191
+
192
+ ## Performance Best Practices
193
+
194
+ ### Bulk Operations
195
+
196
+ ```ruby
197
+ # ✅ Efficient bulk add
198
+ customer.add_domains([domain1, domain2, domain3])
199
+
200
+ # ❌ Avoid loops
201
+ domains.each { |d| customer.add_domains_instance(d) }
202
+ ```
203
+
204
+ ### Pagination
205
+
206
+ ```ruby
207
+ # ✅ Paginated access
208
+ customer.domains.range(0, 19) # First 20
209
+ customer.domains.range(20, 39) # Next 20
210
+
211
+ # ❌ Loading all
212
+ customer.domains.to_a # Loads all IDs
213
+ ```
214
+
215
+ ### Direct Collection Access
216
+
217
+ ```ruby
218
+ # For IDs only
219
+ customer.domains.to_a # Just IDs
220
+ customer.domains.merge([id1, id2]) # Bulk ID operations
221
+
222
+ # For objects
223
+ domain.customer_instances # Efficient bulk loading
224
+ ```
225
+
226
+ ## Troubleshooting
227
+
228
+ ### Common Issues
229
+
230
+ **Method not found:**
231
+ - Ensure `feature :relationships` on both classes
232
+ - Verify `participates_in` declaration
233
+ - Check method naming patterns
234
+
235
+ **Inconsistent relationships:**
236
+ - Use transactions for complex operations
237
+ - Implement validation in overridden methods
238
+ - Monitor reverse index consistency
239
+
240
+ **Performance issues:**
241
+ - Use bulk operations
242
+ - Implement pagination
243
+ - Consider direct collection access for IDs
244
+
245
+ ### Debugging
246
+
247
+ ```ruby
248
+ # Check configuration
249
+ Domain.participation_relationships
250
+ # => [{ target_class: Customer, collection_name: :domains, ... }]
251
+
252
+ # Inspect participations
253
+ domain.current_participations
254
+
255
+ # Validate consistency
256
+ domain.validate_relationships!
257
+ ```
258
+
259
+ ## See Also
260
+
261
+ - [**Relationships Overview**](feature-relationships.md) - Core concepts
262
+ - [**Methods Reference**](feature-relationships-methods.md) - Complete API
263
+ - [**Indexing Guide**](feature-relationships-indexing.md) - Attribute lookups
@@ -1,200 +1,182 @@
1
1
  # Relationships Feature Guide
2
2
 
3
- The Relationships feature transforms how you manage object associations in Familia applications. Instead of manually maintaining foreign keys and indexes, relationships provide automatic bidirectional links, efficient queries, and Ruby-like collection syntax that makes working with related objects feel natural and intuitive.
4
-
5
- This guide provides a breadth-first introduction to the four core relationship capabilities: **participation**, **indexing**, **querying**, and **cascading operations**.
3
+ The Relationships feature provides automatic bidirectional associations between Familia objects, eliminating manual foreign key management while enabling efficient queries through Redis-native data structures.
6
4
 
7
5
  > [!TIP]
8
- > Enable relationships with `feature :relationships`, define associations with `participates_in`, and use clean Ruby syntax like `customer.domains << domain` to manage relationships.
9
-
10
- ## What Are Relationships?
6
+ > Enable with `feature :relationships` and define associations using `participates_in` for automatic method generation.
11
7
 
12
- Relationships automate object associations in Familia, eliminating manual foreign key management:
8
+ ## Quick Start
13
9
 
14
10
  ```ruby
15
- # Without relationships - manual and error-prone
16
- customer.domain_ids.add(domain.identifier)
17
- domain.customer_id = customer.identifier
18
-
19
- # With relationships - automatic and clean
20
- customer.domains << domain # Updates both sides automatically
21
- ```
22
-
23
- **Key Benefits:**
24
- - **Automatic bidirectional updates** - no manual synchronization
25
- - **Ruby-like syntax** - familiar `<<` and collection operations
26
- - **O(1) lookups** - efficient Valkey/Redis-backed indexing
27
- - **Lifecycle management** - automatic cleanup and maintenance
28
-
29
- ## Core Relationship Capabilities
30
-
31
- ### 1. Participation - Bidirectional Object Links
32
-
33
- Connect objects with automatic synchronization:
34
-
35
- ```ruby
36
- class User < Familia::Horreum
11
+ class Customer < Familia::Horreum
37
12
  feature :relationships
38
- set :teams # Collection holder
13
+ # Collection 'domains' created automatically
39
14
  end
40
15
 
41
- class Team < Familia::Horreum
16
+ class Domain < Familia::Horreum
42
17
  feature :relationships
43
- participates_in User, :teams # Declares participation
18
+ participates_in Customer, :domains
44
19
  end
45
20
 
46
- # Usage - automatic bidirectional updates
47
- user.teams << team
48
- team.in_user_teams?(user) # => true
21
+ # Automatic bidirectional relationship management
22
+ customer.add_domains_instance(domain) # Add relationship
23
+ domain.in_customer_domains?(customer) # => true
24
+ domain.customer_instances # => [customer]
49
25
  ```
50
26
 
51
- **Many-to-Many Example:**
27
+ ## Core Capabilities
28
+
29
+ ### Participation - Bidirectional Associations
30
+
31
+ Create semantic relationships between objects with automatic reverse tracking:
32
+
52
33
  ```ruby
53
- class Project < Familia::Horreum
54
- set :contributors, :reviewers
34
+ class User < Familia::Horreum
35
+ feature :relationships
36
+ participates_in Team, :members, score: :joined_at
37
+ participates_in Team, :admins
55
38
  end
56
39
 
57
- class Developer < Familia::Horreum
58
- participates_in Project, :contributors
59
- participates_in Project, :reviewers
60
- end
40
+ # Generated methods on Team (target)
41
+ team.add_members_instance(user) # Add single member
42
+ team.add_members([user1, user2]) # Bulk add
43
+ team.members.range(0, 9) # First 10 members
61
44
 
62
- project.contributors << alice # Alice contributes
63
- project.reviewers << bob # Bob reviews
45
+ # Generated methods on User (participant)
46
+ user.add_to_team_members(team) # Add self to team
47
+ user.in_team_admins?(team) # Check membership
48
+ user.team_instances # All teams (members + admins)
64
49
  ```
65
50
 
66
- ### 2. Indexing - Automatic Object Tracking
51
+ ### Indexing - Fast Attribute Lookups
67
52
 
68
- Enable O(1) lookups with automatic index management:
53
+ Enable O(1) field-based queries with automatic index management:
69
54
 
70
55
  ```ruby
71
56
  class User < Familia::Horreum
72
57
  feature :relationships
73
- field :email, :created_at
74
-
75
- # Global unique lookups
76
- class_indexed_by :email, :email_lookup
58
+ field :email, :username
77
59
 
78
- # Scored tracking collections
79
- class_participates_in :all_users, score: :created_at
60
+ # Global unique indexes (auto-managed on save/destroy)
61
+ unique_index :email, :email_lookup
62
+ unique_index :username, :username_lookup
80
63
  end
81
64
 
82
- # Automatic on save/destroy
83
- User.find_by_email("alice@example.com") # O(1) lookup
84
- User.all_users.range(0, 9) # Most recent 10 users
85
- ```
65
+ User.find_by_email("alice@example.com") # O(1) lookup
66
+ User.find_by_username("alice") # O(1) lookup
86
67
 
87
- **Relationship-Scoped Indexing:**
88
- ```ruby
89
- class Domain < Familia::Horreum
90
- participates_in Customer, :domains
91
- indexed_by :name, :domain_index, target: Customer # Unique per customer
68
+ # Scoped indexing (manual management required)
69
+ class Employee < Familia::Horreum
70
+ feature :relationships
71
+ unique_index :badge_number, :badge_index, within: Company
72
+ multi_index :department, :dept_index, within: Company
92
73
  end
93
74
 
94
- customer.find_by_name("example.com") # Find domain within this customer
75
+ employee.add_to_company_badge_index(company)
76
+ company.find_by_badge_number("12345") # Scoped lookup
77
+ company.find_all_by_department("engineering") # Multi-value
95
78
  ```
96
79
 
97
- ### 3. Querying - Ruby-like Collection Operations
80
+ ### Scoring - Semantic Ordering
98
81
 
99
- Work with relationships like standard Ruby collections:
82
+ Use scores for temporal tracking, priority systems, or custom ordering:
100
83
 
101
84
  ```ruby
102
- # Standard collection operations
103
- org.members << alice # Add relationship
104
- org.members.merge([id1, id2, id3]) # Bulk additions
105
- org.members.size # Count relationships
106
- org.members.empty? # Check if any exist
107
-
108
- # Set operations
109
- common = org1.members & org2.members # Intersection
110
- all = org1.members | org2.members # Union
111
-
112
- # Load actual objects when needed
113
- member_ids = org.members.to_a
114
- members = Person.multiget(*member_ids) # Efficient bulk loading
85
+ class Task < Familia::Horreum
86
+ feature :relationships
87
+ field :priority, :created_at
88
+
89
+ # Field-based scoring
90
+ participates_in Project, :tasks, score: :priority
91
+
92
+ # Lambda-based scoring
93
+ participates_in Sprint, :tasks, score: -> {
94
+ priority * 100 + (Time.now - created_at) / 3600
95
+ }
96
+ end
97
+
98
+ project.tasks.range(0, 4, order: 'DESC') # Top 5 by priority
99
+ sprint.tasks.range_by_score(500, '+inf') # High priority tasks
115
100
  ```
116
101
 
117
- > [!WARNING]
118
- > Collections store identifiers, not objects. Use `multiget` for efficient bulk loading.
102
+ ## Generated Method Reference
103
+
104
+ ### When Domain declares `participates_in Customer, :domains`
105
+
106
+ | Class | Method | Purpose |
107
+ |-------|--------|---------|
108
+ | **Customer** | `domains` | Access collection |
109
+ | | `add_domains_instance(domain)` | Add single item |
110
+ | | `add_domains([domains])` | Bulk add |
111
+ | | `remove_domains_instance(domain)` | Remove item |
112
+ | **Domain** | `add_to_customer_domains(customer)` | Add to collection |
113
+ | | `remove_from_customer_domains(customer)` | Remove from collection |
114
+ | | `in_customer_domains?(customer)` | Check membership |
115
+ | | `score_in_customer_domains(customer)` | Get score (sorted_set) |
116
+ | | `customer_instances` | Load all customers |
117
+ | | `customer_ids` | Get customer IDs |
118
+ | | `customer?` | Has any customers? |
119
+ | | `customer_count` | Count relationships |
119
120
 
120
- ### 4. Cascading Operations - Scored Relationships
121
+ ## Common Patterns
121
122
 
122
- Use scores for time-based tracking and priority systems:
123
+ ### Multiple Collections
123
124
 
124
125
  ```ruby
125
- class Timeline < Familia::Horreum
126
- feature :relationships
127
- sorted_set :events # Scored collection
128
- end
129
-
130
- class Event < Familia::Horreum
126
+ class User < Familia::Horreum
131
127
  feature :relationships
132
- field :timestamp, :priority
133
- participates_in Timeline, :events, score: :timestamp
128
+ participates_in Project, :contributors
129
+ participates_in Project, :reviewers
130
+ participates_in Organization, :employees, as: :employers
134
131
  end
135
132
 
136
- # Automatic scoring when relationships established
137
- timeline.events << event # Uses event.timestamp as score
133
+ # Separate methods per collection
134
+ user.add_to_project_contributors(project)
135
+ user.add_to_project_reviewers(project)
138
136
 
139
- # Time-based and priority queries
140
- recent = timeline.events.range_by_score((Time.now - 1.hour).to_i, '+inf')
141
- top_priority = project.tasks.range(0, 4, order: 'DESC') # Highest priority first
137
+ # Custom reverse method names
138
+ user.employers_instances # Instead of organization_instances
142
139
  ```
143
140
 
144
- **Common Scoring Patterns:**
145
- - **Timestamps** for chronological ordering
146
- - **Priority levels** for ranking systems
147
- - **User ratings** for recommendation systems
148
- - **Custom lambdas** for complex scoring logic
141
+ ### Class-Level Tracking
149
142
 
150
- ## Best Practices
151
-
152
- **Performance:**
153
- - Use `merge([id1, id2, id3])` for bulk additions
154
- - Use `multiget(*ids)` for efficient bulk loading
155
- - Use pagination: `collection.range(0, 9)` instead of loading all
156
-
157
- **Lifecycle Management:**
158
143
  ```ruby
159
- def destroy
160
- cleanup_relationships # Remove from all relationships first
161
- super
144
+ class Customer < Familia::Horreum
145
+ feature :relationships
146
+ class_participates_in :all_customers, score: :created_at
147
+ class_participates_in :premium_customers,
148
+ score: ->(c) { c.tier == 'premium' ? c.last_activity : 0 }
162
149
  end
163
- ```
164
150
 
165
- **Validation:**
166
- ```ruby
167
- def add_member(user_id)
168
- raise "Team is full" if members.size >= max_members
169
- members << user_id
170
- end
151
+ Customer.all_customers.size # Total count
152
+ Customer.premium_customers.range(0, 9) # Top 10 premium
171
153
  ```
172
154
 
173
- ## Common Patterns
155
+ ### Performance Optimization
174
156
 
175
- **Conditional Scoring:**
176
157
  ```ruby
177
- class_participates_in :active_users,
178
- score: ->(user) { user.active? ? user.last_activity : 0 }
179
- ```
158
+ # Bulk operations
159
+ team.add_members([user1, user2, user3])
180
160
 
181
- **Bidirectional Updates:**
182
- ```ruby
183
- # Automatic bidirectional
184
- customer.domains << domain
161
+ # Pagination
162
+ team.members.range(0, 19) # First 20
163
+ team.members.range(20, 39) # Next 20
185
164
 
186
- # Manual (avoid)
187
- customer.domains.add(domain.identifier)
165
+ # Direct ID access (no object loading)
166
+ team.members.to_a # Just IDs
167
+ team.member_instances # Load objects
188
168
  ```
189
169
 
190
- ---
170
+ ## Best Practices
191
171
 
192
- ## See Also
172
+ 1. **Use bulk methods** for multiple additions: `add_domains([d1, d2, d3])`
173
+ 2. **Paginate large collections**: `range(0, 19)` instead of loading all
174
+ 3. **Leverage reverse methods**: `domain.customer_instances` for efficient loading
175
+ 4. **Clean up on destroy**: Call `cleanup_relationships` before deletion
176
+ 5. **Validate before adding**: Check capacity/eligibility in overridden methods
193
177
 
194
- - **[Technical Reference](../reference/api-technical.md#relationships-feature-v200-pre7)** - Implementation details and advanced patterns
195
- - **[Relationship Methods Guide](feature-relationships-methods.md)** - Complete method reference
196
- - **[Feature System Guide](feature-system.md)** - Understanding Familia's feature architecture
197
- - **[Implementation Guide](implementation.md)** - Production deployment and configuration patterns
178
+ ## See Also
198
179
 
199
- > [!NOTE]
200
- > **Next Steps:** Once you're comfortable with basic relationships, explore the [Relationship Methods Guide](feature-relationships-methods.md) for detailed method references, or check the [Technical Reference](../reference/api-technical.md#relationships-feature-v200-pre7) for advanced patterns like permission encoding and performance optimization.
180
+ - [**Relationship Methods**](feature-relationships-methods.md) - Complete API reference
181
+ - [**Participation Guide**](feature-relationships-participation.md) - Deep dive into associations
182
+ - [**Indexing Guide**](feature-relationships-indexing.md) - Attribute lookup patterns