familia 2.0.0.pre19 → 2.0.0.pre21

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 (372) 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/CHANGELOG.rst +177 -112
  8. data/CLAUDE.md +28 -1
  9. data/Gemfile +1 -1
  10. data/Gemfile.lock +20 -17
  11. data/bin/try +16 -0
  12. data/bin/tryouts +16 -0
  13. data/changelog.d/20251105_flexible_external_identifier_format.rst +66 -0
  14. data/changelog.d/20251107_112554_delano_179_participation_asymmetry.rst +44 -0
  15. data/changelog.d/20251107_213121_delano_fix_thread_safety_races_011CUumCP492Twxm4NLt2FvL.rst +20 -0
  16. data/changelog.d/20251107_fix_participates_in_symbol_resolution.rst +91 -0
  17. data/changelog.d/20251107_optimized_redis_exists_checks.rst +94 -0
  18. data/changelog.d/20251108_frozen_string_literal_pragma.rst +44 -0
  19. data/docs/1106-participates_in-bidirectional-solution.md +129 -0
  20. data/docs/guides/encryption.md +486 -0
  21. data/docs/guides/feature-encrypted-fields.md +123 -7
  22. data/docs/guides/feature-expiration.md +161 -117
  23. data/docs/guides/feature-external-identifiers.md +415 -443
  24. data/docs/guides/feature-object-identifiers.md +400 -269
  25. data/docs/guides/feature-quantization.md +120 -6
  26. data/docs/guides/feature-relationships-indexing.md +318 -0
  27. data/docs/guides/feature-relationships-methods.md +146 -604
  28. data/docs/guides/feature-relationships-participation.md +263 -0
  29. data/docs/guides/feature-relationships.md +118 -136
  30. data/docs/guides/feature-system-devs.md +176 -693
  31. data/docs/guides/feature-system.md +119 -6
  32. data/docs/guides/feature-transient-fields.md +81 -0
  33. data/docs/guides/field-system.md +778 -0
  34. data/docs/guides/index.md +32 -15
  35. data/docs/guides/logging.md +187 -0
  36. data/docs/guides/optimized-loading.md +674 -0
  37. data/docs/guides/thread-safety-monitoring.md +61 -0
  38. data/docs/guides/{time-utilities.md → time-literals.md} +12 -12
  39. data/docs/migrating/v2.0.0-pre22.md +241 -0
  40. data/docs/overview.md +7 -9
  41. data/docs/reference/api-technical.md +267 -320
  42. data/examples/autoloader/mega_customer/features/deprecated_fields.rb +2 -0
  43. data/examples/autoloader/mega_customer/safe_dump_fields.rb +2 -0
  44. data/examples/autoloader/mega_customer.rb +2 -0
  45. data/examples/datatype_standalone.rb +4 -3
  46. data/examples/encrypted_fields.rb +2 -1
  47. data/examples/json_usage_patterns.rb +2 -0
  48. data/examples/relationships.rb +3 -0
  49. data/examples/safe_dump.rb +2 -1
  50. data/examples/sampling_demo.rb +53 -0
  51. data/examples/single_connection_transaction_confusions.rb +2 -1
  52. data/familia.gemspec +2 -1
  53. data/lib/familia/base.rb +2 -0
  54. data/lib/familia/connection/behavior.rb +2 -0
  55. data/lib/familia/connection/handlers.rb +2 -0
  56. data/lib/familia/connection/individual_command_proxy.rb +2 -0
  57. data/lib/familia/connection/middleware.rb +34 -24
  58. data/lib/familia/connection/operation_core.rb +2 -0
  59. data/lib/familia/connection/operations.rb +2 -0
  60. data/lib/familia/connection/pipelined_core.rb +2 -0
  61. data/lib/familia/connection/transaction_core.rb +68 -0
  62. data/lib/familia/connection.rb +18 -3
  63. data/lib/familia/data_type/class_methods.rb +3 -1
  64. data/lib/familia/data_type/connection.rb +2 -0
  65. data/lib/familia/data_type/database_commands.rb +2 -0
  66. data/lib/familia/data_type/serialization.rb +6 -4
  67. data/lib/familia/data_type/settings.rb +2 -0
  68. data/lib/familia/data_type/types/counter.rb +2 -0
  69. data/lib/familia/data_type/types/hashkey.rb +7 -5
  70. data/lib/familia/data_type/types/listkey.rb +2 -0
  71. data/lib/familia/data_type/types/lock.rb +2 -0
  72. data/lib/familia/data_type/types/sorted_set.rb +2 -0
  73. data/lib/familia/data_type/types/stringkey.rb +2 -0
  74. data/lib/familia/data_type/types/unsorted_set.rb +2 -0
  75. data/lib/familia/data_type.rb +2 -0
  76. data/lib/familia/encryption/encrypted_data.rb +4 -2
  77. data/lib/familia/encryption/manager.rb +2 -0
  78. data/lib/familia/encryption/provider.rb +2 -0
  79. data/lib/familia/encryption/providers/aes_gcm_provider.rb +2 -0
  80. data/lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb +2 -0
  81. data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +2 -0
  82. data/lib/familia/encryption/registry.rb +2 -0
  83. data/lib/familia/encryption/request_cache.rb +2 -0
  84. data/lib/familia/encryption.rb +9 -2
  85. data/lib/familia/errors.rb +2 -0
  86. data/lib/familia/features/autoloader.rb +2 -0
  87. data/lib/familia/features/encrypted_fields/concealed_string.rb +2 -0
  88. data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +4 -0
  89. data/lib/familia/features/encrypted_fields.rb +2 -2
  90. data/lib/familia/features/expiration/extensions.rb +3 -1
  91. data/lib/familia/features/expiration.rb +12 -4
  92. data/lib/familia/features/external_identifier.rb +33 -7
  93. data/lib/familia/features/object_identifier.rb +2 -0
  94. data/lib/familia/features/quantization.rb +3 -1
  95. data/lib/familia/features/relationships/README.md +3 -1
  96. data/lib/familia/features/relationships/collection_operations.rb +2 -0
  97. data/lib/familia/features/relationships/indexing/multi_index_generators.rb +138 -9
  98. data/lib/familia/features/relationships/indexing/rebuild_strategies.rb +479 -0
  99. data/lib/familia/features/relationships/indexing/unique_index_generators.rb +89 -21
  100. data/lib/familia/features/relationships/indexing.rb +3 -0
  101. data/lib/familia/features/relationships/indexing_relationship.rb +3 -1
  102. data/lib/familia/features/relationships/participation/participant_methods.rb +131 -14
  103. data/lib/familia/features/relationships/participation/rebuild_strategies.md +41 -0
  104. data/lib/familia/features/relationships/participation/target_methods.rb +6 -6
  105. data/lib/familia/features/relationships/participation.rb +155 -69
  106. data/lib/familia/features/relationships/participation_membership.rb +69 -0
  107. data/lib/familia/features/relationships/participation_relationship.rb +34 -6
  108. data/lib/familia/features/relationships/score_encoding.rb +2 -0
  109. data/lib/familia/features/relationships.rb +5 -3
  110. data/lib/familia/features/safe_dump.rb +2 -0
  111. data/lib/familia/features/transient_fields/redacted_string.rb +2 -0
  112. data/lib/familia/features/transient_fields/single_use_redacted_string.rb +2 -0
  113. data/lib/familia/features/transient_fields/transient_field_type.rb +5 -3
  114. data/lib/familia/features/transient_fields.rb +2 -0
  115. data/lib/familia/features.rb +2 -0
  116. data/lib/familia/field_type.rb +3 -1
  117. data/lib/familia/horreum/connection.rb +17 -1
  118. data/lib/familia/horreum/database_commands.rb +2 -0
  119. data/lib/familia/horreum/definition.rb +16 -6
  120. data/lib/familia/horreum/management.rb +212 -42
  121. data/lib/familia/horreum/persistence.rb +176 -108
  122. data/lib/familia/horreum/related_fields.rb +2 -0
  123. data/lib/familia/horreum/serialization.rb +23 -4
  124. data/lib/familia/horreum/settings.rb +2 -0
  125. data/lib/familia/horreum/utils.rb +2 -0
  126. data/lib/familia/horreum.rb +15 -1
  127. data/lib/familia/identifier_extractor.rb +2 -0
  128. data/lib/familia/instrumentation.rb +156 -0
  129. data/lib/familia/json_serializer.rb +2 -0
  130. data/lib/familia/logging.rb +92 -32
  131. data/lib/familia/refinements/dear_json.rb +2 -0
  132. data/lib/familia/refinements/stylize_words.rb +2 -14
  133. data/lib/familia/refinements/time_literals.rb +2 -0
  134. data/lib/familia/refinements.rb +2 -0
  135. data/lib/familia/secure_identifier.rb +10 -2
  136. data/lib/familia/settings.rb +2 -0
  137. data/lib/familia/thread_safety/instrumented_mutex.rb +166 -0
  138. data/lib/familia/thread_safety/monitor.rb +328 -0
  139. data/lib/familia/utils.rb +13 -0
  140. data/lib/familia/verifiable_identifier.rb +3 -1
  141. data/lib/familia/version.rb +3 -1
  142. data/lib/familia.rb +31 -4
  143. data/lib/middleware/database_command_counter.rb +152 -0
  144. data/lib/middleware/database_logger.rb +295 -170
  145. data/lib/multi_result.rb +2 -0
  146. data/try/edge_cases/empty_identifiers_try.rb +2 -0
  147. data/try/edge_cases/hash_symbolization_try.rb +2 -0
  148. data/try/edge_cases/json_serialization_try.rb +2 -0
  149. data/try/edge_cases/legacy_data_detection/deserialization_edge_cases_try.rb +4 -0
  150. data/try/edge_cases/race_conditions_try.rb +4 -0
  151. data/try/edge_cases/reserved_keywords_try.rb +4 -0
  152. data/try/edge_cases/string_coercion_try.rb +2 -0
  153. data/try/edge_cases/ttl_side_effects_try.rb +4 -0
  154. data/try/features/encrypted_fields/aad_protection_try.rb +4 -0
  155. data/try/features/encrypted_fields/concealed_string_core_try.rb +4 -0
  156. data/try/features/encrypted_fields/context_isolation_try.rb +4 -0
  157. data/try/features/encrypted_fields/encrypted_fields_core_try.rb +33 -0
  158. data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +4 -0
  159. data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +4 -0
  160. data/try/features/encrypted_fields/encrypted_fields_security_try.rb +4 -0
  161. data/try/features/encrypted_fields/error_conditions_try.rb +4 -0
  162. data/try/features/encrypted_fields/fresh_key_derivation_try.rb +4 -0
  163. data/try/features/encrypted_fields/fresh_key_try.rb +4 -0
  164. data/try/features/encrypted_fields/key_rotation_try.rb +4 -0
  165. data/try/features/encrypted_fields/memory_security_try.rb +4 -0
  166. data/try/features/encrypted_fields/missing_current_key_version_try.rb +4 -0
  167. data/try/features/encrypted_fields/nonce_uniqueness_try.rb +4 -0
  168. data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +4 -0
  169. data/try/features/encrypted_fields/thread_safety_try.rb +4 -0
  170. data/try/features/encrypted_fields/universal_serialization_safety_try.rb +4 -0
  171. data/try/features/encryption/config_persistence_try.rb +4 -0
  172. data/try/features/encryption/core_try.rb +4 -0
  173. data/try/features/encryption/instance_variable_scope_try.rb +4 -0
  174. data/try/features/encryption/module_loading_try.rb +4 -0
  175. data/try/features/encryption/providers/aes_gcm_provider_try.rb +4 -0
  176. data/try/features/encryption/providers/xchacha20_poly1305_provider_try.rb +4 -0
  177. data/try/features/encryption/roundtrip_validation_try.rb +4 -0
  178. data/try/features/encryption/secure_memory_handling_try.rb +4 -0
  179. data/try/features/expiration/expiration_try.rb +4 -0
  180. data/try/features/external_identifier/external_identifier_try.rb +171 -8
  181. data/try/features/feature_dependencies_try.rb +2 -0
  182. data/try/features/feature_improvements_try.rb +2 -0
  183. data/try/features/field_groups_try.rb +2 -0
  184. data/try/features/object_identifier/object_identifier_integration_try.rb +12 -9
  185. data/try/features/object_identifier/object_identifier_try.rb +2 -0
  186. data/try/features/quantization/quantization_try.rb +4 -0
  187. data/try/features/real_feature_integration_try.rb +2 -0
  188. data/try/features/relationships/indexing_commands_verification_try.rb +2 -0
  189. data/try/features/relationships/indexing_rebuild_try.rb +600 -0
  190. data/try/features/relationships/indexing_try.rb +2 -0
  191. data/try/features/relationships/participation_bidirectional_try.rb +242 -0
  192. data/try/features/relationships/participation_commands_verification_spec.rb +4 -0
  193. data/try/features/relationships/participation_commands_verification_try.rb +2 -0
  194. data/try/features/relationships/participation_performance_improvements_try.rb +11 -9
  195. data/try/features/relationships/participation_reverse_index_try.rb +15 -13
  196. data/try/features/relationships/participation_target_class_resolution_try.rb +209 -0
  197. data/try/features/relationships/participation_unresolved_target_try.rb +109 -0
  198. data/try/features/relationships/relationships_api_changes_try.rb +2 -0
  199. data/try/features/relationships/relationships_edge_cases_try.rb +4 -0
  200. data/try/features/relationships/relationships_performance_minimal_try.rb +4 -0
  201. data/try/features/relationships/relationships_performance_simple_try.rb +4 -0
  202. data/try/features/relationships/relationships_performance_try.rb +4 -0
  203. data/try/features/relationships/relationships_performance_working_try.rb +4 -0
  204. data/try/features/relationships/relationships_try.rb +6 -4
  205. data/try/features/safe_dump/safe_dump_advanced_try.rb +4 -0
  206. data/try/features/safe_dump/safe_dump_try.rb +4 -0
  207. data/try/features/transient_fields/redacted_string_try.rb +2 -0
  208. data/try/features/transient_fields/refresh_reset_try.rb +3 -0
  209. data/try/features/transient_fields/simple_refresh_test.rb +3 -0
  210. data/try/features/transient_fields/single_use_redacted_string_try.rb +2 -0
  211. data/try/features/transient_fields/transient_fields_core_try.rb +4 -0
  212. data/try/features/transient_fields/transient_fields_integration_try.rb +4 -0
  213. data/try/integration/connection/fiber_context_preservation_try.rb +4 -0
  214. data/try/integration/connection/handler_constraints_try.rb +4 -0
  215. data/try/integration/connection/isolated_dbclient_try.rb +4 -0
  216. data/try/integration/connection/middleware_reconnect_try.rb +2 -0
  217. data/try/integration/connection/operation_mode_guards_try.rb +4 -0
  218. data/try/integration/connection/pipeline_fallback_integration_try.rb +3 -0
  219. data/try/integration/connection/pools_try.rb +4 -0
  220. data/try/integration/connection/responsibility_chain_tracking_try.rb +4 -0
  221. data/try/integration/connection/transaction_fallback_integration_try.rb +4 -0
  222. data/try/integration/connection/transaction_mode_permissive_try.rb +4 -0
  223. data/try/integration/connection/transaction_mode_strict_try.rb +4 -0
  224. data/try/integration/connection/transaction_mode_warn_try.rb +4 -0
  225. data/try/integration/connection/transaction_modes_try.rb +4 -0
  226. data/try/integration/conventional_inheritance_try.rb +4 -0
  227. data/try/integration/create_method_try.rb +4 -0
  228. data/try/integration/cross_component_try.rb +4 -0
  229. data/try/integration/data_types/datatype_pipelines_try.rb +4 -0
  230. data/try/integration/data_types/datatype_transactions_try.rb +4 -0
  231. data/try/integration/database_consistency_try.rb +4 -0
  232. data/try/integration/familia_extended_try.rb +4 -0
  233. data/try/integration/familia_members_methods_try.rb +4 -0
  234. data/try/integration/models/customer_safe_dump_try.rb +4 -0
  235. data/try/integration/models/customer_try.rb +4 -0
  236. data/try/integration/models/datatype_base_try.rb +4 -0
  237. data/try/integration/models/familia_object_try.rb +4 -0
  238. data/try/integration/persistence_operations_try.rb +4 -0
  239. data/try/integration/relationships_persistence_round_trip_try.rb +17 -14
  240. data/try/integration/save_methods_consistency_try.rb +241 -0
  241. data/try/integration/scenarios_try.rb +4 -0
  242. data/try/integration/secure_identifier_try.rb +4 -0
  243. data/try/integration/transaction_safety_core_try.rb +176 -0
  244. data/try/integration/transaction_safety_workflow_try.rb +291 -0
  245. data/try/integration/verifiable_identifier_try.rb +4 -0
  246. data/try/investigation/pipeline_routing/README.md +228 -0
  247. data/try/performance/benchmarks_try.rb +4 -0
  248. data/try/performance/transaction_safety_benchmark_try.rb +238 -0
  249. data/try/support/benchmarks/deserialization_benchmark.rb +3 -1
  250. data/try/support/benchmarks/deserialization_correctness_test.rb +3 -1
  251. data/try/support/debugging/cache_behavior_tracer.rb +4 -0
  252. data/try/support/debugging/debug_aad_process.rb +3 -0
  253. data/try/support/debugging/debug_concealed_internal.rb +3 -0
  254. data/try/support/debugging/debug_concealed_reveal.rb +3 -0
  255. data/try/support/debugging/debug_context_aad.rb +3 -0
  256. data/try/support/debugging/debug_context_simple.rb +3 -0
  257. data/try/support/debugging/debug_cross_context.rb +3 -0
  258. data/try/support/debugging/debug_database_load.rb +3 -0
  259. data/try/support/debugging/debug_encrypted_json_check.rb +3 -0
  260. data/try/support/debugging/debug_encrypted_json_step_by_step.rb +3 -0
  261. data/try/support/debugging/debug_exists_lifecycle.rb +3 -0
  262. data/try/support/debugging/debug_field_decrypt.rb +3 -0
  263. data/try/support/debugging/debug_fresh_cross_context.rb +3 -0
  264. data/try/support/debugging/debug_load_path.rb +3 -0
  265. data/try/support/debugging/debug_method_definition.rb +3 -0
  266. data/try/support/debugging/debug_method_resolution.rb +3 -0
  267. data/try/support/debugging/debug_minimal.rb +3 -0
  268. data/try/support/debugging/debug_provider.rb +3 -0
  269. data/try/support/debugging/debug_secure_behavior.rb +3 -0
  270. data/try/support/debugging/debug_string_class.rb +3 -0
  271. data/try/support/debugging/debug_test.rb +3 -0
  272. data/try/support/debugging/debug_test_design.rb +3 -0
  273. data/try/support/debugging/encryption_method_tracer.rb +4 -0
  274. data/try/support/debugging/provider_diagnostics.rb +4 -0
  275. data/try/support/helpers/test_cleanup.rb +4 -0
  276. data/try/support/helpers/test_helpers.rb +5 -0
  277. data/try/support/memory/memory_basic_test.rb +4 -0
  278. data/try/support/memory/memory_detailed_test.rb +4 -0
  279. data/try/support/memory/memory_search_for_string.rb +4 -0
  280. data/try/support/memory/test_actual_redactedstring_protection.rb +4 -0
  281. data/try/support/prototypes/atomic_saves_v1_context_proxy.rb +4 -0
  282. data/try/support/prototypes/atomic_saves_v2_connection_switching.rb +4 -0
  283. data/try/support/prototypes/atomic_saves_v3_connection_pool.rb +4 -0
  284. data/try/support/prototypes/atomic_saves_v4.rb +4 -0
  285. data/try/support/prototypes/lib/atomic_saves_v2_connection_switching_helpers.rb +4 -0
  286. data/try/support/prototypes/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -0
  287. data/try/support/prototypes/pooling/configurable_stress_test.rb +4 -0
  288. data/try/support/prototypes/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -0
  289. data/try/support/prototypes/pooling/lib/connection_pool_metrics.rb +4 -0
  290. data/try/support/prototypes/pooling/lib/connection_pool_stress_test.rb +4 -0
  291. data/try/support/prototypes/pooling/lib/connection_pool_threading_models.rb +4 -0
  292. data/try/support/prototypes/pooling/lib/visualize_stress_results.rb +4 -2
  293. data/try/support/prototypes/pooling/pool_siege.rb +4 -2
  294. data/try/support/prototypes/pooling/run_stress_tests.rb +4 -2
  295. data/try/thread_safety/README.md +496 -0
  296. data/try/thread_safety/class_connection_chain_race_try.rb +265 -0
  297. data/try/thread_safety/connection_chain_race_try.rb +148 -0
  298. data/try/thread_safety/encryption_manager_cache_race_try.rb +166 -0
  299. data/try/thread_safety/feature_registry_race_try.rb +226 -0
  300. data/try/thread_safety/fiber_pipeline_isolation_try.rb +235 -0
  301. data/try/thread_safety/fiber_transaction_isolation_try.rb +208 -0
  302. data/try/thread_safety/field_registration_race_try.rb +222 -0
  303. data/try/thread_safety/logger_initialization_race_try.rb +170 -0
  304. data/try/thread_safety/middleware_registration_race_try.rb +154 -0
  305. data/try/thread_safety/module_config_race_try.rb +175 -0
  306. data/try/thread_safety/secure_identifier_cache_race_try.rb +226 -0
  307. data/try/unit/core/autoloader_try.rb +4 -0
  308. data/try/unit/core/base_enhancements_try.rb +4 -0
  309. data/try/unit/core/connection_try.rb +4 -0
  310. data/try/unit/core/errors_try.rb +4 -0
  311. data/try/unit/core/extensions_try.rb +4 -0
  312. data/try/unit/core/familia_logger_try.rb +2 -0
  313. data/try/unit/core/familia_try.rb +4 -0
  314. data/try/unit/core/middleware_sampling_try.rb +335 -0
  315. data/try/unit/core/middleware_test_helpers_bug_try.rb +58 -0
  316. data/try/unit/core/middleware_thread_safety_try.rb +245 -0
  317. data/try/unit/core/middleware_try.rb +4 -0
  318. data/try/unit/core/settings_try.rb +4 -0
  319. data/try/unit/core/time_utils_try.rb +4 -0
  320. data/try/unit/core/tools_try.rb +4 -0
  321. data/try/unit/core/utils_try.rb +37 -0
  322. data/try/unit/data_types/boolean_try.rb +4 -0
  323. data/try/unit/data_types/counter_try.rb +4 -0
  324. data/try/unit/data_types/datatype_base_try.rb +4 -0
  325. data/try/unit/data_types/hash_try.rb +4 -0
  326. data/try/unit/data_types/list_try.rb +4 -0
  327. data/try/unit/data_types/lock_try.rb +4 -0
  328. data/try/unit/data_types/sorted_set_try.rb +4 -0
  329. data/try/unit/data_types/sorted_set_zadd_options_try.rb +4 -0
  330. data/try/unit/data_types/string_try.rb +4 -0
  331. data/try/unit/data_types/unsortedset_try.rb +4 -0
  332. data/try/unit/familia_resolve_class_try.rb +116 -0
  333. data/try/unit/horreum/auto_indexing_on_save_try.rb +5 -1
  334. data/try/unit/horreum/automatic_index_validation_try.rb +2 -0
  335. data/try/unit/horreum/base_try.rb +4 -0
  336. data/try/unit/horreum/class_methods_try.rb +4 -0
  337. data/try/unit/horreum/commands_try.rb +4 -0
  338. data/try/unit/horreum/defensive_initialization_try.rb +4 -0
  339. data/try/unit/horreum/destroy_related_fields_cleanup_try.rb +4 -0
  340. data/try/unit/horreum/enhanced_conflict_handling_try.rb +4 -0
  341. data/try/unit/horreum/field_categories_try.rb +4 -0
  342. data/try/unit/horreum/field_definition_try.rb +4 -0
  343. data/try/unit/horreum/initialization_try.rb +4 -0
  344. data/try/unit/horreum/json_type_preservation_try.rb +2 -0
  345. data/try/unit/horreum/optimized_loading_try.rb +156 -0
  346. data/try/unit/horreum/relations_try.rb +4 -0
  347. data/try/unit/horreum/serialization_persistent_fields_try.rb +4 -0
  348. data/try/unit/horreum/serialization_try.rb +4 -0
  349. data/try/unit/horreum/settings_try.rb +4 -0
  350. data/try/unit/horreum/unique_index_edge_cases_try.rb +4 -0
  351. data/try/unit/horreum/unique_index_guard_validation_try.rb +2 -0
  352. data/try/unit/middleware/database_command_counter_methods_try.rb +139 -0
  353. data/try/unit/middleware/database_logger_methods_try.rb +251 -0
  354. data/try/unit/refinements/dear_json_array_methods_try.rb +4 -0
  355. data/try/unit/refinements/dear_json_hash_methods_try.rb +4 -0
  356. data/try/unit/refinements/time_literals_numeric_methods_try.rb +4 -0
  357. data/try/unit/refinements/time_literals_string_methods_try.rb +4 -0
  358. data/try/unit/thread_safety_monitor_try.rb +149 -0
  359. metadata +72 -17
  360. data/.github/workflows/code-quality.yml +0 -138
  361. data/changelog.d/20251011_012003_delano_159_datatype_transaction_pipeline_support.rst +0 -91
  362. data/changelog.d/20251011_203905_delano_next.rst +0 -30
  363. data/changelog.d/20251011_212633_delano_next.rst +0 -13
  364. data/changelog.d/20251011_221253_delano_next.rst +0 -26
  365. data/docs/archive/FAMILIA_RELATIONSHIPS.md +0 -210
  366. data/docs/archive/FAMILIA_TECHNICAL.md +0 -823
  367. data/docs/archive/FAMILIA_UPDATE.md +0 -226
  368. data/docs/archive/README.md +0 -64
  369. data/docs/archive/api-reference.md +0 -333
  370. data/docs/guides/core-field-system.md +0 -806
  371. data/docs/guides/implementation.md +0 -276
  372. data/docs/guides/security-model.md +0 -183
