familia 2.0.0.pre19 → 2.0.0.pre22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (370) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/claude-code-review.yml +4 -9
  3. data/.github/workflows/code-smells.yml +64 -3
  4. data/.pre-commit-config.yaml +8 -6
  5. data/.reek.yml +10 -9
  6. data/.rubocop.yml +4 -0
  7. data/.talismanrc +5 -1
  8. data/CHANGELOG.rst +220 -112
  9. data/CLAUDE.md +28 -1
  10. data/Gemfile +1 -1
  11. data/Gemfile.lock +20 -17
  12. data/bin/try +16 -0
  13. data/bin/tryouts +16 -0
  14. data/docs/1106-participates_in-bidirectional-solution.md +129 -0
  15. data/docs/guides/encryption.md +486 -0
  16. data/docs/guides/feature-encrypted-fields.md +123 -7
  17. data/docs/guides/feature-expiration.md +161 -117
  18. data/docs/guides/feature-external-identifiers.md +415 -443
  19. data/docs/guides/feature-object-identifiers.md +400 -269
  20. data/docs/guides/feature-quantization.md +120 -6
  21. data/docs/guides/feature-relationships-indexing.md +318 -0
  22. data/docs/guides/feature-relationships-methods.md +146 -604
  23. data/docs/guides/feature-relationships-participation.md +263 -0
  24. data/docs/guides/feature-relationships.md +118 -136
  25. data/docs/guides/feature-system-devs.md +176 -693
  26. data/docs/guides/feature-system.md +119 -6
  27. data/docs/guides/feature-transient-fields.md +81 -0
  28. data/docs/guides/field-system.md +778 -0
  29. data/docs/guides/index.md +32 -15
  30. data/docs/guides/logging.md +187 -0
  31. data/docs/guides/optimized-loading.md +674 -0
  32. data/docs/guides/thread-safety-monitoring.md +61 -0
  33. data/docs/guides/{time-utilities.md → time-literals.md} +12 -12
  34. data/docs/migrating/v2.0.0-pre22.md +241 -0
  35. data/docs/overview.md +7 -9
  36. data/docs/reference/api-technical.md +267 -320
  37. data/examples/autoloader/mega_customer/features/deprecated_fields.rb +2 -0
  38. data/examples/autoloader/mega_customer/safe_dump_fields.rb +2 -0
  39. data/examples/autoloader/mega_customer.rb +2 -0
  40. data/examples/datatype_standalone.rb +4 -3
  41. data/examples/encrypted_fields.rb +2 -1
  42. data/examples/json_usage_patterns.rb +2 -0
  43. data/examples/relationships.rb +3 -0
  44. data/examples/safe_dump.rb +2 -1
  45. data/examples/sampling_demo.rb +53 -0
  46. data/examples/single_connection_transaction_confusions.rb +2 -1
  47. data/familia.gemspec +2 -1
  48. data/lib/familia/base.rb +2 -0
  49. data/lib/familia/connection/behavior.rb +2 -0
  50. data/lib/familia/connection/handlers.rb +2 -0
  51. data/lib/familia/connection/individual_command_proxy.rb +2 -0
  52. data/lib/familia/connection/middleware.rb +34 -24
  53. data/lib/familia/connection/operation_core.rb +3 -2
  54. data/lib/familia/connection/operations.rb +2 -0
  55. data/lib/familia/connection/pipelined_core.rb +3 -3
  56. data/lib/familia/connection/transaction_core.rb +69 -2
  57. data/lib/familia/connection.rb +18 -3
  58. data/lib/familia/data_type/class_methods.rb +3 -1
  59. data/lib/familia/data_type/connection.rb +2 -0
  60. data/lib/familia/data_type/database_commands.rb +2 -0
  61. data/lib/familia/data_type/serialization.rb +79 -52
  62. data/lib/familia/data_type/settings.rb +2 -0
  63. data/lib/familia/data_type/types/counter.rb +2 -0
  64. data/lib/familia/data_type/types/hashkey.rb +7 -5
  65. data/lib/familia/data_type/types/listkey.rb +2 -0
  66. data/lib/familia/data_type/types/lock.rb +2 -0
  67. data/lib/familia/data_type/types/sorted_set.rb +7 -10
  68. data/lib/familia/data_type/types/stringkey.rb +24 -0
  69. data/lib/familia/data_type/types/unsorted_set.rb +2 -0
  70. data/lib/familia/data_type.rb +2 -0
  71. data/lib/familia/encryption/encrypted_data.rb +4 -2
  72. data/lib/familia/encryption/manager.rb +2 -0
  73. data/lib/familia/encryption/provider.rb +2 -0
  74. data/lib/familia/encryption/providers/aes_gcm_provider.rb +2 -0
  75. data/lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb +2 -0
  76. data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +2 -0
  77. data/lib/familia/encryption/registry.rb +2 -0
  78. data/lib/familia/encryption/request_cache.rb +2 -0
  79. data/lib/familia/encryption.rb +9 -2
  80. data/lib/familia/errors.rb +2 -0
  81. data/lib/familia/features/autoloader.rb +2 -0
  82. data/lib/familia/features/encrypted_fields/concealed_string.rb +2 -0
  83. data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +4 -0
  84. data/lib/familia/features/encrypted_fields.rb +2 -2
  85. data/lib/familia/features/expiration/extensions.rb +3 -1
  86. data/lib/familia/features/expiration.rb +12 -4
  87. data/lib/familia/features/external_identifier.rb +62 -7
  88. data/lib/familia/features/object_identifier.rb +49 -0
  89. data/lib/familia/features/quantization.rb +3 -1
  90. data/lib/familia/features/relationships/README.md +3 -1
  91. data/lib/familia/features/relationships/collection_operations.rb +2 -0
  92. data/lib/familia/features/relationships/indexing/multi_index_generators.rb +138 -9
  93. data/lib/familia/features/relationships/indexing/rebuild_strategies.rb +479 -0
  94. data/lib/familia/features/relationships/indexing/unique_index_generators.rb +97 -21
  95. data/lib/familia/features/relationships/indexing.rb +3 -0
  96. data/lib/familia/features/relationships/indexing_relationship.rb +3 -1
  97. data/lib/familia/features/relationships/participation/participant_methods.rb +131 -14
  98. data/lib/familia/features/relationships/participation/rebuild_strategies.md +41 -0
  99. data/lib/familia/features/relationships/participation/target_methods.rb +6 -6
  100. data/lib/familia/features/relationships/participation.rb +155 -69
  101. data/lib/familia/features/relationships/participation_membership.rb +69 -0
  102. data/lib/familia/features/relationships/participation_relationship.rb +34 -6
  103. data/lib/familia/features/relationships/score_encoding.rb +2 -0
  104. data/lib/familia/features/relationships.rb +5 -3
  105. data/lib/familia/features/safe_dump.rb +2 -0
  106. data/lib/familia/features/transient_fields/redacted_string.rb +2 -0
  107. data/lib/familia/features/transient_fields/single_use_redacted_string.rb +2 -0
  108. data/lib/familia/features/transient_fields/transient_field_type.rb +5 -3
  109. data/lib/familia/features/transient_fields.rb +2 -0
  110. data/lib/familia/features.rb +2 -0
  111. data/lib/familia/field_type.rb +3 -1
  112. data/lib/familia/horreum/connection.rb +17 -1
  113. data/lib/familia/horreum/database_commands.rb +8 -1
  114. data/lib/familia/horreum/definition.rb +16 -6
  115. data/lib/familia/horreum/management.rb +353 -52
  116. data/lib/familia/horreum/persistence.rb +179 -108
  117. data/lib/familia/horreum/related_fields.rb +2 -0
  118. data/lib/familia/horreum/serialization.rb +23 -4
  119. data/lib/familia/horreum/settings.rb +2 -0
  120. data/lib/familia/horreum/utils.rb +2 -0
  121. data/lib/familia/horreum.rb +15 -1
  122. data/lib/familia/identifier_extractor.rb +3 -1
  123. data/lib/familia/instrumentation.rb +156 -0
  124. data/lib/familia/json_serializer.rb +2 -0
  125. data/lib/familia/logging.rb +92 -32
  126. data/lib/familia/refinements/dear_json.rb +2 -0
  127. data/lib/familia/refinements/stylize_words.rb +2 -14
  128. data/lib/familia/refinements/time_literals.rb +2 -0
  129. data/lib/familia/refinements.rb +2 -0
  130. data/lib/familia/secure_identifier.rb +10 -2
  131. data/lib/familia/settings.rb +2 -0
  132. data/lib/familia/thread_safety/instrumented_mutex.rb +166 -0
  133. data/lib/familia/thread_safety/monitor.rb +328 -0
  134. data/lib/familia/utils.rb +13 -0
  135. data/lib/familia/verifiable_identifier.rb +3 -1
  136. data/lib/familia/version.rb +3 -1
  137. data/lib/familia.rb +31 -4
  138. data/lib/middleware/database_command_counter.rb +152 -0
  139. data/lib/middleware/database_logger.rb +295 -170
  140. data/lib/multi_result.rb +61 -31
  141. data/try/edge_cases/empty_identifiers_try.rb +2 -0
  142. data/try/edge_cases/hash_symbolization_try.rb +2 -0
  143. data/try/edge_cases/json_serialization_try.rb +2 -0
  144. data/try/edge_cases/legacy_data_detection/deserialization_edge_cases_try.rb +4 -0
  145. data/try/edge_cases/race_conditions_try.rb +4 -0
  146. data/try/edge_cases/reserved_keywords_try.rb +4 -0
  147. data/try/edge_cases/string_coercion_try.rb +2 -0
  148. data/try/edge_cases/ttl_side_effects_try.rb +4 -0
  149. data/try/features/count_any_edge_cases_try.rb +486 -0
  150. data/try/features/count_any_methods_try.rb +197 -0
  151. data/try/features/encrypted_fields/aad_protection_try.rb +4 -0
  152. data/try/features/encrypted_fields/concealed_string_core_try.rb +4 -0
  153. data/try/features/encrypted_fields/context_isolation_try.rb +4 -0
  154. data/try/features/encrypted_fields/encrypted_fields_core_try.rb +33 -0
  155. data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +4 -0
  156. data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +4 -0
  157. data/try/features/encrypted_fields/encrypted_fields_security_try.rb +4 -0
  158. data/try/features/encrypted_fields/error_conditions_try.rb +4 -0
  159. data/try/features/encrypted_fields/fresh_key_derivation_try.rb +4 -0
  160. data/try/features/encrypted_fields/fresh_key_try.rb +4 -0
  161. data/try/features/encrypted_fields/key_rotation_try.rb +4 -0
  162. data/try/features/encrypted_fields/memory_security_try.rb +4 -0
  163. data/try/features/encrypted_fields/missing_current_key_version_try.rb +4 -0
  164. data/try/features/encrypted_fields/nonce_uniqueness_try.rb +4 -0
  165. data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +4 -0
  166. data/try/features/encrypted_fields/thread_safety_try.rb +4 -0
  167. data/try/features/encrypted_fields/universal_serialization_safety_try.rb +4 -0
  168. data/try/features/encryption/config_persistence_try.rb +4 -0
  169. data/try/features/encryption/core_try.rb +4 -0
  170. data/try/features/encryption/instance_variable_scope_try.rb +4 -0
  171. data/try/features/encryption/module_loading_try.rb +4 -0
  172. data/try/features/encryption/providers/aes_gcm_provider_try.rb +4 -0
  173. data/try/features/encryption/providers/xchacha20_poly1305_provider_try.rb +4 -0
  174. data/try/features/encryption/roundtrip_validation_try.rb +4 -0
  175. data/try/features/encryption/secure_memory_handling_try.rb +4 -0
  176. data/try/features/expiration/expiration_try.rb +4 -0
  177. data/try/features/external_identifier/external_identifier_try.rb +305 -8
  178. data/try/features/feature_dependencies_try.rb +2 -0
  179. data/try/features/feature_improvements_try.rb +2 -0
  180. data/try/features/field_groups_try.rb +2 -0
  181. data/try/features/object_identifier/object_identifier_integration_try.rb +12 -9
  182. data/try/features/object_identifier/object_identifier_try.rb +140 -0
  183. data/try/features/quantization/quantization_try.rb +4 -0
  184. data/try/features/real_feature_integration_try.rb +2 -0
  185. data/try/features/relationships/indexing_commands_verification_try.rb +2 -0
  186. data/try/features/relationships/indexing_rebuild_try.rb +606 -0
  187. data/try/features/relationships/indexing_try.rb +2 -0
  188. data/try/features/relationships/participation_bidirectional_try.rb +242 -0
  189. data/try/features/relationships/participation_commands_verification_spec.rb +4 -0
  190. data/try/features/relationships/participation_commands_verification_try.rb +2 -0
  191. data/try/features/relationships/participation_performance_improvements_try.rb +11 -9
  192. data/try/features/relationships/participation_reverse_index_try.rb +15 -13
  193. data/try/features/relationships/participation_target_class_resolution_try.rb +209 -0
  194. data/try/features/relationships/participation_unresolved_target_try.rb +109 -0
  195. data/try/features/relationships/relationships_api_changes_try.rb +2 -0
  196. data/try/features/relationships/relationships_edge_cases_try.rb +4 -0
  197. data/try/features/relationships/relationships_performance_minimal_try.rb +4 -0
  198. data/try/features/relationships/relationships_performance_simple_try.rb +4 -0
  199. data/try/features/relationships/relationships_performance_try.rb +4 -0
  200. data/try/features/relationships/relationships_performance_working_try.rb +4 -0
  201. data/try/features/relationships/relationships_try.rb +6 -4
  202. data/try/features/safe_dump/safe_dump_advanced_try.rb +4 -0
  203. data/try/features/safe_dump/safe_dump_try.rb +4 -0
  204. data/try/features/transient_fields/redacted_string_try.rb +2 -0
  205. data/try/features/transient_fields/refresh_reset_try.rb +3 -0
  206. data/try/features/transient_fields/simple_refresh_test.rb +3 -0
  207. data/try/features/transient_fields/single_use_redacted_string_try.rb +2 -0
  208. data/try/features/transient_fields/transient_fields_core_try.rb +4 -0
  209. data/try/features/transient_fields/transient_fields_integration_try.rb +4 -0
  210. data/try/integration/connection/fiber_context_preservation_try.rb +4 -0
  211. data/try/integration/connection/handler_constraints_try.rb +4 -0
  212. data/try/integration/connection/isolated_dbclient_try.rb +4 -0
  213. data/try/integration/connection/middleware_reconnect_try.rb +2 -0
  214. data/try/integration/connection/operation_mode_guards_try.rb +4 -0
  215. data/try/integration/connection/pipeline_fallback_integration_try.rb +3 -0
  216. data/try/integration/connection/pools_try.rb +4 -0
  217. data/try/integration/connection/responsibility_chain_tracking_try.rb +4 -0
  218. data/try/integration/connection/transaction_fallback_integration_try.rb +4 -0
  219. data/try/integration/connection/transaction_mode_permissive_try.rb +4 -0
  220. data/try/integration/connection/transaction_mode_strict_try.rb +4 -0
  221. data/try/integration/connection/transaction_mode_warn_try.rb +4 -0
  222. data/try/integration/connection/transaction_modes_try.rb +4 -0
  223. data/try/integration/conventional_inheritance_try.rb +4 -0
  224. data/try/integration/create_method_try.rb +4 -0
  225. data/try/integration/cross_component_try.rb +4 -0
  226. data/try/integration/data_types/datatype_pipelines_try.rb +9 -3
  227. data/try/integration/data_types/datatype_transactions_try.rb +17 -7
  228. data/try/integration/database_consistency_try.rb +4 -0
  229. data/try/integration/familia_extended_try.rb +4 -0
  230. data/try/integration/familia_members_methods_try.rb +4 -0
  231. data/try/integration/models/customer_safe_dump_try.rb +4 -0
  232. data/try/integration/models/customer_try.rb +7 -3
  233. data/try/integration/models/datatype_base_try.rb +4 -0
  234. data/try/integration/models/familia_object_try.rb +4 -0
  235. data/try/integration/persistence_operations_try.rb +4 -0
  236. data/try/integration/relationships_persistence_round_trip_try.rb +17 -14
  237. data/try/integration/save_methods_consistency_try.rb +241 -0
  238. data/try/integration/scenarios_try.rb +4 -0
  239. data/try/integration/secure_identifier_try.rb +4 -0
  240. data/try/integration/transaction_safety_core_try.rb +176 -0
  241. data/try/integration/transaction_safety_workflow_try.rb +291 -0
  242. data/try/integration/verifiable_identifier_try.rb +4 -0
  243. data/try/investigation/pipeline_routing/README.md +228 -0
  244. data/try/performance/benchmarks_try.rb +4 -0
  245. data/try/performance/transaction_safety_benchmark_try.rb +238 -0
  246. data/try/support/benchmarks/deserialization_benchmark.rb +3 -1
  247. data/try/support/benchmarks/deserialization_correctness_test.rb +3 -1
  248. data/try/support/debugging/cache_behavior_tracer.rb +4 -0
  249. data/try/support/debugging/debug_aad_process.rb +3 -0
  250. data/try/support/debugging/debug_concealed_internal.rb +3 -0
  251. data/try/support/debugging/debug_concealed_reveal.rb +3 -0
  252. data/try/support/debugging/debug_context_aad.rb +3 -0
  253. data/try/support/debugging/debug_context_simple.rb +3 -0
  254. data/try/support/debugging/debug_cross_context.rb +3 -0
  255. data/try/support/debugging/debug_database_load.rb +3 -0
  256. data/try/support/debugging/debug_encrypted_json_check.rb +3 -0
  257. data/try/support/debugging/debug_encrypted_json_step_by_step.rb +3 -0
  258. data/try/support/debugging/debug_exists_lifecycle.rb +3 -0
  259. data/try/support/debugging/debug_field_decrypt.rb +3 -0
  260. data/try/support/debugging/debug_fresh_cross_context.rb +3 -0
  261. data/try/support/debugging/debug_load_path.rb +3 -0
  262. data/try/support/debugging/debug_method_definition.rb +3 -0
  263. data/try/support/debugging/debug_method_resolution.rb +3 -0
  264. data/try/support/debugging/debug_minimal.rb +3 -0
  265. data/try/support/debugging/debug_provider.rb +3 -0
  266. data/try/support/debugging/debug_secure_behavior.rb +3 -0
  267. data/try/support/debugging/debug_string_class.rb +3 -0
  268. data/try/support/debugging/debug_test.rb +3 -0
  269. data/try/support/debugging/debug_test_design.rb +3 -0
  270. data/try/support/debugging/encryption_method_tracer.rb +4 -0
  271. data/try/support/debugging/provider_diagnostics.rb +4 -0
  272. data/try/support/helpers/test_cleanup.rb +4 -0
  273. data/try/support/helpers/test_helpers.rb +5 -0
  274. data/try/support/memory/memory_basic_test.rb +4 -0
  275. data/try/support/memory/memory_detailed_test.rb +4 -0
  276. data/try/support/memory/memory_search_for_string.rb +4 -0
  277. data/try/support/memory/test_actual_redactedstring_protection.rb +4 -0
  278. data/try/support/prototypes/atomic_saves_v1_context_proxy.rb +4 -0
  279. data/try/support/prototypes/atomic_saves_v2_connection_switching.rb +4 -0
  280. data/try/support/prototypes/atomic_saves_v3_connection_pool.rb +4 -0
  281. data/try/support/prototypes/atomic_saves_v4.rb +4 -0
  282. data/try/support/prototypes/lib/atomic_saves_v2_connection_switching_helpers.rb +4 -0
  283. data/try/support/prototypes/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -0
  284. data/try/support/prototypes/pooling/configurable_stress_test.rb +4 -0
  285. data/try/support/prototypes/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -0
  286. data/try/support/prototypes/pooling/lib/connection_pool_metrics.rb +4 -0
  287. data/try/support/prototypes/pooling/lib/connection_pool_stress_test.rb +4 -0
  288. data/try/support/prototypes/pooling/lib/connection_pool_threading_models.rb +4 -0
  289. data/try/support/prototypes/pooling/lib/visualize_stress_results.rb +4 -2
  290. data/try/support/prototypes/pooling/pool_siege.rb +4 -2
  291. data/try/support/prototypes/pooling/run_stress_tests.rb +4 -2
  292. data/try/thread_safety/README.md +496 -0
  293. data/try/thread_safety/class_connection_chain_race_try.rb +265 -0
  294. data/try/thread_safety/connection_chain_race_try.rb +148 -0
  295. data/try/thread_safety/encryption_manager_cache_race_try.rb +166 -0
  296. data/try/thread_safety/feature_registry_race_try.rb +226 -0
  297. data/try/thread_safety/fiber_pipeline_isolation_try.rb +235 -0
  298. data/try/thread_safety/fiber_transaction_isolation_try.rb +208 -0
  299. data/try/thread_safety/field_registration_race_try.rb +222 -0
  300. data/try/thread_safety/logger_initialization_race_try.rb +170 -0
  301. data/try/thread_safety/middleware_registration_race_try.rb +154 -0
  302. data/try/thread_safety/module_config_race_try.rb +175 -0
  303. data/try/thread_safety/secure_identifier_cache_race_try.rb +226 -0
  304. data/try/unit/core/autoloader_try.rb +4 -0
  305. data/try/unit/core/base_enhancements_try.rb +4 -0
  306. data/try/unit/core/connection_try.rb +4 -0
  307. data/try/unit/core/errors_try.rb +4 -0
  308. data/try/unit/core/extensions_try.rb +4 -0
  309. data/try/unit/core/familia_logger_try.rb +2 -0
  310. data/try/unit/core/familia_try.rb +4 -0
  311. data/try/unit/core/middleware_sampling_try.rb +335 -0
  312. data/try/unit/core/middleware_test_helpers_bug_try.rb +58 -0
  313. data/try/unit/core/middleware_thread_safety_try.rb +245 -0
  314. data/try/unit/core/middleware_try.rb +4 -0
  315. data/try/unit/core/settings_try.rb +4 -0
  316. data/try/unit/core/time_utils_try.rb +4 -0
  317. data/try/unit/core/tools_try.rb +4 -0
  318. data/try/unit/core/utils_try.rb +37 -0
  319. data/try/unit/data_types/boolean_try.rb +39 -22
  320. data/try/unit/data_types/counter_try.rb +4 -0
  321. data/try/unit/data_types/datatype_base_try.rb +4 -0
  322. data/try/unit/data_types/hash_try.rb +6 -2
  323. data/try/unit/data_types/list_try.rb +4 -0
  324. data/try/unit/data_types/lock_try.rb +4 -0
  325. data/try/unit/data_types/serialization_try.rb +386 -0
  326. data/try/unit/data_types/sorted_set_try.rb +4 -0
  327. data/try/unit/data_types/sorted_set_zadd_options_try.rb +4 -0
  328. data/try/unit/data_types/string_try.rb +4 -0
  329. data/try/unit/data_types/unsortedset_try.rb +4 -0
  330. data/try/unit/familia_resolve_class_try.rb +116 -0
  331. data/try/unit/horreum/auto_indexing_on_save_try.rb +5 -1
  332. data/try/unit/horreum/automatic_index_validation_try.rb +2 -0
  333. data/try/unit/horreum/base_try.rb +4 -0
  334. data/try/unit/horreum/class_methods_try.rb +4 -0
  335. data/try/unit/horreum/commands_try.rb +4 -0
  336. data/try/unit/horreum/defensive_initialization_try.rb +4 -0
  337. data/try/unit/horreum/destroy_related_fields_cleanup_try.rb +6 -1
  338. data/try/unit/horreum/enhanced_conflict_handling_try.rb +4 -0
  339. data/try/unit/horreum/field_categories_try.rb +4 -0
  340. data/try/unit/horreum/field_definition_try.rb +4 -0
  341. data/try/unit/horreum/initialization_try.rb +4 -0
  342. data/try/unit/horreum/json_type_preservation_try.rb +2 -0
  343. data/try/unit/horreum/optimized_loading_try.rb +156 -0
  344. data/try/unit/horreum/relations_try.rb +4 -0
  345. data/try/unit/horreum/serialization_persistent_fields_try.rb +4 -0
  346. data/try/unit/horreum/serialization_try.rb +4 -0
  347. data/try/unit/horreum/settings_try.rb +4 -0
  348. data/try/unit/horreum/unique_index_edge_cases_try.rb +4 -0
  349. data/try/unit/horreum/unique_index_guard_validation_try.rb +2 -0
  350. data/try/unit/middleware/database_command_counter_methods_try.rb +139 -0
  351. data/try/unit/middleware/database_logger_methods_try.rb +251 -0
  352. data/try/unit/refinements/dear_json_array_methods_try.rb +4 -0
  353. data/try/unit/refinements/dear_json_hash_methods_try.rb +4 -0
  354. data/try/unit/refinements/time_literals_numeric_methods_try.rb +4 -0
  355. data/try/unit/refinements/time_literals_string_methods_try.rb +4 -0
  356. data/try/unit/thread_safety_monitor_try.rb +149 -0
  357. metadata +69 -17
  358. data/.github/workflows/code-quality.yml +0 -138
  359. data/changelog.d/20251011_012003_delano_159_datatype_transaction_pipeline_support.rst +0 -91
  360. data/changelog.d/20251011_203905_delano_next.rst +0 -30
  361. data/changelog.d/20251011_212633_delano_next.rst +0 -13
  362. data/changelog.d/20251011_221253_delano_next.rst +0 -26
  363. data/docs/archive/FAMILIA_RELATIONSHIPS.md +0 -210
  364. data/docs/archive/FAMILIA_TECHNICAL.md +0 -823
  365. data/docs/archive/FAMILIA_UPDATE.md +0 -226
  366. data/docs/archive/README.md +0 -64
  367. data/docs/archive/api-reference.md +0 -333
  368. data/docs/guides/core-field-system.md +0 -806
  369. data/docs/guides/implementation.md +0 -276
  370. data/docs/guides/security-model.md +0 -183
