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,245 @@
1
+ # try/unit/core/middleware_thread_safety_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
5
+ # Thread Safety Tests for DatabaseLogger Middleware
6
+ #
7
+ # These tests specifically target potential race conditions and concurrency issues
8
+ # in the DatabaseLogger middleware that could lead to nil entries in the @commands array.
9
+ #
10
+ # Covers:
11
+ # - Concurrent append_command operations
12
+ # - Thread-safe pipeline command logging
13
+ # - Mixed operation types under contention
14
+ # - Sampling counter atomicity
15
+ # - Rapid sequential calls within threads
16
+ # - clear_commands during active logging
17
+ #
18
+ # Background:
19
+ # An intermittent NoMethodError was observed where .command was called on nil
20
+ # during teardown of middleware_sampling_try.rb. The error suggests potential
21
+ # corruption of the @commands Concurrent::Array, possibly due to race conditions
22
+ # between append_command, clear_commands, or middleware state management.
23
+
24
+ require_relative '../../support/helpers/test_helpers'
25
+ require 'concurrent'
26
+
27
+ # Setup: Reset DatabaseLogger and ensure middleware is registered
28
+ Familia.connection_provider = nil
29
+ Familia.enable_database_logging = true
30
+ Familia.reconnect!
31
+ DatabaseLogger.clear_commands
32
+ DatabaseLogger.sample_rate = nil
33
+ DatabaseLogger.structured_logging = false
34
+
35
+ ## DatabaseLogger.append_command is thread-safe under concurrent access from 50 threads
36
+ # First verify middleware is working in main thread
37
+ DatabaseLogger.clear_commands
38
+ test_client = Familia.dbclient
39
+ test_client.set("setup_test", "value")
40
+ setup_commands = DatabaseLogger.commands.size
41
+
42
+ # Now run the actual test
43
+ DatabaseLogger.clear_commands
44
+ barrier = Concurrent::CyclicBarrier.new(50)
45
+ threads = []
46
+ dbclient = Familia.dbclient # Get connection in main thread (has middleware)
47
+
48
+ 50.times do |i|
49
+ threads << Thread.new do
50
+ barrier.wait # Synchronize start to maximize contention
51
+ dbclient.set("thread_key_#{i}", "value_#{i}")
52
+ end
53
+ end
54
+
55
+ threads.each(&:join)
56
+ commands = DatabaseLogger.commands
57
+
58
+ # All commands should be captured (no lost writes)
59
+ # No nil entries should exist in the commands array
60
+ # Note: setup_commands verifies middleware is working (should be 1)
61
+ [setup_commands, commands.size, commands.any?(nil), commands.all? { |cmd| cmd.respond_to?(:command) }]
62
+ #=> [1, 50, false, true]
63
+
64
+ ## Pipelined commands are thread-safe under concurrent access from 25 threads
65
+ DatabaseLogger.clear_commands
66
+ barrier = Concurrent::CyclicBarrier.new(25)
67
+ threads = []
68
+ dbclient = Familia.dbclient # Get connection in main thread (has middleware)
69
+
70
+ 25.times do |i|
71
+ threads << Thread.new do
72
+ barrier.wait
73
+ dbclient.pipelined do |pipeline|
74
+ pipeline.set("pipeline_thread_#{i}_key1", "val1")
75
+ pipeline.set("pipeline_thread_#{i}_key2", "val2")
76
+ end
77
+ end
78
+ end
79
+
80
+ threads.each(&:join)
81
+ commands = DatabaseLogger.commands
82
+
83
+ # Each thread creates one pipeline command (25 total)
84
+ # Verify no nil entries and all are proper CommandMessage objects
85
+ [commands.size, commands.any?(nil), commands.all? { |cmd| cmd.respond_to?(:command) }]
86
+ #=> [25, false, true]
87
+
88
+ ## Mixed middleware operations (call, call_pipelined, call_once) are thread-safe
89
+ DatabaseLogger.clear_commands
90
+ barrier = Concurrent::CyclicBarrier.new(60)
91
+ threads = []
92
+ dbclient = Familia.dbclient # Get connection in main thread (has middleware)
93
+
94
+ 60.times do |i|
95
+ threads << Thread.new do
96
+ barrier.wait
97
+
98
+ case i % 3
99
+ when 0 # Regular call
100
+ dbclient.set("mixed_#{i}", "val")
101
+ when 1 # Pipelined
102
+ dbclient.pipelined { |p| p.get("mixed_#{i}") }
103
+ when 2 # Multiple rapid calls
104
+ 3.times { dbclient.get("mixed_#{i}") }
105
+ end
106
+ end
107
+ end
108
+
109
+ threads.each(&:join)
110
+ commands = DatabaseLogger.commands
111
+
112
+ # Verify no nil entries regardless of operation type
113
+ # All entries should be valid CommandMessage instances
114
+ [commands.any?(nil), commands.all? { |cmd| cmd.is_a?(DatabaseLogger::CommandMessage) }]
115
+ #=> [false, true]
116
+
117
+ ## sample_rate counter is thread-safe with 100 concurrent operations
118
+ # REMOVED: This test had incorrect expectations. The sample_rate controls LOGGING
119
+ # output, not COMMAND CAPTURE. Per database_logger.rb:153-154:
120
+ # "Command capture is unaffected - only logger output is sampled."
121
+ # The commands array always contains all commands regardless of sample_rate.
122
+ # Thread safety of the AtomicFixnum counter is verified by other tests.
123
+
124
+ ## Rapid sequential calls within threads don't corrupt shared state
125
+ DatabaseLogger.clear_commands
126
+ DatabaseLogger.sample_rate = nil # Log everything
127
+ latch = Concurrent::CountDownLatch.new(20)
128
+ threads = []
129
+ dbclient = Familia.dbclient # Get connection in main thread (has middleware)
130
+
131
+ 20.times do |i|
132
+ threads << Thread.new do
133
+ # Rapid-fire 10 operations per thread to test state isolation
134
+ 10.times do |j|
135
+ dbclient.set("rapid_#{i}_#{j}", "val")
136
+ end
137
+ latch.count_down
138
+ end
139
+ end
140
+
141
+ latch.wait(5) # 5 second timeout
142
+ commands = DatabaseLogger.commands
143
+
144
+ # Should have 200 commands (20 threads × 10 calls)
145
+ # Most importantly: NO nil entries from rapid sequential access
146
+ [commands.size, commands.any?(nil)]
147
+ #=> [200, false]
148
+
149
+ ## clear_commands doesn't cause nil entries during concurrent logging
150
+ DatabaseLogger.clear_commands
151
+ DatabaseLogger.sample_rate = nil
152
+ barrier = Concurrent::CyclicBarrier.new(51) # 50 loggers + 1 clearer
153
+ threads = []
154
+ dbclient = Familia.dbclient # Get connection in main thread (has middleware)
155
+
156
+ # 50 threads logging continuously
157
+ 50.times do |i|
158
+ threads << Thread.new do
159
+ barrier.wait
160
+ 10.times do |j|
161
+ dbclient.set("clear_test_#{i}_#{j}", "val")
162
+ end
163
+ end
164
+ end
165
+
166
+ # 1 thread clearing repeatedly to create contention
167
+ clearer = Thread.new do
168
+ barrier.wait
169
+ 5.times do
170
+ sleep 0.001 # Small delay between clears
171
+ DatabaseLogger.clear_commands
172
+ end
173
+ end
174
+
175
+ threads.each(&:join)
176
+ clearer.join
177
+
178
+ # After clearing, commands should be empty or valid (never contain nil)
179
+ # This tests whether clear_commands can corrupt the array during active logging
180
+ commands = DatabaseLogger.commands
181
+ [commands.any?(nil)]
182
+ #=> [false]
183
+
184
+ ## CommandMessage structure is preserved under concurrent access
185
+ DatabaseLogger.clear_commands
186
+ barrier = Concurrent::CyclicBarrier.new(30)
187
+ threads = []
188
+ dbclient = Familia.dbclient # Get connection in main thread (has middleware)
189
+
190
+ 30.times do |i|
191
+ threads << Thread.new do
192
+ barrier.wait
193
+ dbclient.set("structure_test_#{i}", "value_#{i}")
194
+ end
195
+ end
196
+
197
+ threads.each(&:join)
198
+ commands = DatabaseLogger.commands
199
+
200
+ # Verify all CommandMessage fields are properly initialized
201
+ # This ensures the Data.define structure isn't corrupted by concurrency
202
+ all_valid = commands.all? do |cmd|
203
+ cmd.command.is_a?(String) &&
204
+ cmd.μs.is_a?(Integer) &&
205
+ cmd.timeline.is_a?(Float)
206
+ end
207
+
208
+ [commands.size, commands.any?(nil), all_valid]
209
+ #=> [30, false, true]
210
+
211
+ ## Concurrent pipelined operations with varying sizes don't cause corruption
212
+ # REMOVED: This test was checking exact pipeline command count which can vary
213
+ # due to intentionally non-atomic append_command trimming logic.
214
+ # See database_logger.rb:214-217 - we don't care about exact count when trimming.
215
+ # The important invariants (no nil entries, successful operations) are tested elsewhere.
216
+
217
+ ## AtomicFixnum counter increments correctly under high contention
218
+ DatabaseLogger.clear_commands
219
+ DatabaseLogger.sample_rate = 1.0 # Track every increment but log everything
220
+ counter_start = DatabaseLogger.instance_variable_get(:@sample_counter).value
221
+
222
+ barrier = Concurrent::CyclicBarrier.new(100)
223
+ threads = []
224
+ dbclient = Familia.dbclient # Get connection in main thread (has middleware)
225
+
226
+ 100.times do |i|
227
+ threads << Thread.new do
228
+ barrier.wait
229
+ dbclient.set("counter_test_#{i}", "val")
230
+ end
231
+ end
232
+
233
+ threads.each(&:join)
234
+ counter_end = DatabaseLogger.instance_variable_get(:@sample_counter).value
235
+ commands = DatabaseLogger.commands
236
+
237
+ # Counter should have incremented by exactly 100
238
+ # Commands should have all 100 entries with no nil values
239
+ [counter_end - counter_start, commands.size, commands.any?(nil)]
240
+ #=> [100, 100, false]
241
+
242
+ # Teardown: Reset to defaults
243
+ DatabaseLogger.sample_rate = nil
244
+ DatabaseLogger.structured_logging = false
245
+ DatabaseLogger.clear_commands
@@ -1,3 +1,7 @@
1
+ # try/unit/core/middleware_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/core/middleware_try.rb
2
6
 