@@ -0,0 +1,149 @@
1
+ # try/unit/thread_safety_monitor_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
5
+ require_relative '../support/helpers/test_helpers'
6
+
7
+ # Thread safety monitoring tests
8
+ #
9
+ # Tests basic monitoring functionality without complex concurrency
10
+
11
+ # setup
12
+ Familia.stop_monitoring! if Familia.thread_safety_monitor.enabled
13
+ Familia.thread_safety_monitor.reset_metrics
14
+
15
+ ## Monitor starts and stops correctly
16
+ Familia.start_monitoring!
17
+ started = Familia.thread_safety_monitor.enabled
18
+ Familia.stop_monitoring!
19
+ stopped = !Familia.thread_safety_monitor.enabled
20
+ started && stopped
21
+ #=> true
22
+
23
+ ## Monitor tracks contentions
24
+ Familia.start_monitoring!
25
+ Familia.thread_safety_monitor.record_contention('test_location')
26
+ Familia.thread_safety_monitor.record_contention('test_location')
27
+ report = Familia.thread_safety_report
28
+ report[:summary][:mutex_contentions]
29
+ #=> 2
30
+
31
+ ## Monitor tracks different locations
32
+ Familia.thread_safety_monitor.reset_metrics
33
+ Familia.thread_safety_monitor.record_contention('location_a')
34
+ Familia.thread_safety_monitor.record_contention('location_b')
35
+ Familia.thread_safety_monitor.record_contention('location_a')
36
+ report = Familia.thread_safety_report
37
+ report[:hot_spots].size
38
+ #=> 2
39
+
40
+ ## Monitor tracks race conditions
41
+ Familia.thread_safety_monitor.reset_metrics
42
+ Familia.thread_safety_monitor.record_race_condition('test', 'details')
43
+ report = Familia.thread_safety_report
44
+ report[:summary][:race_detections]
45
+ #=> 1
46
+
47
+ ## Monitor exports metrics
48
+ Familia.thread_safety_monitor.reset_metrics
49
+ Familia.thread_safety_monitor.record_contention('test')
50
+ metrics = Familia.thread_safety_metrics
51
+ metrics['familia.thread_safety.mutex_contentions']
52
+ #=> 1
53
+
54
+ ## Health score starts at maximum
55
+ Familia.thread_safety_monitor.reset_metrics
56
+ report = Familia.thread_safety_report
57
+ report[:health]
58
+ #=> 100
59
+
60
+ ## InstrumentedMutex is used for connection chain
61
+ conn_mutex = Familia.instance_variable_get(:@connection_chain_mutex)
62
+ conn_mutex.is_a?(Familia::ThreadSafety::InstrumentedMutex)
63
+ #=> true
64
+
65
+ ## InstrumentedMutex tracks basic operations
66
+ mutex = Familia::ThreadSafety::InstrumentedMutex.new('test')
67
+ mutex.synchronize { 'work' }
68
+ stats = mutex.stats
69
+ stats[:lock_count]
70
+ #=> 1
71
+
72
+ ## Monitor time_critical_section works
73
+ Familia.thread_safety_monitor.reset_metrics
74
+ result = Familia.thread_safety_monitor.time_critical_section('test') { 37 }
75
+ result
76
+ #=> 37
77
+
78
+ ## Critical sections are tracked
79
+ report = Familia.thread_safety_report
80
+ report[:summary][:critical_sections]
81
+ #=> 1
82
+
83
+ ## Monitor uses microsecond timing for precision
84
+ Familia.thread_safety_monitor.reset_metrics
85
+ start_μs = Familia.now_in_μs
86
+ Familia.thread_safety_monitor.time_critical_section('timing_test') do
87
+ sleep 0.005 # 5ms sleep
88
+ end
89
+ end_μs = Familia.now_in_μs
90
+ duration_μs = end_μs - start_μs
91
+ # Should be at least 5000 microseconds (5ms)
92
+ duration_μs >= 5000
93
+ #=> true
94
+
95
+ ## Wait time tracking uses microsecond precision
96
+ mutex = Familia::ThreadSafety::InstrumentedMutex.new('timing_mutex')
97
+ Familia.thread_safety_monitor.reset_metrics
98
+
99
+ # Create intentional contention with timing
100
+ t1_ready = false
101
+ t2_ready = false
102
+
103
+ t1 = Thread.new do
104
+ mutex.synchronize do
105
+ t1_ready = true
106
+ sleep 0.01 while !t2_ready # Wait for t2 to be waiting
107
+ sleep 0.005 # Hold lock for 5ms
108
+ end
109
+ end
110
+
111
+ t2 = Thread.new do
112
+ sleep 0.001 while !t1_ready # Wait for t1 to acquire lock
113
+ t2_ready = true
114
+ mutex.synchronize { 'got lock' }
115
+ end
116
+
117
+ t1.join
118
+ t2.join
119
+
120
+ stats = mutex.stats
121
+ # Should show contention occurred due to intentional delay
122
+ stats[:contention_count] > 0
123
+ #=> true
124
+
125
+ ## Monitor preserves microsecond precision
126
+ Familia.thread_safety_monitor.reset_metrics
127
+ Familia.thread_safety_monitor.record_contention('precision_test', 1500) # 1500μs = 1.5ms
128
+
129
+ report = Familia.thread_safety_report
130
+ hot_spot = report[:hot_spots].first
131
+ # Should preserve microsecond precision, not convert to seconds
132
+ hot_spot[:avg_wait_μs]
133
+ #=> 1500
134
+
135
+ ## Critical section timing uses microseconds
136
+ Familia.thread_safety_monitor.reset_metrics
137
+ result = Familia.thread_safety_monitor.time_critical_section('precision_timing') do
138
+ sleep 0.003 # 3ms
139
+ 37
140
+ end
141
+
142
+ report = Familia.thread_safety_report
143
+ section_perf = report[:section_performance].first
144
+ # Total time should be in microseconds (≥3000μs for 3ms sleep)
145
+ section_perf[:total_time_μs] >= 3000
146
+ #=> true
147
+
148
+ # teardown
149
+ Familia.stop_monitoring!
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: familia
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre19
4
+ version: 2.0.0.pre21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum
@@ -23,6 +23,20 @@ dependencies:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
25
  version: '0.4'