@@ -0,0 +1,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.pre22
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,33 @@ 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
160
171
  - changelog.d/README.md
161
172
  - changelog.d/scriv.ini
173
+ - docs/1106-participates_in-bidirectional-solution.md
162
174
  - 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
175
  - docs/conf.py
169
176
  - docs/guides/.gitignore
170
- - docs/guides/core-field-system.md
177
+ - docs/guides/encryption.md
171
178
  - docs/guides/feature-encrypted-fields.md
172
179
  - docs/guides/feature-expiration.md
173
180
  - docs/guides/feature-external-identifiers.md
174
181
  - docs/guides/feature-object-identifiers.md
175
182
  - docs/guides/feature-quantization.md
183
+ - docs/guides/feature-relationships-indexing.md
176
184
  - docs/guides/feature-relationships-methods.md
185
+ - docs/guides/feature-relationships-participation.md
177
186
  - docs/guides/feature-relationships.md
178
187
  - docs/guides/feature-system-devs.md
179
188
  - docs/guides/feature-system.md
180
189
  - docs/guides/feature-transient-fields.md
181
- - docs/guides/implementation.md
190
+ - docs/guides/field-system.md
182
191
  - docs/guides/index.md
183
- - docs/guides/security-model.md
184
- - docs/guides/time-utilities.md
192
+ - docs/guides/logging.md
193
+ - docs/guides/optimized-loading.md
194
+ - docs/guides/thread-safety-monitoring.md
195
+ - docs/guides/time-literals.md
185
196
  - docs/migrating/.gitignore
