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
data/CHANGELOG.rst CHANGED
@@ -7,61 +7,222 @@ The format is based on `Keep a Changelog <https://keepachangelog.com/en/1.1.0/>`
7
7
 
8
8
  <!--scriv-insert-here-->
9
9
 
10
- .. _changelog-2.0.0.pre19:
10
+ .. _changelog-2.0.0.pre22:
11
+
12
+ 2.0.0.pre22 — 2025-12-03
13
+ ========================
14
+
15
+ - **ExternalIdentifier Format Flexibility**: The `external_identifier` feature now supports customizable format templates via the `format` option (e.g., `format: 'cust_%{id}'` or `format: 'api-%{id}'`). Default format remains `'ext_%{id}'`. Provides complete flexibility for various ID formatting needs including different prefixes, separators, URL paths, or no prefix at all.
11
16
 
12
- 2.0.0.pre19 2025-10-11
13
- =========================
17
+ - **Participation Relationships with Symbol/String Target Classes**: Fixed four bugs that occurred when calling `participates_in` with Symbol/String target class instead of Class object. Issues included NoMethodError during relationship definition (private method call), failures in `current_participations` (undefined `familia_name`), errors in `target_class_config_name` (undefined `config_name`), and confusing error messages for load order issues. All now properly resolve using `Familia.resolve_class` API with clear error messages for common issues.
18
+
19
+ - **Pipelined Bulk Loading Methods**: New `load_multi` and `load_multi_by_keys` methods enable efficient bulk object loading using Redis pipelining, reducing network round trips from N×2 commands to a single batch (up to 2× performance improvement). Methods maintain nil-return contract for missing objects and preserve input order.
20
+
21
+ - **Optional EXISTS Check Optimization**: The `find_by_dbkey` and `find_by_identifier` methods now accept `check_exists:` parameter (default: `true`) to optionally skip EXISTS check, reducing Redis commands from 2 to 1 per object. Maintains backwards compatibility and same nil-return behavior.
22
+
23
+ - **Parameter Consistency**: The `suffix` parameter in `find_by_identifier` is now a keyword parameter (was optional positional) for consistency with `check_exists`, following Ruby conventions.
14
24
 
15
25
  Added
16
26
  -----
17
27
 
18
- - **DataType Transaction and Pipeline Support** - DataType objects can now initiate transactions and pipelines independently, enabling atomic operations and batch command execution for both parent-owned and standalone DataType objects. `PR #160 <https://github.com/familia/familia/pull/160>`__. Key capabilities added:
28
+ - Bidirectional reverse collection methods for ``participates_in`` with ``_instances`` suffix (e.g., ``user.project_team_instances``, ``user.project_team_ids``). Supports union behavior for multiple collections and custom naming via ``as:`` parameter. Closes #179.
29
+
30
+ Changed
31
+ -------
32
+
33
+ - All Ruby files now include consistent headers with ``frozen_string_literal: true`` pragma for improved performance and memory efficiency. Headers follow the format: filename comment, blank comment line, frozen string literal pragma. Executable scripts properly place shebang first.
34
+
35
+ - Standardized DataType serialization to use JSON encoding for type preservation, matching Horreum field behavior. All primitive values (Integer, Boolean, String, Float, Hash, Array, nil) are now consistently serialized through JSON, ensuring types are preserved across the Redis storage boundary. Familia object references continue to use identifier extraction. Issue #190.
36
+
37
+ Fixed
38
+ -----
39
+
40
+ - Fixed critical race condition in mutex initialization for connection chain lazy loading. The mutex itself was being lazily initialized with ``||=``, which is not atomic and could result in multiple threads creating different mutex instances, defeating synchronization. Changed to eager initialization via ``Connection.included`` hook. (`lib/familia/horreum/connection.rb`)
41
+
42
+ - Fixed critical race condition in mutex initialization for logger lazy loading. Similar to connection chain issue, the logger mutex was lazily initialized with ``||=``. Changed to eager initialization at module definition time. (`lib/familia/logging.rb`)
43
+
44
+ - Fixed logger assignment atomicity issue where ``Familia.logger=`` set ``DatabaseLogger.logger`` outside the mutex synchronization block, potentially causing ``Familia.logger`` and ``DatabaseLogger.logger`` to be temporarily out of sync during concurrent access. Moved ``DatabaseLogger.logger`` assignment inside the synchronization block. (`lib/familia/logging.rb`)
45
+
46
+ - Added explicit return statement to ``Familia.logger`` method for robustness against future refactoring. (`lib/familia/logging.rb`)
19
47
 
20
- * ``transaction`` and ``pipelined`` methods for atomic MULTI/EXEC operations and batched command execution on all DataType classes
21
- * Connection chain pattern with Chain of Responsibility for DataType objects
22
- * Two new connection handlers: ``ParentDelegationHandler`` for owned DataTypes and ``StandaloneConnectionHandler`` for independent DataTypes
23
- * Enhanced ``direct_access`` method with automatic transaction/pipeline context detection
24
- * Shared ``Familia::Connection::Behavior`` module extracting common connection functionality
48
+ AI Assistance
49
+ -------------
25
50
 