26
+ - !ruby/object:Gem::Dependency
27
+ name: concurrent-ruby
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '1.3'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.3'
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: connection_pool
28
42
  requirement: !ruby/object:Gem::Requirement
@@ -137,7 +151,6 @@ files:
137
151
  - ".github/workflows/ci.yml"
138
152
  - ".github/workflows/claude-code-review.yml"
139
153
  - ".github/workflows/claude.yml"
140
- - ".github/workflows/code-quality.yml"
141
154
  - ".github/workflows/code-smells.yml"
142
155
  - ".github/workflows/docs.yml"
143
156
  - ".gitignore"
@@ -153,35 +166,39 @@ files:
153
166
  - LICENSE.txt
154
167
  - README.md
155
168
  - bin/irb
156
- - changelog.d/20251011_012003_delano_159_datatype_transaction_pipeline_support.rst
157
- - changelog.d/20251011_203905_delano_next.rst
158
- - changelog.d/20251011_212633_delano_next.rst
159
- - changelog.d/20251011_221253_delano_next.rst
169
+ - bin/try
170
+ - bin/tryouts
171
+ - changelog.d/20251105_flexible_external_identifier_format.rst
172
+ - changelog.d/20251107_112554_delano_179_participation_asymmetry.rst
173
+ - changelog.d/20251107_213121_delano_fix_thread_safety_races_011CUumCP492Twxm4NLt2FvL.rst
174
+ - changelog.d/20251107_fix_participates_in_symbol_resolution.rst
175
+ - changelog.d/20251107_optimized_redis_exists_checks.rst
176
+ - changelog.d/20251108_frozen_string_literal_pragma.rst
160
177
  - changelog.d/README.md