186
197
  - docs/migrating/v2.0.0-pre.md
187
198
  - docs/migrating/v2.0.0-pre11.md
@@ -190,6 +201,7 @@ files:
190
201
  - docs/migrating/v2.0.0-pre14.md
191
202
  - docs/migrating/v2.0.0-pre18.md
192
203
  - docs/migrating/v2.0.0-pre19.md
204
+ - docs/migrating/v2.0.0-pre22.md
193
205
  - docs/migrating/v2.0.0-pre5.md
194
206
  - docs/migrating/v2.0.0-pre6.md
195
207
  - docs/migrating/v2.0.0-pre7.md
@@ -204,6 +216,7 @@ files:
204
216
  - examples/json_usage_patterns.rb
205
217
  - examples/relationships.rb
206
218
  - examples/safe_dump.rb
219
+ - examples/sampling_demo.rb
207
220
  - examples/single_connection_transaction_confusions.rb
208
221
  - familia.gemspec
209
222
  - lib/familia.rb
@@ -255,11 +268,14 @@ files:
255
268
  - lib/familia/features/relationships/collection_operations.rb
256
269
  - lib/familia/features/relationships/indexing.rb
257
270
  - lib/familia/features/relationships/indexing/multi_index_generators.rb
271
+ - lib/familia/features/relationships/indexing/rebuild_strategies.rb
258
272
  - lib/familia/features/relationships/indexing/unique_index_generators.rb