3
7
  # Test Valkey/Redis middleware components
@@ -1,3 +1,7 @@
1
+ # try/unit/core/settings_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/core/settings_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/core/time_utils_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  require_relative '../../support/helpers/test_helpers'
2
6
 
3
7
  module RefinedContext
@@ -1,3 +1,7 @@
1
+ # try/unit/core/tools_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/core/tools_try.rb
2
6
 
3
7
  # Test Familia::Tools - key migration and utility functions
@@ -1,3 +1,7 @@
1
+ # try/unit/core/utils_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/core/utils_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -85,6 +89,39 @@ rescue Familia::NotDistinguishableError => e
85
89
  end
86
90
  #=> Familia::NotDistinguishableError
87
91
 
92
+ ##
93
+ ## Time utilities
94
+ ##
95
+
96
+ ## now returns Float timestamp in seconds
97
+ time_result = Familia.now
98
+ [time_result.is_a?(Float), time_result > 0]
99
+ #=> [true, true]
100
+
101
+ ## now accepts Time argument
102
+ test_time = Time.utc(2023, 6, 15, 14, 30, 0)
103
+ result_time = Familia.now(test_time)
104
+ [result_time.is_a?(Float), result_time == test_time.utc.to_f]
105
+ #=> [true, true]
106
+
107
+ ## now_in_μs returns Integer microseconds
108
+ μs_result = Familia.now_in_μs
109
+ [μs_result.is_a?(Integer), μs_result > 0]
110
+ #=> [true, true]
111
+
112
+ ## now_in_microseconds is an alias for now_in_μs
113
+ alias_result = Familia.now_in_microseconds
114
+ [alias_result.is_a?(Integer), alias_result > 0]
115
+ #=> [true, true]
116
+
117
+ ## now_in_μs returns monotonic time suitable for duration measurement
118
+ start = Familia.now_in_μs
119
+ sleep 0.001 # Sleep for at least 1ms
120
+ finish = Familia.now_in_μs
121
+ duration = finish - start
122
+ [duration.is_a?(Integer), duration >= 1000] # At least 1000 microseconds (1ms)
123
+ #=> [true, true]
124
+
88
125
  # Cleanup - restore defaults, leave nothing but footprints