161
178
  - changelog.d/scriv.ini
179
+ - docs/1106-participates_in-bidirectional-solution.md
162
180
  - docs/archive/.gitignore
163
- - docs/archive/FAMILIA_RELATIONSHIPS.md
164
- - docs/archive/FAMILIA_TECHNICAL.md
165
- - docs/archive/FAMILIA_UPDATE.md
166
- - docs/archive/README.md
167
- - docs/archive/api-reference.md
168
181
  - docs/conf.py
169
182
  - docs/guides/.gitignore
170
- - docs/guides/core-field-system.md
183
+ - docs/guides/encryption.md
171
184
  - docs/guides/feature-encrypted-fields.md
172
185
  - docs/guides/feature-expiration.md
173
186
  - docs/guides/feature-external-identifiers.md
174
187
  - docs/guides/feature-object-identifiers.md
175
188
  - docs/guides/feature-quantization.md
189
+ - docs/guides/feature-relationships-indexing.md
176
190
  - docs/guides/feature-relationships-methods.md
191
+ - docs/guides/feature-relationships-participation.md
177
192
  - docs/guides/feature-relationships.md
178
193
  - docs/guides/feature-system-devs.md
179
194
  - docs/guides/feature-system.md
180
195
  - docs/guides/feature-transient-fields.md