259
273
  - lib/familia/features/relationships/indexing_relationship.rb
260
274
  - lib/familia/features/relationships/participation.rb
261
275
  - lib/familia/features/relationships/participation/participant_methods.rb
276
+ - lib/familia/features/relationships/participation/rebuild_strategies.md
262
277
  - lib/familia/features/relationships/participation/target_methods.rb
278
+ - lib/familia/features/relationships/participation_membership.rb
263
279
  - lib/familia/features/relationships/participation_relationship.rb
264
280
  - lib/familia/features/relationships/score_encoding.rb
265
281
  - lib/familia/features/safe_dump.rb
@@ -279,6 +295,7 @@ files:
279
295
  - lib/familia/horreum/settings.rb
280
296
  - lib/familia/horreum/utils.rb
281
297
  - lib/familia/identifier_extractor.rb
298
+ - lib/familia/instrumentation.rb
282
299
  - lib/familia/json_serializer.rb
283
300
  - lib/familia/logging.rb
284
301
  - lib/familia/refinements.rb
@@ -287,9 +304,12 @@ files:
287
304
  - lib/familia/refinements/time_literals.rb
288
305
  - lib/familia/secure_identifier.rb
289
306
  - lib/familia/settings.rb
307
+ - lib/familia/thread_safety/instrumented_mutex.rb
308
+ - lib/familia/thread_safety/monitor.rb
290
309
  - lib/familia/utils.rb