26
- - New error hierarchy with ``PersistenceError``, ``HorreumError``, ``CreationError``, and ``OptimisticLockError`` classes for better error categorization and handling
27
- - ``watch``, ``unwatch``, and ``discard`` Redis commands for optimistic locking support
28
- - Enhanced database command logging with structured format for pipelined and transaction operations
29
- - ``save_fields`` method in Persistence module for selective field updates
51
+ - Claude Code (Opus 4, Sonnet 4.5): Implementation of bidirectional participation relationships, external identifier format flexibility, bulk loading optimization with pipelining, race condition fixes in mutex initialization, frozen string literal pragma automation (308 files), and DataType serialization standardization. Comprehensive test coverage and documentation throughout.
52
+
53
+ .. _changelog-2.0.0.pre21:
54
+
55
+ 2.0.0.pre21 — 2025-10-21
56
+ ========================
57
+
58
+ Added
59
+ -----
60
+
61
+ - Pipeline Routing Investigation: Created 7 diagnostic testcases in ``try/investigation/pipeline_routing/`` to investigate suspected middleware routing issue. Investigation revealed single-command pipelines don't have ' | ' separator (expected Array#join behavior), confirming no routing bug exists. Full analysis documented in ``CONCLUSION.md``.
30
62
 
31
63
  Changed
32
64
  -------
33
65
 