181
- - docs/guides/implementation.md
196
+ - docs/guides/field-system.md
182
197
  - docs/guides/index.md
183
- - docs/guides/security-model.md
184
- - docs/guides/time-utilities.md
198
+ - docs/guides/logging.md
199
+ - docs/guides/optimized-loading.md
200
+ - docs/guides/thread-safety-monitoring.md
201
+ - docs/guides/time-literals.md
185
202
  - docs/migrating/.gitignore
186
203
  - docs/migrating/v2.0.0-pre.md
187
204
  - docs/migrating/v2.0.0-pre11.md
@@ -190,6 +207,7 @@ files:
190
207
  - docs/migrating/v2.0.0-pre14.md
191
208
  - docs/migrating/v2.0.0-pre18.md
192
209
  - docs/migrating/v2.0.0-pre19.md
210
+ - docs/migrating/v2.0.0-pre22.md
193
211
  - docs/migrating/v2.0.0-pre5.md
194
212
  - docs/migrating/v2.0.0-pre6.md
195
213
  - docs/migrating/v2.0.0-pre7.md
@@ -204,6 +222,7 @@ files:
204
222
  - examples/json_usage_patterns.rb
205
223
  - examples/relationships.rb
206
224
  - examples/safe_dump.rb
225
+ - examples/sampling_demo.rb
207
226
  - examples/single_connection_transaction_confusions.rb