291
310
  - lib/familia/verifiable_identifier.rb
292
311
  - lib/familia/version.rb
312
+ - lib/middleware/database_command_counter.rb
293
313
  - lib/middleware/database_logger.rb
294
314
  - lib/multi_result.rb
295
315
  - pr_agent.toml
@@ -302,6 +322,8 @@ files:
302
322
  - try/edge_cases/reserved_keywords_try.rb
303
323
  - try/edge_cases/string_coercion_try.rb
304
324
  - try/edge_cases/ttl_side_effects_try.rb
325
+ - try/features/count_any_edge_cases_try.rb
326
+ - try/features/count_any_methods_try.rb
305
327
  - try/features/encrypted_fields/aad_protection_try.rb
306
328
  - try/features/encrypted_fields/concealed_string_core_try.rb
307
329
  - try/features/encrypted_fields/context_isolation_try.rb
@@ -337,11 +359,15 @@ files:
337
359
  - try/features/quantization/quantization_try.rb
338
360
  - try/features/real_feature_integration_try.rb
339
361
  - try/features/relationships/indexing_commands_verification_try.rb
362
+ - try/features/relationships/indexing_rebuild_try.rb
340
363
  - try/features/relationships/indexing_try.rb
364
+ - try/features/relationships/participation_bidirectional_try.rb
341
365
  - try/features/relationships/participation_commands_verification_spec.rb