89
126
  Familia.delim(':')
90
127
  Familia.suffix(:object)
@@ -1,3 +1,7 @@
1
+ # try/unit/data_types/boolean_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/data_types/boolean_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/data_types/counter_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/data_types/counter_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/data_types/datatype_base_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/data_types/base_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/data_types/hash_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/data_types/hash_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/data_types/list_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/data_types/list_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/data_types/lock_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/data_types/lock_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/data_types/sorted_set_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/data_types/sorted_set_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/data_types/sorted_set_zadd_options_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/features/data_type/sorted_set_zadd_options_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/data_types/string_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/data_types/string_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/data_types/unsortedset_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/data_types/unsortedset_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -0,0 +1,116 @@
1
+ # try/unit/familia_resolve_class_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
5
+ # Unit tests for Familia.resolve_class method
6
+ #
7
+ # This test ensures the public API for resolving class references works
8
+ # correctly across different input types (Class, Symbol, String).
9
+ #
10
+ # Related to the fix for NoMethodError in participates_in where the private
11
+ # method member_by_config_name was being called directly instead of using
12
+ # the public resolve_class API.
13
+
14
+ require_relative '../support/helpers/test_helpers'
15
+
16
+ # Test class for resolution
17
+ class ResolveTestClass < Familia::Horreum
18
+ identifier_field :id
19
+ field :id
20
+ field :name
21
+ end
22
+
23
+ # Test class in module for modularized class resolution
24
+ module ResolveTestModule
25
+ class ModularClass < Familia::Horreum
26
+ identifier_field :id
27
+ field :id
28
+ end
29
+ end
30
+
31
+ ## Test resolve_class with Class object returns the class unchanged
32
+ @resolved_class = Familia.resolve_class(ResolveTestClass)
33
+ @resolved_class == ResolveTestClass
34
+ #=> true
35
+
36
+ ## Test resolve_class with Symbol returns the correct class
37
+ @resolved_symbol = Familia.resolve_class(:ResolveTestClass)
38
+ @resolved_symbol == ResolveTestClass
39
+ #=> true
40
+
41
+ ## Test resolve_class with String returns the correct class
42
+ @resolved_string = Familia.resolve_class('ResolveTestClass')
43
+ @resolved_string == ResolveTestClass
44
+ #=> true
45
+
46
+ ## Test resolve_class with PascalCase symbol works
47
+ @resolved_pascal_sym = Familia.resolve_class(:ResolveTestClass)
48
+ @resolved_pascal_sym == ResolveTestClass
49
+ #=> true
50
+
51
+ ## Test resolve_class with PascalCase string works
52
+ @resolved_pascal_str = Familia.resolve_class('ResolveTestClass')
53
+ @resolved_pascal_str == ResolveTestClass
54
+ #=> true
55
+
56
+ ## Test resolve_class with snake_case symbol works
57
+ @resolved_snake = Familia.resolve_class(:resolve_test_class)
58
+ @resolved_snake == ResolveTestClass
59
+ #=> true
60
+
61
+ ## Test resolve_class with snake_case string works
62
+ @resolved_snake_str = Familia.resolve_class('resolve_test_class')
63
+ @resolved_snake_str == ResolveTestClass
64
+ #=> true
65
+
66
+ ## Test resolve_class raises ArgumentError for invalid types
67
+ begin
68
+ Familia.resolve_class(123)
69
+ @raised = false
70
+ rescue ArgumentError => e
71
+ @raised = true
72
+ @error_message = e.message
73
+ end
74
+ @raised
75
+ #=> true
76
+
77
+ ## Test error message is descriptive
78
+ @error_message.include?('Expected Class, String, or Symbol')
79
+ #=> true
80
+
81
+ ## Test resolve_class returns nil for non-existent class
82
+ @nonexistent = Familia.resolve_class(:NonExistentClass)
83
+ @nonexistent.nil?
84
+ #=> true
85
+
86
+ ## Test resolve_class with variations of proper naming
87
+ # Note: All-caps or all-lowercase don't work because snake_case needs case boundaries
88
+ # Realistic usage: PascalCase, snake_case, or mixed-case with boundaries
89
+ @case_variant_snake = Familia.resolve_class('resolve_test_class')
90
+ @case_variant_snake == ResolveTestClass
91
+ #=> true
92
+
93
+ ## Test resolve_class handles already snake_cased symbols
94
+ @already_snake = Familia.resolve_class(:resolve_test_class)
95
+ @already_snake == ResolveTestClass
96
+ #=> true
97
+
98
+ ## Test resolve_class with modularized Symbol (without module prefix)
99
+ @modular_resolved = Familia.resolve_class(:ModularClass)
100
+ @modular_resolved == ResolveTestModule::ModularClass
101
+ #=> true
102
+
103
+ ## Test resolve_class with modularized String (without module prefix)
104
+ @modular_resolved_str = Familia.resolve_class('ModularClass')
105
+ @modular_resolved_str == ResolveTestModule::ModularClass
106
+ #=> true
107
+
108
+ ## Test resolve_class with snake_case modularized Symbol
109
+ @modular_snake = Familia.resolve_class(:modular_class)
110
+ @modular_snake == ResolveTestModule::ModularClass
111
+ #=> true
112
+
113
+ ## Test resolve_class with Class object for modularized class
114
+ @modular_class_obj = Familia.resolve_class(ResolveTestModule::ModularClass)
115
+ @modular_class_obj == ResolveTestModule::ModularClass
116
+ #=> true
@@ -1,3 +1,7 @@
1
+ # try/unit/horreum/auto_indexing_on_save_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/horreum/auto_indexing_on_save_try.rb
2
6
 