208
227
  - familia.gemspec
209
228
  - lib/familia.rb
@@ -255,11 +274,14 @@ files:
255
274
  - lib/familia/features/relationships/collection_operations.rb
256
275
  - lib/familia/features/relationships/indexing.rb
257
276
  - lib/familia/features/relationships/indexing/multi_index_generators.rb
277
+ - lib/familia/features/relationships/indexing/rebuild_strategies.rb
258
278
  - lib/familia/features/relationships/indexing/unique_index_generators.rb
259
279
  - lib/familia/features/relationships/indexing_relationship.rb
260
280
  - lib/familia/features/relationships/participation.rb
261
281
  - lib/familia/features/relationships/participation/participant_methods.rb
282
+ - lib/familia/features/relationships/participation/rebuild_strategies.md
262
283
  - lib/familia/features/relationships/participation/target_methods.rb
284
+ - lib/familia/features/relationships/participation_membership.rb
263
285
  - lib/familia/features/relationships/participation_relationship.rb
264
286
  - lib/familia/features/relationships/score_encoding.rb
265
287
  - lib/familia/features/safe_dump.rb
@@ -279,6 +301,7 @@ files:
279
301
  - lib/familia/horreum/settings.rb
280
302
  - lib/familia/horreum/utils.rb
281
303
  - lib/familia/identifier_extractor.rb
304
+ - lib/familia/instrumentation.rb
282
305
  - lib/familia/json_serializer.rb
283
306
  - lib/familia/logging.rb
284
307
  - lib/familia/refinements.rb
@@ -287,9 +310,12 @@ files:
287
310
  - lib/familia/refinements/time_literals.rb
288
311
  - lib/familia/secure_identifier.rb
289
312
  - lib/familia/settings.rb
313
+ - lib/familia/thread_safety/instrumented_mutex.rb
314
+ - lib/familia/thread_safety/monitor.rb
290
315
  - lib/familia/utils.rb
291
316
  - lib/familia/verifiable_identifier.rb
292
317
  - lib/familia/version.rb
318
+ - lib/middleware/database_command_counter.rb
293
319
  - lib/middleware/database_logger.rb
294
320
  - lib/multi_result.rb
295
321
  - pr_agent.toml
@@ -337,11 +363,15 @@ files:
337
363
  - try/features/quantization/quantization_try.rb
338
364
  - try/features/real_feature_integration_try.rb
339
365
  - try/features/relationships/indexing_commands_verification_try.rb
366
+ - try/features/relationships/indexing_rebuild_try.rb
340
367
  - try/features/relationships/indexing_try.rb
368
+ - try/features/relationships/participation_bidirectional_try.rb
341
369
  - try/features/relationships/participation_commands_verification_spec.rb
342
370
  - try/features/relationships/participation_commands_verification_try.rb
343
371
  - try/features/relationships/participation_performance_improvements_try.rb
344
372
  - try/features/relationships/participation_reverse_index_try.rb
373
+ - try/features/relationships/participation_target_class_resolution_try.rb
374
+ - try/features/relationships/participation_unresolved_target_try.rb
345
375
  - try/features/relationships/relationships_api_changes_try.rb
346
376
  - try/features/relationships/relationships_edge_cases_try.rb
347
377
  - try/features/relationships/relationships_performance_minimal_try.rb
@@ -384,10 +414,15 @@ files:
384
414
  - try/integration/models/familia_object_try.rb
385
415
  - try/integration/persistence_operations_try.rb
386
416
  - try/integration/relationships_persistence_round_trip_try.rb
417
+ - try/integration/save_methods_consistency_try.rb
387
418
  - try/integration/scenarios_try.rb
388
419
  - try/integration/secure_identifier_try.rb
420
+ - try/integration/transaction_safety_core_try.rb
421
+ - try/integration/transaction_safety_workflow_try.rb
389
422
  - try/integration/verifiable_identifier_try.rb
423
+ - try/investigation/pipeline_routing/README.md
390
424
  - try/performance/benchmarks_try.rb
425
+ - try/performance/transaction_safety_benchmark_try.rb
391
426
  - try/support/benchmarks/deserialization_benchmark.rb
392
427
  - try/support/benchmarks/deserialization_correctness_test.rb
393
428
  - try/support/debugging/README.md
@@ -437,6 +472,18 @@ files:
437
472
  - try/support/prototypes/pooling/lib/visualize_stress_results.rb
438
473
  - try/support/prototypes/pooling/pool_siege.rb
439
474
  - try/support/prototypes/pooling/run_stress_tests.rb
475
+ - try/thread_safety/README.md
476
+ - try/thread_safety/class_connection_chain_race_try.rb
477
+ - try/thread_safety/connection_chain_race_try.rb
478
+ - try/thread_safety/encryption_manager_cache_race_try.rb
479
+ - try/thread_safety/feature_registry_race_try.rb
480
+ - try/thread_safety/fiber_pipeline_isolation_try.rb
481
+ - try/thread_safety/fiber_transaction_isolation_try.rb
482
+ - try/thread_safety/field_registration_race_try.rb
483
+ - try/thread_safety/logger_initialization_race_try.rb
484
+ - try/thread_safety/middleware_registration_race_try.rb
485
+ - try/thread_safety/module_config_race_try.rb
486
+ - try/thread_safety/secure_identifier_cache_race_try.rb
440
487
  - try/unit/core/autoloader_try.rb