342
366
  - try/features/relationships/participation_commands_verification_try.rb
343
367
  - try/features/relationships/participation_performance_improvements_try.rb
344
368
  - try/features/relationships/participation_reverse_index_try.rb
369
+ - try/features/relationships/participation_target_class_resolution_try.rb
370
+ - try/features/relationships/participation_unresolved_target_try.rb
345
371
  - try/features/relationships/relationships_api_changes_try.rb
346
372
  - try/features/relationships/relationships_edge_cases_try.rb
347
373
  - try/features/relationships/relationships_performance_minimal_try.rb
@@ -384,10 +410,15 @@ files:
384
410
  - try/integration/models/familia_object_try.rb
385
411
  - try/integration/persistence_operations_try.rb
386
412
  - try/integration/relationships_persistence_round_trip_try.rb
413
+ - try/integration/save_methods_consistency_try.rb
387
414
  - try/integration/scenarios_try.rb
388
415
  - try/integration/secure_identifier_try.rb
416
+ - try/integration/transaction_safety_core_try.rb
417
+ - try/integration/transaction_safety_workflow_try.rb
389
418
  - try/integration/verifiable_identifier_try.rb
419
+ - try/investigation/pipeline_routing/README.md
390
420
  - try/performance/benchmarks_try.rb
421
+ - try/performance/transaction_safety_benchmark_try.rb
391
422
  - try/support/benchmarks/deserialization_benchmark.rb