3
7
  #
@@ -182,7 +186,7 @@ AutoIndexWithTransient.find_by_email(@transient_email)&.id
182
186
  begin
183
187
  @transient_dup.save
184
188
  rescue Familia::RecordExistsError => ex
185
- Familia.ld ex.backtrace.join("\n")
189
+ Familia.debug ex.backtrace.join("\n")
186
190
  ex.message
187
191
  end
188
192
  #=:> String
@@ -1,4 +1,6 @@
1
1
  # try/unit/horreum/automatic_index_validation_try.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  #
4
6
  # Automatic index validation tests
@@ -1,3 +1,7 @@
1
+ # try/unit/horreum/base_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/horreum/base_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/horreum/class_methods_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/horreum/class_methods_try.rb
2
6
 
3
7
  # Test Horreum class methods
@@ -1,3 +1,7 @@
1
+ # try/unit/horreum/commands_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/horreum/commands_try.rb
2
6
 
3
7
  # Test Horreum Valkey/Redis commands
@@ -1,3 +1,7 @@
1
+ # try/unit/horreum/defensive_initialization_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/horreum/defensive_initialization_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/horreum/destroy_related_fields_cleanup_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/horreum/destroy_related_fields_cleanup_try.rb
2
6
 
3
7
  # Horreum destroy! Related Fields Cleanup Tryouts
@@ -1,3 +1,7 @@
1
+ # try/unit/horreum/enhanced_conflict_handling_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/horreum/enhanced_conflict_handling_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/horreum/field_categories_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/horreum/field_categories_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/horreum/field_definition_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/horreum/field_definition_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,7 @@
1
+ # try/unit/horreum/initialization_try.rb
2
+ #
3
+ # frozen_string_literal: true
4
+
1
5
  # try/horreum/initialization_try.rb
2
6
 
3
7
  require_relative '../../support/helpers/test_helpers'
@@ -1,3 +1,5 @@
1
+ # try/unit/horreum/json_type_preservation_try.rb
2
+ #
1
3
  # frozen_string_literal: true
2
4
 
3
5
  require_relative '../../support/helpers/test_helpers'