441
488
  - try/unit/core/base_enhancements_try.rb
442
489
  - try/unit/core/connection_try.rb
@@ -444,6 +491,9 @@ files:
444
491
  - try/unit/core/extensions_try.rb
445
492
  - try/unit/core/familia_logger_try.rb
446
493
  - try/unit/core/familia_try.rb
494
+ - try/unit/core/middleware_sampling_try.rb
495
+ - try/unit/core/middleware_test_helpers_bug_try.rb
496
+ - try/unit/core/middleware_thread_safety_try.rb
447
497
  - try/unit/core/middleware_try.rb
448
498
  - try/unit/core/settings_try.rb
449
499
  - try/unit/core/time_utils_try.rb
@@ -459,6 +509,7 @@ files:
459
509
  - try/unit/data_types/sorted_set_zadd_options_try.rb
460
510
  - try/unit/data_types/string_try.rb
461
511
  - try/unit/data_types/unsortedset_try.rb
512
+ - try/unit/familia_resolve_class_try.rb
462
513
  - try/unit/horreum/auto_indexing_on_save_try.rb
463
514
  - try/unit/horreum/automatic_index_validation_try.rb
464
515
  - try/unit/horreum/base_try.rb
@@ -471,16 +522,20 @@ files:
471
522
  - try/unit/horreum/field_definition_try.rb
472
523
  - try/unit/horreum/initialization_try.rb
473
524
  - try/unit/horreum/json_type_preservation_try.rb
525
+ - try/unit/horreum/optimized_loading_try.rb
474
526
  - try/unit/horreum/relations_try.rb
475
527
  - try/unit/horreum/serialization_persistent_fields_try.rb
476
528
  - try/unit/horreum/serialization_try.rb
477
529
  - try/unit/horreum/settings_try.rb
478
530
  - try/unit/horreum/unique_index_edge_cases_try.rb
479
531
  - try/unit/horreum/unique_index_guard_validation_try.rb
532
+ - try/unit/middleware/database_command_counter_methods_try.rb
533
+ - try/unit/middleware/database_logger_methods_try.rb
480
534
  - try/unit/refinements/dear_json_array_methods_try.rb
481
535
  - try/unit/refinements/dear_json_hash_methods_try.rb
482
536
  - try/unit/refinements/time_literals_numeric_methods_try.rb
483
537
  - try/unit/refinements/time_literals_string_methods_try.rb
538
+ - try/unit/thread_safety_monitor_try.rb
484
539
  - try/valkey.conf
485
540
  homepage: https://github.com/delano/familia
486
541
  licenses:
@@ -494,14 +549,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
494
549
  requirements:
495
550
  - - ">="
496
551
  - !ruby/object:Gem::Version
497
- version: '3.4'
552
+ version: 3.3.6
498
553
  required_rubygems_version: !ruby/object:Gem::Requirement
499
554
  requirements:
500
555
  - - ">="
501
556
  - !ruby/object:Gem::Version
502
557
  version: '0'
503
558
  requirements: []
504
- rubygems_version: 3.6.9
559
+ rubygems_version: 3.7.2
505
560
  specification_version: 4
506
561
  summary: An ORM for Valkey-compatible databases in Ruby.
507
562
  test_files: []