392
423
  - try/support/benchmarks/deserialization_correctness_test.rb
393
424
  - try/support/debugging/README.md
@@ -437,6 +468,18 @@ files:
437
468
  - try/support/prototypes/pooling/lib/visualize_stress_results.rb
438
469
  - try/support/prototypes/pooling/pool_siege.rb
439
470
  - try/support/prototypes/pooling/run_stress_tests.rb
471
+ - try/thread_safety/README.md
472
+ - try/thread_safety/class_connection_chain_race_try.rb
473
+ - try/thread_safety/connection_chain_race_try.rb
474
+ - try/thread_safety/encryption_manager_cache_race_try.rb
475
+ - try/thread_safety/feature_registry_race_try.rb
476
+ - try/thread_safety/fiber_pipeline_isolation_try.rb
477
+ - try/thread_safety/fiber_transaction_isolation_try.rb
478
+ - try/thread_safety/field_registration_race_try.rb
479
+ - try/thread_safety/logger_initialization_race_try.rb
480
+ - try/thread_safety/middleware_registration_race_try.rb
481
+ - try/thread_safety/module_config_race_try.rb
482
+ - try/thread_safety/secure_identifier_cache_race_try.rb
440
483
  - try/unit/core/autoloader_try.rb
441
484
  - try/unit/core/base_enhancements_try.rb