34
- - **Connection Architecture Refactored** - The ``Horreum::Connection`` module now includes ``Familia::Connection::Behavior``, eliminating code duplication by sharing URI normalization and connection creation methods between Horreum and DataType. DataType objects with ``logical_database`` settings now return clean URIs without custom port information (e.g., ``redis://127.0.0.1/3`` instead of ``redis://127.0.0.1:2525/3``), ensuring consistent URI representation across the library.
66
+ - **BREAKING**: Duration measurements now use integer microseconds instead of milliseconds. Instrumentation hooks and logging output have changed format:
67
+
68
+ - ``Familia.on_command`` receives ``duration`` in microseconds (was ``duration_ms`` in milliseconds)
69
+ - ``Familia.on_pipeline`` receives ``duration`` in microseconds (was ``duration_ms`` in milliseconds)
70
+ - ``Familia.on_lifecycle`` uses ``duration`` key in microseconds (was ``duration_ms`` in milliseconds)
71
+ - Log messages show ``duration=1234`` (microseconds) instead of ``duration_ms=1.23`` (milliseconds)
72
+
73
+ - Migration: Convert to milliseconds when needed: ``duration / 1000.0``
74
+
75
+ Fixed
76
+ -----
77
+
78
+ - Connection Chain Race Condition: Fixed race condition in connection chain initialization where concurrent calls could create multiple instances. Added thread-safe protection to ensure proper singleton behavior.
79
+
80
+ - Thread Safety Test Suite: Corrected test assertions to properly verify thread safety invariants.
81
+
82
+
83
+ AI Assistance
84
+ -------------
85
+
86
+ - Claude Code assisted with analyzing test failures, identifying and fixing the connection chain race condition with Mutex protection, correcting test assertions to verify proper thread safety invariants, and creating diagnostic testcases to investigate pipeline routing behavior.
87
+
88
+
89
+
90
+ .. _changelog-2.0.0.pre20:
91
+
92
+ 2.0.0.pre20 — 2025-10-20
93
+ ========================
94
+
95
+ Added
96
+ -----
97
+
98
+ - **Instrumentation Hooks**: New ``Familia::Instrumentation`` module provides hooks for Redis commands, pipeline operations, lifecycle events, and errors. Applications can now register callbacks for audit trails and performance monitoring.
99
+
100
+ - **DatabaseLogger Structured Mode**: Added ``DatabaseLogger.structured_logging`` mode that outputs Redis commands with structured key=value context instead of formatted string output.
101
+
102
+ - **DatabaseLogger Sampling**: Added ``DatabaseLogger.sample_rate`` for controlling log volume in high-traffic scenarios. Set to 0.1 for 10% sampling, 0.01 for 1% sampling, or nil to disable. Command capture for testing remains unaffected.
103
+
104
+ - **Lifecycle Logging**: Horreum initialize, save, and destroy operations now log with timing and structured context when ``FAMILIA_DEBUG`` is enabled.
105
+
106
+ - **Operational Logging**: TTL operations and serialization errors now include structured context for better debugging.
107
+
108
+ Changed
109
+ -------
110
+
111
+ - Refactored ``save`` and ``save_if_not_exists!`` to use shared helper methods (``prepare_for_save`` and ``persist_to_storage``) to eliminate code duplication and ensure consistency. Both methods now follow the same preparation and persistence logic, differing only in their concurrency control patterns (simple transaction vs. optimistic locking with WATCH).
112
+
113
+ - **Structured Logging**: Replaced internal logging methods (``Familia.ld``, ``Familia.le``) with structured logging methods (``Familia.debug``, ``Familia.info``, ``Familia.error``) that support keyword context for operational observability.
114
+
115
+ Removed
116
+ -------
35
117
 
36
- - **BREAKING**: Renamed ``Management.create`` to ``create!`` to follow Rails conventions and indicate potential exceptions
37
- - **BREAKING**: Updated ``save_if_not_exists`` to ``save_if_not_exists!`` with optimistic locking and automatic retry logic (up to 3 attempts)
38
- - Improved ``save`` method to use single atomic transaction encompassing field updates, expiration setting, index updates, and instance collection management
39
- - Enhanced ``delete!`` methods to work correctly within Redis transactions
40
- - Updated timestamp fields (``created``, ``updated``) to use float values instead of integers for higher precision
41
- - Refined log message formatting for better readability and debugging
42
- - Removed deprecated Connection instance methods for Horreum models in favor of class-level database operations
43
- - Clarified "pipelined" terminology throughout codebase (renamed from "pipeline" for consistency with Redis documentation)
118
+ - **Internal Methods**: Removed ``Familia.ld`` and ``Familia.le`` internal logging methods. These were never part of the public API.
44
119
 
45
120
  Fixed
46
121
  -----
47
122
 
48
- - Resolved atomicity issues and race conditions in save operations by consolidating all related operations into single Redis transaction with proper watch/multi/exec pattern and optimistic locking
49
- - Corrected transaction handling to ensure proper cleanup and error propagation
123
+ - Fixed ``save_if_not_exists!`` to perform the same operations as ``save`` when creating new objects. Previously, ``save_if_not_exists!`` omitted timestamp updates (``created``/``updated``), unique index validation (``guard_unique_indexes!``), and adding to the instances collection. Now both methods produce identical results when saving a new object, with ``save_if_not_exists`` only differing in its conditional existence check.
124
+
125
+ - Fixed ``save_if_not_exists!`` return value to correctly return ``true`` when successfully saving new objects. Previously returned ``false`` despite successful persistence due to incorrect handling of transaction result.
50
126
 
51
127
  Documentation
52
128
  -------------
53
129
 
54
- - Added comprehensive parameter documentation for database command methods including return value specifications and usage examples
130
+ - Streamlined inline documentation for ``save``, ``save_if_not_exists!``, and ``save_if_not_exists`` methods to be more concise, internally consistent, and non-redundant. Each method's documentation now stands on its own with clear, focused descriptions.
55
131
 
56
132
  AI Assistance
57
133
  -------------
58
134
 
59
- This feature was implemented with AI assistance from Claude Sonnet 4.5, Opus 4.1 (Anthropic).
135
+ - Claude Code identified the inconsistencies between ``save`` and ``save_if_not_exists!`` methods, implemented the fixes, refactored both methods to extract shared logic into private helper methods (``prepare_for_save`` and ``persist_to_storage``), and updated the documentation to be more concise and internally consistent.
136
+
137
+
138
+
139
+ This implementation was completed with significant AI assistance from Claude (Anthropic), including:
140
+
141
+ - Architecture design for the instrumentation hook system
142
+ - Implementation of structured logging methods with backward-compatible signatures
143
+ - Integration of hooks into DatabaseLogger middleware
144
+ - Bulk replacement of 51 logging method calls across 21 files
145
+ - Comprehensive code review and bug fixes (RedisClient::Config object vs hash handling)
146
+ - Documentation and changelog creation
147
+
148
+ The AI provided discussion, rubber ducking, code generation, testing strategy, and documentation throughout the implementation process.
149
+
150
+ Developer Notes
151
+ ---------------
152
+
153
+ This is a clean break for v2.0 with no deprecation warnings, as the removed methods were internal-only. Applications using the public API are unaffected.
154
+
155
+ **Migration**: No action required for external users. Internal development references to ``Familia.ld`` should use ``Familia.debug``, and ``Familia.le`` should use ``Familia.error``.
156
+
157
+ **New Capabilities**: Applications can now register instrumentation hooks for operational observability:
158
+
159
+ .. code-block:: ruby
160
+
161
+ # Enable structured logging with 10% sampling for production
162
+ Familia.logger = Rails.logger
163
+ DatabaseLogger.structured_logging = true
164
+ DatabaseLogger.sample_rate = 0.1 # Log 10% of commands
165
+
166
+ # Register hooks for audit trails
167
+ Familia.on_command do |cmd, duration_ms, context|
168
+ AuditLog.create!(
169
+ event: 'redis_command',
170
+ command: cmd,
171
+ duration_ms: duration_ms,
172
+ user_id: RequestContext.current_user_id
173
+ )
174
+ end
60
175
 
61
- * Architectural design of the connection chain pattern and shared Behavior module
62
- * Implementation of DataType-specific connection handlers (ParentDelegationHandler, StandaloneConnectionHandler) and comprehensive test coverage
63
- * Error hierarchy design and transaction atomicity optimization
64
- * Documentation enhancement and URI formatting debugging
176
+ Familia.on_lifecycle do |event, instance, context|
177
+ case event
178
+ when :save
179
+ AuditLog.create!(event: 'object_saved', object_id: instance.identifier)
180
+ when :destroy
181
+ AuditLog.create!(event: 'object_destroyed', object_id: instance.identifier)
182
+ end
183
+ end
184
+
185
+ .. _changelog-2.0.0.pre19:
186
+
187
+ 2.0.0.pre19 — 2025-10-13
188
+ ========================
189
+
190
+ Added
191
+ -----
192
+
193
+ - **DataType Transaction and Pipeline Support** - DataType objects can now initiate transactions and pipelines independently, enabling atomic operations and batch command execution. `PR #159 <https://github.com/familia/familia/pull/159>`_
194
+
195
+ * ``transaction`` and ``pipelined`` methods for all DataType classes
196
+ * Connection chain pattern with ``ParentDelegationHandler`` and ``StandaloneConnectionHandler``
197
+ * Enhanced ``direct_access`` method with automatic context detection
198
+ * Shared ``Familia::Connection::Behavior`` module for common functionality
199
+
200
+ - **Automatic Unique Index Validation** - Instance-scoped unique indexes now validate automatically in ``add_to_*`` methods, with transaction detection to prevent ``save()`` calls within MULTI/EXEC blocks
201
+
202
+ Changed
203
+ -------
204
+
205
+ - **Connection Architecture** - Refactored to share ``Familia::Connection::Behavior`` between Horreum and DataType, with cleaner URI construction for logical databases
206
+
207
+ - **Indexing Terminology** - Renamed internal ``target_class`` to ``scope_class`` throughout to clarify semantic role. Added explicit ``:within`` field to IndexingRelationship for clearer instance-scoped index handling
208
+
209
+ Fixed
210
+ -----
211
+
212
+ - URI formatting for DataType objects with logical database settings
213
+ - Transaction detection and validation flow for unique index operations
214
+
215
+ Documentation
216
+ -------------
217
+
218
+ - Enhanced ``save()`` method documentation with transaction restrictions
219
+ - Updated indexing and relationship cheatsheets with improved terminology
220
+ - Added comprehensive test coverage (48 new tests) for transactions, pipelines, and validation
221
+
222
+ AI Assistance
223
+ -------------
224
+
225
+ This release was implemented with assistance from Claude (Anthropic) for architectural design, test coverage, and systematic refactoring of terminology across the codebase.
65
226
 
66
227
 
67
228
  .. _changelog-2.0.0.pre18:
@@ -118,7 +279,7 @@ Documentation
118
279
  AI Assistance
119
280
  -------------
120
281
 
121
- - Claude Code (claude-sonnet-4-5) provided implementation guidance, identified the ``initialize_with_keyword_args`` falsy value bug, wrote comprehensive test suite, and coordinated multi-file changes across serialization, management, and base modules.
282
+ - Claude Code (claude-sonnet-4-5) provided implementation guidance, identified the ``initialize_with_keyword_args`` falsy value bug, wrote test coverage, and coordinated multi-file changes across serialization, management, and base modules.
122
283
 
123
284
  - Issue analysis, implementation guidance, test verification, and documentation for JSON serialization changes and encrypted field security fix.
124
285
 
@@ -132,19 +293,17 @@ AI Assistance
132
293
  Added
133
294
  -----
134
295
 
135
- - **SortedSet#add**: Full ZADD option support (NX, XX, GT, LT, CH) for atomic conditional operations and accurate change tracking. This enables proper index management with timestamp preservation, update-only operations, conditional score updates, and analytics tracking. Closes issue #135.
296
+ - **SortedSet#add** - Full ZADD option support (NX, XX, GT, LT, CH) for atomic conditional operations and accurate change tracking. Closes #135
136
297
 
137
298
  Fixed
138
299
  -----
139
300
 
140
- - Restored objid provenance tracking when loading objects from Redis. The ``ObjectIdentifier`` feature now infers the generator type (:uuid_v7, :uuid_v4, :hex) from the objid format, enabling dependent features like ``ExternalIdentifier`` to derive external identifiers from loaded objects. PR #131
301
+ - Restored objid provenance tracking when loading objects from Redis, enabling dependent features to derive external identifiers. PR #131
141
302
 
142
303
  AI Assistance
143
304
  -------------
144
305
 
145
- - Claude Code assisted with implementing the ``infer_objid_generator`` method and updating the setter logic in ``lib/familia/features/object_identifier.rb``.
146
-
147
- - Claude Code assisted with Redis ZADD option semantics research, mutual exclusivity validation design, comprehensive test case matrix creation (50+ test cases), and YAML documentation examples.
306
+ - Claude (Anthropic) assisted with objid generator inference implementation and ZADD option validation design.
148
307
 
149
308
  .. _changelog-2.0.0.pre16:
150
309
 
@@ -154,57 +313,29 @@ AI Assistance
154
313
  Added
155
314
  -----
156
315
 
157
- - Added support for instance-scoped unique indexes via ``unique_index`` with ``within:`` parameter. Issue #128
158
-
159
- Example: ``unique_index :badge_number, :badge_index, within: Company`` creates per-company unique badge lookups using HashKey DataType.
316
+ - **Instance-scoped unique indexes** via ``unique_index`` with ``within:`` parameter for per-scope unique lookups. Issue #128
160
317
 
161
318
  Changed
162
319
  -------
163
320
 
164
- - **BREAKING**: Consolidated relationships API by replacing ``tracked_in`` and ``member_of`` with unified ``participates_in`` method. PR #110
165
- - **BREAKING**: Renamed ``context_class`` terminology to ``target_class`` throughout relationships module for clarity
166
- - **BREAKING**: Removed ``tracking.rb`` and ``membership.rb`` modules, merged functionality into ``participation.rb``
167
- - **BREAKING**: Updated method names and configuration keys to use ``target`` instead of ``context`` terminology
168
- - Added ``bidirectional`` parameter to ``participates_in`` to control generation of convenience methods (default: true)
169
- - Added support for different collection types (sorted_set, set, list) in unified ``participates_in`` API
170
- - Renamed ``class_tracked_in`` to ``class_participates_in`` for consistency
171
-
172
- - Renamed DataType classes to avoid Ruby namespace confusion: ``Familia::String`` → ``Familia::StringKey``, ``Familia::List`` → ``Familia::ListKey``
173
- - Added dual registration for both traditional and explicit method names (``string``/``stringkey``, ``list``/``listkey``)
174
- - Updated ``Counter`` and ``Lock`` to inherit from ``StringKey`` instead of ``String``
321
+ - **BREAKING**: Consolidated relationships API - replaced ``tracked_in`` and ``member_of`` with unified ``participates_in`` method. PR #110
175
322
 
176
- - **BREAKING:** Renamed indexing API methods for clarity. Issue #128
323
+ - **BREAKING**: Renamed indexing API methods for clarity. Issue #128
324
+ - ``class_indexed_by`` → ``unique_index``
325
+ - ``indexed_by`` → ``multi_index``
326
+ - Changed ``multi_index`` to use ``UnsortedSet`` instead of ``SortedSet``
177
327
 
178
- - ``class_indexed_by`` → ``unique_index`` (1:1 field-to-object mapping via HashKey)
179
- - ``indexed_by`` → ``multi_index`` (1:many field-to-objects mapping via UnsortedSet)
180
- - Parameter ``target:`` → ``within:`` for consistency across both index types
181
-
182
- - **BREAKING:** Changed ``multi_index`` to use ``UnsortedSet`` instead of ``SortedSet``. Issue #128
183
-
184
- Multi-value indexes no longer include temporal scoring. This aligns with the design philosophy that indexing is for finding objects by attribute, not ordering them. Sort results in Ruby when needed: ``employees.sort_by(&:hire_date)``
328
+ - **DataType class renaming** to avoid Ruby namespace conflicts: ``Familia::String`` → ``Familia::StringKey``, ``Familia::List`` ``Familia::ListKey``, etc., with dual registration for compatibility
185
329
 
186
330
  Documentation
187
331
  -------------
188
332
 
189
- - Updated overview documentation to explain dual naming system and namespace safety benefits
190
- - Enhanced examples to demonstrate both traditional and explicit DataType method naming
191
-
192
- - Updated inline module documentation
193
- - ``Familia::Features::Relationships::Indexing`` with comprehensive examples, terminology guide, and design philosophy.
194
- - ``Familia::Features::Relationships::Participation`` to clarify differences from indexing module.
333
+ - Updated indexing and participation module documentation with comprehensive examples and design philosophy
195
334
 
196
335
  AI Assistance
197
336
  -------------
198
337
 
199
- - Comprehensive analysis of existing ``tracked_in`` and ``member_of`` implementations
200
- - Design and implementation of unified ``participates_in`` API integrating both functionalities
201
- - Systematic refactoring of codebase terminology from context to target
202
- - Complete test suite updates to verify API consolidation and new functionality
203
-
204
- - DataType class renaming and dual registration system implementation designed and developed with Claude Code assistance
205
- - All test updates and documentation enhancements created with AI support
206
-
207
- - Architecture design, implementation, test updates, and documentation for indexing API refactoring completed with Claude Code assistance. Issue #128
338
+ - Claude (Anthropic) assisted with relationship API consolidation, DataType renaming, and indexing API refactoring.
208
339
 
209
340
  .. _changelog-2.0.0.pre14:
210
341
 
@@ -214,19 +345,18 @@ AI Assistance
214
345
  Changed
215
346
  -------
216
347
 
217
- - **BREAKING CHANGE**: Renamed ``Familia::Refinements::TimeUtils`` to ``Familia::Refinements::TimeLiterals`` to better reflect the module's primary purpose of enabling numeric and string values to be treated as time unit literals (e.g., ``5.minutes``, ``"30m".in_seconds``). Functionality remains the same - only the module name has changed. Users must update their refinement usage from ``using Familia::Refinements::TimeUtils`` to ``using Familia::Refinements::TimeLiterals``.
348
+ - **BREAKING**: Renamed ``TimeUtils`` to ``TimeLiterals`` to better reflect module purpose. PR #100
218
349
 
219
350
  Fixed
220
351
  -----
221
352
 
222
- - Fixed ExternalIdentifier HashKey method calls by replacing incorrect ``.del()`` calls with ``.remove_field()`` in three critical locations: extid setter (cleanup old mapping when changing value), find_by_extid (cleanup orphaned mapping when object not found), and destroy! (cleanup mapping when object is destroyed). Added comprehensive test coverage for all scenarios to prevent regression. PR #100
353
+ - **CRITICAL**: Fixed Redis connection persistence for standalone DataType objects. PR #107
354
+ - Fixed ExternalIdentifier HashKey cleanup using correct ``remove_field()`` method. PR #100
223
355
 
224
356
  AI Assistance
225
357
  -------------
226
358
 
227
- - Claude Code helped rename TimeUtils to TimeLiterals throughout the codebase, including module name, file path, all usage references, and updating existing documentation.
228
- - Gemini 2.5 Flash wrote the inline docs for TimeLiterals based on a discussion re: naming rationale.
229
- - Claude Code fixed the ExternalIdentifier HashKey method bug, replacing incorrect ``.del()`` calls with proper ``.remove_field()`` calls, and implemented test coverage for the affected scenarios.
359
+ - Claude (Anthropic) and Gemini assisted with TimeLiterals refactoring and ExternalIdentifier fixes.
230
360
 
231
361
  .. _changelog-2.0.0.pre13:
232
362
 
@@ -236,61 +366,39 @@ AI Assistance
236
366
  Added
237
367
  -----
238
368
 
239
- - **Feature Autoloading System**: Features can now automatically discover and load extension files from your project directories. When you include a feature like ``safe_dump``, Familia searches for configuration files using conventional patterns like ``{model_name}/{feature_name}_*.rb``, enabling clean separation between core model definitions and feature-specific configurations. See ``docs/migrating/v2.0.0-pre13.md`` for migration details.
240
-
241
- - **Consolidated autoloader architecture**: Introduced ``Familia::Features::Autoloader`` as a shared utility for consistent file loading patterns across the framework, supporting both general-purpose and feature-specific autoloading scenarios.
242
-
243
- - Added ``PER_MONTH`` constant (2,629,746 seconds = 30.437 days) derived from Gregorian year for consistent month calculations.
244
- - Added ``months``, ``month``, and ``in_months`` conversion methods to Numeric refinement.
245
- - Added month unit mappings (``'mo'``, ``'month'``, ``'months'``) to TimeLiterals ``UNIT_METHODS`` hash.
369
+ - **Feature Autoloading System** - Features automatically discover and load extension files from project directories using conventional patterns. PR #97
246
370
 
247
- - **Error Handling**: Added ``NotSupportedError`` for invalid serialization mode combinations in encryption subsystem. PR #97
371
+ - **Month calculations** - Added ``PER_MONTH`` constant and month conversion methods to TimeLiterals refinement. Issue #94
248
372
 
249
373
  Changed
250
374
  -------
251
375
 
252
- - Refactored time and numeric extensions from global monkey patches to proper Ruby refinements for better encapsulation and reduced global namespace pollution
253
- - Updated all internal classes to use refinements via ``using Familia::Refinements::TimeLiterals`` statements
254
- - Added centralized ``RefinedContext`` module in test helpers to support refinement testing in tryouts files
255
-
256
- - Updated ``PER_YEAR`` constant to use Gregorian year (31,556,952 seconds = 365.2425 days) for calendar consistency.
257
-
258
- - **Performance**: Replaced stdlib JSON with OJ gem for 2-5x faster JSON operations and reduced memory allocation. All existing code remains compatible through mimic_JSON mode. PR #97
259
-
260
- - **Encryption**: Enhanced serialization safety for encrypted fields with improved ConcealedString handling across different JSON processing modes. Strengthened protection against accidental data exposure during serialization. PR #97
376
+ - **Performance** - Replaced stdlib JSON with OJ gem for 2-5x faster operations. PR #97
377
+ - Refactored time/numeric extensions from global monkey patches to Ruby refinements
378
+ - Enhanced encryption serialization safety with improved ConcealedString handling
261
379
 
262
380
  Fixed
263
381
  -----
264
382
 
265
- - Fixed byte conversion logic in ``to_bytes`` method to correctly handle exact 1024-byte boundaries (``size >= 1024`` instead of ``size > 1024``)
266
- - Resolved refinement testing issues in tryouts by implementing ``eval``-based code execution within refined contexts
267
-
268
- - Fixed TimeLiterals refinement ``months_old`` and ``years_old`` methods returning incorrect values (raw seconds instead of months/years). The underlying ``age_in`` method now properly handles ``:months`` and ``:years`` units. Issue #94.
269
- - Fixed calendar consistency issue where ``12.months != 1.year`` by updating ``PER_YEAR`` to use Gregorian year (365.2425 days) and defining ``PER_MONTH`` as ``PER_YEAR / 12``.
383
+ - Fixed ``months_old`` and ``years_old`` methods returning raw seconds instead of proper units. Issue #94
384
+ - Fixed byte conversion boundary logic (``size >= 1024`` instead of ``size > 1024``)
385
+ - Fixed calendar consistency where ``12.months != 1.year`` by using Gregorian year
270
386
 
271
387
  Security
272
388
  --------
273
389
 
274
- - **Encryption**: Improved concealed value protection during JSON serialization, ensuring encrypted data remains properly protected across all OJ serialization modes. PR #97
390
+ - Improved concealed value protection during JSON serialization across all OJ modes. PR #97
275
391
 
276
392
  Documentation
277
393
  -------------
278
394
 
279
- - **Feature System Autoloading Guide**: Added comprehensive guide at ``docs/guides/Feature-System-Autoloading.md`` explaining the new autoloading system, including file naming conventions, directory patterns, and usage examples.
280
- - **Enhanced API documentation**: Added detailed YARD documentation for autoloading modules and methods.
395
+ - Added Feature System Autoloading guide with conventions and usage examples
396
+ - Enhanced YARD documentation for autoloading modules
281
397
 
282
398
  AI Assistance
283
399
  -------------
284
400
 
285
- - Provided comprehensive analysis of Ruby refinement scoping issues and designed the eval-based testing solution
286
- - Assisted with refactoring global extensions to proper refinements while maintaining backward compatibility
287
- - Helped debug and fix the byte conversion boundary condition bug
288
-
289
- - Significant AI assistance in architectural design and implementation of the feature-specific autoloading system, including pattern matching logic, Ruby introspection methods, and comprehensive debugging of edge cases and thread safety considerations.
290
-
291
- - Claude Code assisted with implementing the fix for broken ``months_old`` and ``years_old`` methods in the TimeLiterals refinement, including analysis, implementation, testing, and documentation.
292
-
293
- - Performance optimization research and OJ gem integration strategy, including compatibility analysis and testing approach for seamless stdlib JSON replacement. PR #97
401
+ - Claude (Anthropic) assisted with refinement refactoring, autoloading system design, and OJ integration.
294
402
 
295
403
  2.0.0.pre12 — 2025-09-04
296
404
  ========================
data/CLAUDE.md CHANGED
@@ -53,7 +53,7 @@ Add changelog fragment with each user-facing or documented change (optional but
53
53
  ### Known Issues & Quirks
54
54
  - **Reserved Keywords**: Cannot use `ttl`, `db`, `valkey`, `redis` as field names - use prefixed alternatives
55
55
  - **Empty Identifiers**: Cause stack overflow in key generation - validate before operations
56
- - **Connection Pool Race Conditions**: Thread safety issues under high concurrency
56
+ - **Lazy Initialization Races**: Connection chains and field collections use lazy initialization without synchronization (generally safe due to Ruby GIL, but not guaranteed)
57
57
 
58
58
  ### Debugging
59
59
  - **Database command logging**: You can request real-time Database command monitoring from the user
@@ -191,3 +191,30 @@ end
191
191
  **Memory Efficiency**: Only non-nil values are stored in keystore database to optimize memory usage.
192
192
 
193
193
  **Thread Safety**: Data types are frozen after instantiation to ensure immutability.
194
+
195
+ ## Thread Safety Considerations
196
+
197
+ ### Current Thread Safety Status (as of 2025-10-21)
198
+
199
+ Familia has **good thread safety** for standard multi-threaded environments:
200
+
201
+ ### Testing Thread Safety
202
+
203
+ Thread safety tests are available in `try/thread_safety/`:
204
+ - **100% passing** (56/56 tests)
205
+ - **CyclicBarrier pattern** for maximum contention testing
206
+ - **Test execution**: ~300ms for full suite with 1,000+ concurrent operations
207
+ - **Production monitoring**: 10/10 monitoring tests passing
208
+
209
+ Run thread safety tests:
210
+ ```bash
211
+ bundle exec try --agent try/thread_safety/
212
+ bundle exec try --agent try/unit/thread_safety_monitor_try.rb
213
+ ```
214
+
215
+ ### Best Practices for Thread-Safe Usage
216
+
217
+ 1. **Configure Once at Startup**: Module-level configuration should be set before threads spawn
218
+ 2. **Use Immutable DataTypes**: Leverage the fact that DataType instances are frozen
219
+ 3. **Test Under Concurrency**: Use the patterns in `try/thread_safety/` to verify thread safety
220
+ 4. **Enable Production Monitoring**: Use `Familia.start_monitoring!` to track contention in production
data/Gemfile CHANGED
@@ -9,7 +9,7 @@ group :test do
9
9
  gem 'ruby-prof'
10
10
  gem 'stackprof'
11
11
  gem 'timecop', require: false
12
- gem 'tryouts', '~> 3.6.0', require: false
12
+ gem 'tryouts', '~> 3.7.1', require: false
13
13
  end
14
14
 
15
15
  group :development, :test do
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- familia (2.0.0.pre19)
4
+ familia (2.0.0.pre22)
5
5
  benchmark (~> 0.4)
6
+ concurrent-ruby (~> 1.3)
6
7
  connection_pool (~> 2.5)
7
8
  csv (~> 3.3)
8
9
  logger (~> 1.7)
@@ -21,7 +22,7 @@ GEM
21
22
  concurrent-ruby (1.3.5)
22
23
  connection_pool (2.5.3)
23
24
  csv (3.3.5)
24
- date (3.4.1)
25
+ date (3.5.0)
25
26
  debug (1.11.0)
26
27
  irb (~> 1.10)
27
28
  reline (>= 0.3.8)
@@ -55,11 +56,11 @@ GEM
55
56
  dry-inflector (~> 1.0)
56
57
  dry-logic (~> 1.4)
57
58
  zeitwerk (~> 2.6)
58
- erb (5.0.2)
59
+ erb (5.1.3)
59
60
  ffi (1.17.2)
60
61
  ffi (1.17.2-arm64-darwin)
61
62
  io-console (0.8.1)
62
- irb (1.15.2)
63
+ irb (1.15.3)
63
64
  pp (>= 0.6.0)
64
65
  rdoc (>= 4.0.0)
65
66
  reline (>= 0.4.2)
@@ -67,7 +68,7 @@ GEM
67
68
  language_server-protocol (3.17.0.5)
68
69
  lint_roller (1.1.0)
69
70
  logger (1.7.0)
70
- minitest (5.25.5)
71
+ minitest (5.26.0)
71
72
  oj (3.16.11)
72
73
  bigdecimal (>= 3.0)
73
74
  ostruct (>= 0.2)
@@ -78,10 +79,10 @@ GEM
78
79
  racc
79
80
  pastel (0.8.0)
80
81
  tty-color (~> 0.5)
81
- pp (0.6.2)
82
+ pp (0.6.3)
82
83
  prettyprint
83
84
  prettyprint (0.2.0)
84
- prism (1.5.2)
85
+ prism (1.6.0)
85
86
  psych (5.2.6)
86
87
  date
87
88
  stringio
@@ -91,9 +92,10 @@ GEM
91
92
  ffi (~> 1)
92
93
  rbs (3.9.5)
93
94
  logger
94
- rdoc (6.14.2)
95
+ rdoc (6.15.1)
95
96
  erb
96
97
  psych (>= 4.0.0)
98
+ tsort
97
99
  redcarpet (3.6.1)
98
100
  redis (5.4.1)
99
101
  redis-client (>= 0.22.0)
@@ -109,19 +111,19 @@ GEM
109
111
  reline (0.6.2)
110
112
  io-console (~> 0.5)
111
113
  rexml (3.4.1)
112
- rspec (3.13.1)
114
+ rspec (3.13.2)
113
115
  rspec-core (~> 3.13.0)
114
116
  rspec-expectations (~> 3.13.0)
115
117
  rspec-mocks (~> 3.13.0)
116
- rspec-core (3.13.5)
118
+ rspec-core (3.13.6)
117
119
  rspec-support (~> 3.13.0)
118
120
  rspec-expectations (3.13.5)
119
121
  diff-lcs (>= 1.2.0, < 2.0)
120
122
  rspec-support (~> 3.13.0)
121
- rspec-mocks (3.13.5)
123
+ rspec-mocks (3.13.7)
122
124
  diff-lcs (>= 1.2.0, < 2.0)
123
125
  rspec-support (~> 3.13.0)
124
- rspec-support (3.13.4)
126
+ rspec-support (3.13.6)
125
127
  rubocop (1.81.1)
126
128
  json (~> 2.3)
127
129
  language_server-protocol (~> 3.17.0.2)
@@ -154,15 +156,16 @@ GEM
154
156
  stackprof (0.2.27)
155
157
  stringio (3.1.7)
156
158
  timecop (0.9.10)
157
- tryouts (3.6.0)
158
- concurrent-ruby (~> 1.0)
159
+ tryouts (3.7.1)
160
+ concurrent-ruby (~> 1.0, < 2)
159
161
  irb
160
162
  minitest (~> 5.0)
161
163
  pastel (~> 0.8)
162
164
  prism (~> 1.0)
163
- rspec (~> 3.0)
165
+ rspec (>= 3.0, < 5.0)
164
166
  tty-cursor (~> 0.7)
165
167
  tty-screen (~> 0.8)
168
+ tsort (0.2.0)
166
169
  tty-color (0.6.0)
167
170
  tty-cursor (0.7.1)
168
171
  tty-screen (0.8.2)
@@ -192,8 +195,8 @@ DEPENDENCIES
192
195
  ruby-prof
193
196
  stackprof
194
197
  timecop
195
- tryouts (~> 3.6.0)
198
+ tryouts (~> 3.7.1)
196
199
  yard (~> 0.9)
197
200
 
198
201
  BUNDLED WITH
199
- 2.6.2
202
+ 2.7.2
data/bin/try ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'try' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ require "rubygems"
14
+ require "bundler/setup"
15
+
16
+ load Gem.bin_path("tryouts", "try")