@@ -1,138 +0,0 @@
1
- name: Code Quality
2
-
3
- on:
4
- pull_request:
5
- branches: [ main ]
6
- push:
7
- branches: [ main ]
8
- workflow_dispatch:
9
-
10
- permissions:
11
- contents: read
12
- pull-requests: write # Needed to post comments on PRs
13
-
14
- jobs:
15
- reek:
16
- name: Reek Code Analysis
17
- runs-on: ubuntu-24.04
18
- timeout-minutes: 5
19
-
20
- steps:
21
- - name: Checkout code
22
- uses: actions/checkout@v4
23
-
24
- - name: Set up Ruby
25
- uses: ruby/setup-ruby@v1
26
- with:
27
- ruby-version: 3.4
28
- bundler-cache: true
29
-
30
- - name: Configure Bundler for secure gem installation
31
- run: |
32
- bundle config set --local path 'vendor/bundle'
33
- bundle config set --local deployment 'false'
34
-
35
- - name: Install dependencies
36
- run: bundle install
37
-
38
- - name: Run Reek analysis
39
- run: |
40
- echo "=== Running Reek code analysis ==="
41
- echo "This analysis identifies code smells and potential improvements."
42
- echo "Results are informational and won't fail the build."
43
- echo ""
44
-
45
- # Run reek and capture output (don't fail on warnings)
46
- # Use success-exit-code to prevent failures from stopping the analysis
47
- bundle exec reek --format=text --success-exit-code 0 --failure-exit-code 0 || true
48
-
49
- echo ""
50
- echo "=== Reek analysis complete ==="
51
- continue-on-error: true # Don't fail the build on code smells
52
-
53
- - name: Generate Reek report (if analysis available)
54
- run: |
55
- echo "=== Generating detailed Reek report ==="
56
-
57
- # Generate JSON report for potential future processing
58
- bundle exec reek --format=json --success-exit-code 0 --failure-exit-code 0 > reek-report.json || true
59
-
60
- # Display summary
61
- if [ -s reek-report.json ]; then
62
- echo "Reek JSON report generated: $(wc -l < reek-report.json) lines"
63
- echo "Top code smell types found:"
64
- jq -r '.[].smells[].smell_type' reek-report.json 2>/dev/null | sort | uniq -c | sort -rn | head -10 || echo "Unable to parse JSON report"
65
- else
66
- echo "No code smells detected or analysis failed"
67
- fi
68
- continue-on-error: true
69
-
70
- - name: Upload Reek report as artifact
71
- uses: actions/upload-artifact@v4
72
- if: always()
73
- with:
74
- name: reek-report
75
- path: reek-report.json
76
- retention-days: 30
77
-
78
- # Add other code quality checks here
79
- additional-quality-checks:
80
- name: Additional Quality Checks
81
- runs-on: ubuntu-24.04
82
- timeout-minutes: 5
83
-
84
- steps:
85
- - name: Checkout code
86
- uses: actions/checkout@v4
87
-
88
- - name: Set up Ruby
89
- uses: ruby/setup-ruby@v1
90
- with:
91
- ruby-version: 3.4
92
- bundler-cache: true
93
-
94
- - name: Configure Bundler for secure gem installation
95
- run: |
96
- bundle config set --local path 'vendor/bundle'
97
- bundle config set --local deployment 'false'
98
-
99
- - name: Install dependencies
100
- run: bundle install
101
-
102
- - name: Check for TODO/FIXME comments
103
- run: |
104
- echo "=== Scanning for TODO/FIXME comments ==="
105
- echo "This helps track technical debt and action items."
106
- echo ""
107
-
108
- # Find TODO/FIXME comments (excluding this workflow file)
109
- find . -name "*.rb" -not -path "./vendor/*" -not -path "./tmp/*" | \
110
- xargs grep -Hn -i -E "(TODO|FIXME|HACK|XXX|NOTE):" 2>/dev/null | \
111
- head -20 || echo "No TODO/FIXME comments found"
112
- continue-on-error: true
113
-
114
- - name: Check Ruby file syntax
115
- run: |
116
- echo "=== Checking Ruby syntax ==="
117
- echo "Validates that all Ruby files have correct syntax."
118
- echo ""
119
-
120
- find . -name "*.rb" -not -path "./vendor/*" -not -path "./tmp/*" | \
121
- while read -r file; do
122
- if ! ruby -c "$file" > /dev/null 2>&1; then
123
- echo "Syntax error in: $file"
124
- ruby -c "$file"
125
- fi
126
- done
127
- continue-on-error: true
128
-
129
- - name: Check for long lines
130
- run: |
131
- echo "=== Checking for long lines (>120 characters) ==="
132
- echo "Identifies potentially hard-to-read code lines."
133
- echo ""
134
-
135
- find . -name "*.rb" -not -path "./vendor/*" -not -path "./tmp/*" | \
136
- xargs grep -Hn "^.\{121,\}$" | \
137
- head -10 || echo "No overly long lines found"
138
- continue-on-error: true
@@ -1,91 +0,0 @@
1
- .. Added
2
- .. -----
3
- .. New features and capabilities that have been added.
4
-
5
- .. Changed
6
- .. -------
7
- .. Changes to existing functionality.
8
-
9
- .. Deprecated
10
- .. ----------
11
- .. Soon-to-be removed features.
12
-
13
- .. Removed
14
- .. -------
15
- .. Now removed features.
16
-
17
- .. Fixed
18
- .. -----
19
- .. Bug fixes.
20
-
21
- .. Security
22
- .. --------
23
- .. Security-related improvements.
24
-
25
- Added
26
- -----
27
-
28
- - **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 #159 <https://github.com/familia/familia/pull/159>`_
29
-
30
- Key capabilities added:
31
-
32
- * ``transaction`` method for atomic MULTI/EXEC operations on all DataType classes
33
- * ``pipelined`` method for batched command execution on all DataType classes
34
- * Connection chain pattern with Chain of Responsibility for DataType objects
35
- * Two new connection handlers: ``ParentDelegationHandler`` for owned DataTypes and ``StandaloneConnectionHandler`` for independent DataTypes
36
- * Enhanced ``direct_access`` method with automatic transaction/pipeline context detection
37
- * Shared ``Familia::Connection::Behavior`` module extracting common connection functionality
38
-
39
- This enhancement addresses a critical gap where standalone DataType objects could not guarantee atomicity across multiple operations. A prime example is session storage implementations (similar to Rack::Session stores) where setting session data and expiration must be atomic to prevent memory leaks or security issues. Both parent-owned DataTypes (delegating to parent Horreum objects) and standalone DataTypes now support the full transaction and pipeline API.
40
-
41
- Example usage:
42
-
43
- .. code-block:: ruby
44
-
45
- # Recommended: Use DataType methods for clean, key-free syntax
46
- # Parent-owned DataType transaction
47
- user.scores.transaction do
48
- user.scores.add('level1', 100)
49
- user.scores.add('level2', 200)
50
- end
51
-
52
- # Standalone DataType transaction (e.g., session storage)
53
- session_store = Familia::StringKey.new('session:abc123')
54
- session_store.transaction do
55
- session_store.set(session_data)
56
- session_store.update_expiration(expiration: 3600)
57
- end
58
-
59
- # Pipeline for performance optimization
60
- leaderboard.pipelined do
61
- leaderboard.add('player1', 500)
62
- leaderboard.add('player2', 600)
63
- leaderboard.size
64
- end
65
-
66
- # Advanced: Connection available for low-level Redis commands when needed
67
- user.scores.transaction do |conn|
68
- conn.zadd(user.scores.dbkey, 100, 'level1')
69
- conn.hset(user.profile.dbkey, 'status', 'active')
70
- end
71
-
72
- Changed
73
- -------
74
-
75
- - **DataType URI Construction** - 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.
76
-
77
- - **Horreum::Connection 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. This refactoring improves maintainability while preserving all existing functionality.
78
-
79
- AI Assistance
80
- -------------
81
-
82
- This feature was implemented with significant AI assistance from Claude (Anthropic). The AI helped with:
83
-
84
- * Architectural design of the connection chain pattern for DataType objects
85
- * Implementation of the shared Behavior module to extract common functionality
86
- * Creation of DataType-specific connection handlers (ParentDelegationHandler, StandaloneConnectionHandler)
87
- * Comprehensive test coverage including transaction and pipeline integration tests
88
- * Documentation and changelog preparation
89
- * Debugging and fixing URI formatting edge cases
90
-
91
- The implementation preserves backward compatibility (all 2,216 existing tests pass) while adding 27 new tests specifically for DataType transaction and pipeline support.
@@ -1,30 +0,0 @@
1
- .. A new scriv changelog fragment.
2
- ..
3
- .. Uncomment the section that is right (remove the leading dots).
4
- .. For top level release notes, leave all the headers commented out.
5
- ..
6
- Added
7
- -----
8
-
9
- - Automatic validation in ``add_to_*`` methods for instance-scoped unique indexes. Previously required manual ``guard_unique_*!`` call before adding to index; now validation happens automatically with clear error messages on duplicate detection.
10
-
11
- - Transaction detection in ``save()`` method. Raises ``Familia::OperationModeError`` when ``save()`` is called within an existing transaction, since unique index guards need to read current values which is not possible inside MULTI/EXEC blocks.
12
-
13
- Changed
14
- -------
15
-
16
- - Instance-scoped unique index ``add_to_*`` methods now automatically validate uniqueness before adding to parent's index. This matches modern ORM expectations where constraint validation happens implicitly during mutation operations.
17
-
18
- Documentation
19
- -------------
20
-
21
- - Enhanced ``save()`` method documentation to explain transaction restrictions and unique index validation flow.
22
-
23
- - Updated ``UniqueIndexGenerators`` documentation to clarify that ``add_to_*`` methods perform automatic validation.
24
-
25
- - Added comprehensive test suite (21 test cases) demonstrating automatic validation behavior, transaction detection, and error handling patterns.
26
-
27
- AI Assistance
28
- -------------
29
-
30
- - Claude Sonnet 4.5 assisted with implementation design, test coverage, and documentation for automatic unique index validation and transaction detection features.
@@ -1,13 +0,0 @@
1
-
2
- Changed
3
- -------
4
-
5
- - **IndexingRelationship**: Added explicit ``:within`` field to preserve the original DSL parameter, replacing brittle ``target_class`` equality checks with clearer ``within.nil?`` checks. This makes the distinction between class-level and instance-scoped indexes more explicit and prevents potential issues with inheritance scenarios.
6
-
7
- AI Assistance
8
- -------------
9
-
10
- - Design review and architectural analysis by Claude Code (Sonnet 4.5) via second-opinion agent, identifying brittleness in class comparison logic and recommending explicit storage of the ``within`` parameter.
11
- - Implementation of the ``within`` field addition across IndexingRelationship, generators, and usage sites by Claude Code.
12
- - All tests verified passing with no behavioral changes.
13
- ..