442
485
  - try/unit/core/connection_try.rb
@@ -444,6 +487,9 @@ files:
444
487
  - try/unit/core/extensions_try.rb
445
488
  - try/unit/core/familia_logger_try.rb
446
489
  - try/unit/core/familia_try.rb
490
+ - try/unit/core/middleware_sampling_try.rb
491
+ - try/unit/core/middleware_test_helpers_bug_try.rb
492
+ - try/unit/core/middleware_thread_safety_try.rb
447
493
  - try/unit/core/middleware_try.rb
448
494
  - try/unit/core/settings_try.rb
449
495
  - try/unit/core/time_utils_try.rb
@@ -455,10 +501,12 @@ files:
455
501
  - try/unit/data_types/hash_try.rb
456
502
  - try/unit/data_types/list_try.rb
457
503
  - try/unit/data_types/lock_try.rb
504
+ - try/unit/data_types/serialization_try.rb
458
505
  - try/unit/data_types/sorted_set_try.rb
459
506
  - try/unit/data_types/sorted_set_zadd_options_try.rb
460
507
  - try/unit/data_types/string_try.rb
461
508
  - try/unit/data_types/unsortedset_try.rb
509
+ - try/unit/familia_resolve_class_try.rb
462
510
  - try/unit/horreum/auto_indexing_on_save_try.rb
463
511
  - try/unit/horreum/automatic_index_validation_try.rb
464
512
  - try/unit/horreum/base_try.rb
@@ -471,16 +519,20 @@ files:
471
519
  - try/unit/horreum/field_definition_try.rb
472
520
  - try/unit/horreum/initialization_try.rb
473
521
  - try/unit/horreum/json_type_preservation_try.rb
522
+ - try/unit/horreum/optimized_loading_try.rb
474
523
  - try/unit/horreum/relations_try.rb
475
524
  - try/unit/horreum/serialization_persistent_fields_try.rb
476
525
  - try/unit/horreum/serialization_try.rb
477
526
  - try/unit/horreum/settings_try.rb
478
527
  - try/unit/horreum/unique_index_edge_cases_try.rb
479
528
  - try/unit/horreum/unique_index_guard_validation_try.rb
529
+ - try/unit/middleware/database_command_counter_methods_try.rb
530
+ - try/unit/middleware/database_logger_methods_try.rb
480
531
  - try/unit/refinements/dear_json_array_methods_try.rb
481
532
  - try/unit/refinements/dear_json_hash_methods_try.rb
482
533
  - try/unit/refinements/time_literals_numeric_methods_try.rb
483
534
  - try/unit/refinements/time_literals_string_methods_try.rb
535
+ - try/unit/thread_safety_monitor_try.rb
484
536
  - try/valkey.conf
485
537
  homepage: https://github.com/delano/familia
486
538
  licenses:
@@ -494,14 +546,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
494
546
  requirements:
495
547
  - - ">="
496
548
  - !ruby/object:Gem::Version
497
- version: '3.4'
549
+ version: 3.3.6
498
550
  required_rubygems_version: !ruby/object:Gem::Requirement
499
551
  requirements:
500
552
  - - ">="
501
553
  - !ruby/object:Gem::Version
502
554
  version: '0'
503
555
  requirements: []
504
- rubygems_version: 3.6.9
556
+ rubygems_version: 3.7.2
505
557
  specification_version: 4
506
558
  summary: An ORM for Valkey-compatible databases in Ruby.
507
559
  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
- ..