familia 2.0.0.pre17 → 2.0.0.pre18
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.
- checksums.yaml +4 -4
- data/CHANGELOG.rst +60 -0
- data/CLAUDE.md +9 -2
- data/Gemfile.lock +1 -1
- data/README.md +13 -0
- data/bin/irb +1 -1
- data/docs/guides/core-field-system.md +48 -26
- data/docs/migrating/v2.0.0-pre18.md +58 -0
- data/docs/qodo-merge-compliance.md +96 -0
- data/lib/familia/base.rb +0 -2
- data/lib/familia/connection/middleware.rb +58 -4
- data/lib/familia/connection.rb +1 -1
- data/lib/familia/data_type/{commands.rb → database_commands.rb} +2 -2
- data/lib/familia/data_type/serialization.rb +5 -5
- data/lib/familia/data_type.rb +2 -2
- data/lib/familia/encryption/encrypted_data.rb +12 -2
- data/lib/familia/encryption/manager.rb +11 -4
- data/lib/familia/features/autoloader.rb +3 -1
- data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +11 -3
- data/lib/familia/features/relationships/indexing/multi_index_generators.rb +9 -9
- data/lib/familia/features/relationships/indexing/unique_index_generators.rb +41 -27
- data/lib/familia/features/safe_dump.rb +2 -3
- data/lib/familia/horreum/database_commands.rb +1 -1
- data/lib/familia/horreum/definition.rb +6 -37
- data/lib/familia/horreum/management.rb +17 -12
- data/lib/familia/horreum/persistence.rb +1 -1
- data/lib/familia/horreum/serialization.rb +91 -73
- data/lib/familia/horreum.rb +10 -6
- data/lib/familia/identifier_extractor.rb +60 -0
- data/lib/familia/logging.rb +271 -112
- data/lib/familia/refinements.rb +0 -1
- data/lib/familia/version.rb +1 -1
- data/lib/familia.rb +2 -2
- data/lib/middleware/{database_middleware.rb → database_logger.rb} +47 -14
- data/pr_agent.toml +31 -0
- data/pr_compliance_checklist.yaml +45 -0
- data/try/edge_cases/empty_identifiers_try.rb +1 -1
- data/try/edge_cases/hash_symbolization_try.rb +31 -31
- data/try/edge_cases/json_serialization_try.rb +2 -2
- data/try/edge_cases/legacy_data_detection/deserialization_edge_cases_try.rb +170 -0
- data/try/edge_cases/race_conditions_try.rb +1 -1
- data/try/edge_cases/reserved_keywords_try.rb +1 -1
- data/try/edge_cases/string_coercion_try.rb +1 -1
- data/try/edge_cases/ttl_side_effects_try.rb +1 -1
- data/try/features/encrypted_fields/aad_protection_try.rb +1 -1
- data/try/features/encrypted_fields/concealed_string_core_try.rb +1 -1
- data/try/features/encrypted_fields/context_isolation_try.rb +1 -1
- data/try/features/encrypted_fields/encrypted_fields_core_try.rb +1 -1
- data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +1 -1
- data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +1 -1
- data/try/features/encrypted_fields/encrypted_fields_security_try.rb +1 -1
- data/try/features/encrypted_fields/error_conditions_try.rb +1 -1
- data/try/features/encrypted_fields/fresh_key_derivation_try.rb +1 -1
- data/try/features/encrypted_fields/fresh_key_try.rb +1 -1
- data/try/features/encrypted_fields/key_rotation_try.rb +1 -1
- data/try/features/encrypted_fields/memory_security_try.rb +1 -1
- data/try/features/encrypted_fields/missing_current_key_version_try.rb +1 -1
- data/try/features/encrypted_fields/nonce_uniqueness_try.rb +1 -1
- data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +1 -1
- data/try/features/encrypted_fields/thread_safety_try.rb +1 -1
- data/try/features/encrypted_fields/universal_serialization_safety_try.rb +1 -1
- data/try/{encryption → features/encryption}/config_persistence_try.rb +1 -1
- data/try/{encryption/encryption_core_try.rb → features/encryption/core_try.rb} +2 -2
- data/try/{encryption → features/encryption}/instance_variable_scope_try.rb +1 -1
- data/try/{encryption → features/encryption}/module_loading_try.rb +1 -1
- data/try/{encryption → features/encryption}/providers/aes_gcm_provider_try.rb +1 -1
- data/try/{encryption → features/encryption}/providers/xchacha20_poly1305_provider_try.rb +1 -1
- data/try/{encryption → features/encryption}/roundtrip_validation_try.rb +1 -1
- data/try/{encryption → features/encryption}/secure_memory_handling_try.rb +2 -2
- data/try/features/expiration/expiration_try.rb +1 -1
- data/try/features/external_identifier/external_identifier_try.rb +1 -1
- data/try/features/feature_dependencies_try.rb +1 -1
- data/try/features/feature_improvements_try.rb +1 -1
- data/try/features/object_identifier/object_identifier_integration_try.rb +1 -1
- data/try/features/object_identifier/object_identifier_try.rb +1 -1
- data/try/features/quantization/quantization_try.rb +1 -1
- data/try/features/real_feature_integration_try.rb +17 -14
- data/try/features/relationships/indexing_commands_verification_try.rb +8 -3
- data/try/features/relationships/indexing_try.rb +6 -1
- data/try/features/relationships/participation_commands_verification_spec.rb +1 -1
- data/try/features/relationships/participation_commands_verification_try.rb +4 -4
- data/try/features/relationships/participation_performance_improvements_try.rb +1 -1
- data/try/features/relationships/participation_reverse_index_try.rb +1 -1
- data/try/features/relationships/relationships_api_changes_try.rb +1 -1
- data/try/features/relationships/relationships_edge_cases_try.rb +3 -3
- data/try/features/relationships/relationships_performance_minimal_try.rb +1 -1
- data/try/features/relationships/relationships_performance_simple_try.rb +1 -1
- data/try/features/relationships/relationships_performance_try.rb +1 -1
- data/try/features/relationships/relationships_performance_working_try.rb +1 -1
- data/try/features/relationships/relationships_try.rb +1 -1
- data/try/features/safe_dump/safe_dump_advanced_try.rb +1 -1
- data/try/features/safe_dump/safe_dump_try.rb +1 -1
- data/try/features/transient_fields/redacted_string_try.rb +1 -1
- data/try/features/transient_fields/refresh_reset_try.rb +1 -1
- data/try/features/transient_fields/single_use_redacted_string_try.rb +1 -1
- data/try/features/transient_fields/transient_fields_core_try.rb +1 -1
- data/try/features/transient_fields/transient_fields_integration_try.rb +1 -1
- data/try/{connection → integration/connection}/fiber_context_preservation_try.rb +1 -1
- data/try/{connection → integration/connection}/handler_constraints_try.rb +1 -1
- data/try/{core → integration/connection}/isolated_dbclient_try.rb +1 -1
- data/try/integration/connection/middleware_reconnect_try.rb +87 -0
- data/try/{connection → integration/connection}/operation_mode_guards_try.rb +1 -1
- data/try/{connection → integration/connection}/pipeline_fallback_integration_try.rb +1 -1
- data/try/{core → integration/connection}/pools_try.rb +1 -1
- data/try/{connection → integration/connection}/responsibility_chain_tracking_try.rb +1 -1
- data/try/{connection → integration/connection}/transaction_fallback_integration_try.rb +1 -1
- data/try/{connection → integration/connection}/transaction_mode_permissive_try.rb +1 -1
- data/try/{connection → integration/connection}/transaction_mode_strict_try.rb +1 -1
- data/try/{connection → integration/connection}/transaction_mode_warn_try.rb +1 -1
- data/try/{connection → integration/connection}/transaction_modes_try.rb +1 -1
- data/try/{core → integration}/conventional_inheritance_try.rb +1 -1
- data/try/{core → integration}/create_method_try.rb +1 -1
- data/try/integration/cross_component_try.rb +1 -1
- data/try/{core → integration}/database_consistency_try.rb +11 -8
- data/try/{core → integration}/familia_extended_try.rb +1 -1
- data/try/{core → integration}/familia_members_methods_try.rb +1 -1
- data/try/{models → integration/models}/customer_safe_dump_try.rb +1 -1
- data/try/{models → integration/models}/customer_try.rb +1 -1
- data/try/{models → integration/models}/datatype_base_try.rb +1 -1
- data/try/{models → integration/models}/familia_object_try.rb +1 -1
- data/try/{core → integration}/persistence_operations_try.rb +1 -1
- data/try/integration/relationships_persistence_round_trip_try.rb +441 -0
- data/try/{configuration → integration}/scenarios_try.rb +1 -1
- data/try/{core → integration}/secure_identifier_try.rb +1 -1
- data/try/{core → integration}/verifiable_identifier_try.rb +1 -1
- data/try/performance/benchmarks_try.rb +2 -2
- data/try/support/benchmarks/deserialization_benchmark.rb +180 -0
- data/try/support/benchmarks/deserialization_correctness_test.rb +237 -0
- data/try/{helpers → support/helpers}/test_helpers.rb +12 -3
- data/try/{core → unit/core}/autoloader_try.rb +1 -1
- data/try/{core → unit/core}/base_enhancements_try.rb +1 -9
- data/try/{core → unit/core}/connection_try.rb +1 -1
- data/try/{core → unit/core}/errors_try.rb +1 -1
- data/try/{core → unit/core}/extensions_try.rb +1 -1
- data/try/unit/core/familia_logger_try.rb +110 -0
- data/try/{core → unit/core}/familia_try.rb +1 -1
- data/try/{core → unit/core}/middleware_try.rb +41 -1
- data/try/{core → unit/core}/settings_try.rb +1 -1
- data/try/{core → unit/core}/time_utils_try.rb +1 -1
- data/try/{core → unit/core}/tools_try.rb +1 -1
- data/try/{core → unit/core}/utils_try.rb +17 -14
- data/try/{data_types → unit/data_types}/boolean_try.rb +1 -1
- data/try/{data_types → unit/data_types}/counter_try.rb +1 -1
- data/try/{data_types → unit/data_types}/datatype_base_try.rb +1 -1
- data/try/{data_types → unit/data_types}/hash_try.rb +1 -1
- data/try/{data_types → unit/data_types}/list_try.rb +1 -1
- data/try/{data_types → unit/data_types}/lock_try.rb +1 -1
- data/try/{data_types → unit/data_types}/sorted_set_try.rb +1 -1
- data/try/{data_types → unit/data_types}/sorted_set_zadd_options_try.rb +1 -1
- data/try/{data_types → unit/data_types}/string_try.rb +1 -1
- data/try/{data_types → unit/data_types}/unsortedset_try.rb +1 -1
- data/try/{horreum → unit/horreum}/auto_indexing_on_save_try.rb +1 -1
- data/try/{horreum → unit/horreum}/base_try.rb +3 -3
- data/try/{horreum → unit/horreum}/class_methods_try.rb +1 -1
- data/try/{horreum → unit/horreum}/commands_try.rb +1 -1
- data/try/{horreum → unit/horreum}/defensive_initialization_try.rb +1 -1
- data/try/{horreum → unit/horreum}/destroy_related_fields_cleanup_try.rb +1 -1
- data/try/{horreum → unit/horreum}/enhanced_conflict_handling_try.rb +1 -1
- data/try/{horreum → unit/horreum}/field_categories_try.rb +27 -18
- data/try/{horreum → unit/horreum}/field_definition_try.rb +1 -1
- data/try/{horreum → unit/horreum}/initialization_try.rb +2 -2
- data/try/unit/horreum/json_type_preservation_try.rb +248 -0
- data/try/{horreum → unit/horreum}/relations_try.rb +1 -1
- data/try/{horreum → unit/horreum}/serialization_persistent_fields_try.rb +24 -18
- data/try/{horreum → unit/horreum}/serialization_try.rb +4 -4
- data/try/{horreum → unit/horreum}/settings_try.rb +1 -1
- data/try/{refinements → unit/refinements}/dear_json_array_methods_try.rb +1 -1
- data/try/{refinements → unit/refinements}/dear_json_hash_methods_try.rb +1 -1
- data/try/{refinements → unit/refinements}/time_literals_numeric_methods_try.rb +1 -1
- data/try/{refinements → unit/refinements}/time_literals_string_methods_try.rb +1 -1
- metadata +134 -125
- data/lib/familia/distinguisher.rb +0 -85
- data/lib/familia/refinements/logger_trace.rb +0 -60
- data/try/refinements/logger_trace_methods_try.rb +0 -44
- /data/try/{debugging → support/debugging}/README.md +0 -0
- /data/try/{debugging → support/debugging}/cache_behavior_tracer.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_aad_process.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_concealed_internal.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_concealed_reveal.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_context_aad.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_context_simple.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_cross_context.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_database_load.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_encrypted_json_check.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_encrypted_json_step_by_step.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_exists_lifecycle.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_field_decrypt.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_fresh_cross_context.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_load_path.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_method_definition.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_method_resolution.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_minimal.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_provider.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_secure_behavior.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_string_class.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_test.rb +0 -0
- /data/try/{debugging → support/debugging}/debug_test_design.rb +0 -0
- /data/try/{debugging → support/debugging}/encryption_method_tracer.rb +0 -0
- /data/try/{debugging → support/debugging}/provider_diagnostics.rb +0 -0
- /data/try/{helpers → support/helpers}/test_cleanup.rb +0 -0
- /data/try/{memory → support/memory}/memory_basic_test.rb +0 -0
- /data/try/{memory → support/memory}/memory_detailed_test.rb +0 -0
- /data/try/{memory → support/memory}/memory_docker_ruby_dump.sh +0 -0
- /data/try/{memory → support/memory}/memory_search_for_string.rb +0 -0
- /data/try/{memory → support/memory}/test_actual_redactedstring_protection.rb +0 -0
- /data/try/{prototypes → support/prototypes}/atomic_saves_v1_context_proxy.rb +0 -0
- /data/try/{prototypes → support/prototypes}/atomic_saves_v2_connection_switching.rb +0 -0
- /data/try/{prototypes → support/prototypes}/atomic_saves_v3_connection_pool.rb +0 -0
- /data/try/{prototypes → support/prototypes}/atomic_saves_v4.rb +0 -0
- /data/try/{prototypes → support/prototypes}/lib/atomic_saves_v2_connection_switching_helpers.rb +0 -0
- /data/try/{prototypes → support/prototypes}/lib/atomic_saves_v3_connection_pool_helpers.rb +0 -0
- /data/try/{prototypes → support/prototypes}/pooling/README.md +0 -0
- /data/try/{prototypes → support/prototypes}/pooling/configurable_stress_test.rb +0 -0
- /data/try/{prototypes → support/prototypes}/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +0 -0
- /data/try/{prototypes → support/prototypes}/pooling/lib/connection_pool_metrics.rb +0 -0
- /data/try/{prototypes → support/prototypes}/pooling/lib/connection_pool_stress_test.rb +0 -0
- /data/try/{prototypes → support/prototypes}/pooling/lib/connection_pool_threading_models.rb +0 -0
- /data/try/{prototypes → support/prototypes}/pooling/lib/visualize_stress_results.rb +0 -0
- /data/try/{prototypes → support/prototypes}/pooling/pool_siege.rb +0 -0
- /data/try/{prototypes → support/prototypes}/pooling/run_stress_tests.rb +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
# try/features/real_feature_integration_try.rb
|
2
2
|
|
3
|
-
require_relative '../helpers/test_helpers'
|
3
|
+
require_relative '../support/helpers/test_helpers'
|
4
4
|
|
5
5
|
Familia.debug = false
|
6
6
|
|
@@ -12,15 +12,17 @@ class ExpirationIntegrationTest < Familia::Horreum
|
|
12
12
|
feature :expiration
|
13
13
|
end
|
14
14
|
|
15
|
-
# Safe dump feature integration with field
|
15
|
+
# Safe dump feature integration with field types
|
16
16
|
class SafeDumpCategoryTest < Familia::Horreum
|
17
|
+
feature :encrypted_fields
|
18
|
+
feature :transient_fields
|
19
|
+
feature :safe_dump
|
20
|
+
|
17
21
|
identifier_field :id
|
18
22
|
field :id
|
19
|
-
field :public_name
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
feature :safe_dump
|
23
|
+
field :public_name
|
24
|
+
encrypted_field :email
|
25
|
+
transient_field :tryouts_cache_data
|
24
26
|
|
25
27
|
# Use new SafeDump DSL
|
26
28
|
safe_dump_field :id
|
@@ -30,14 +32,15 @@ end
|
|
30
32
|
|
31
33
|
# Combined features work together
|
32
34
|
class CombinedFeaturesTest < Familia::Horreum
|
33
|
-
|
34
|
-
field :id
|
35
|
-
field :name, category: :persistent
|
36
|
-
field :temp_data, category: :transient
|
37
|
-
|
35
|
+
feature :transient_fields
|
38
36
|
feature :expiration
|
39
37
|
feature :safe_dump
|
40
38
|
|
39
|
+
identifier_field :id
|
40
|
+
field :id
|
41
|
+
field :name
|
42
|
+
transient_field :temp_data
|
43
|
+
|
41
44
|
# Use new SafeDump DSL
|
42
45
|
safe_dump_field :id
|
43
46
|
safe_dump_field :name
|
@@ -123,11 +126,11 @@ CombinedFeaturesTest.features_enabled.include?(:safe_dump)
|
|
123
126
|
|
124
127
|
## Test that feature() method returns current features when called with no args
|
125
128
|
CombinedFeaturesTest.feature
|
126
|
-
#=> [:expiration, :safe_dump]
|
129
|
+
#=> [:transient_fields, :expiration, :safe_dump]
|
127
130
|
|
128
131
|
## Test that features_enabled() method returns the same results as feature() method
|
129
132
|
CombinedFeaturesTest.feature
|
130
|
-
#=> [:expiration, :safe_dump]
|
133
|
+
#=> [:transient_fields, :expiration, :safe_dump]
|
131
134
|
|
132
135
|
## Features list is accessible
|
133
136
|
QueryFeaturesTest.feature
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This test ensures the indexing system uses proper DataType methods instead of direct Redis calls
|
5
5
|
#
|
6
6
|
|
7
|
-
require_relative '../../helpers/test_helpers'
|
7
|
+
require_relative '../../support/helpers/test_helpers'
|
8
8
|
|
9
9
|
# Enable database command logging for command verification tests
|
10
10
|
Familia.enable_database_logging = true
|
@@ -44,8 +44,11 @@ end
|
|
44
44
|
|
45
45
|
# Test data
|
46
46
|
@user = TestIndexedUser.new(user_id: 'test_user_123', email: 'test@example.com', department: 'engineering')
|
47
|
+
@user.save
|
47
48
|
@company = TestIndexedCompany.new(company_id: 'test_company_456', name: 'Test Corp')
|
49
|
+
@company.save
|
48
50
|
@employee = TestIndexedEmployee.new(emp_id: 'test_emp_789', email: 'emp@example.com', department: 'sales')
|
51
|
+
@employee.save
|
49
52
|
|
50
53
|
## Class-level indexing creates proper DataType field
|
51
54
|
TestIndexedUser.respond_to?(:email_index)
|
@@ -91,6 +94,7 @@ end
|
|
91
94
|
#=> false
|
92
95
|
|
93
96
|
## Instance-level indexing works with parent context
|
97
|
+
@employee.save
|
94
98
|
@employee.add_to_test_indexed_company_dept_index(@company)
|
95
99
|
sample = @company.sample_from_department('sales')
|
96
100
|
sample.first&.emp_id == @employee.emp_id
|
@@ -103,15 +107,16 @@ dept_index.class.name
|
|
103
107
|
|
104
108
|
## Multiple employees in same department
|
105
109
|
@employee2 = TestIndexedEmployee.new(emp_id: 'test_emp_999', email: 'emp2@example.com', department: 'sales')
|
110
|
+
@employee2.save
|
106
111
|
@employee2.add_to_test_indexed_company_dept_index(@company)
|
107
112
|
employees_in_sales = @company.find_all_by_department('sales')
|
108
|
-
employees_in_sales
|
113
|
+
employees_in_sales&.map(&:emp_id).sort
|
109
114
|
#=> ["test_emp_789", "test_emp_999"]
|
110
115
|
|
111
116
|
## Removing from instance-level index works
|
112
117
|
@employee.remove_from_test_indexed_company_dept_index(@company)
|
113
118
|
remaining_employees = @company.find_all_by_department('sales')
|
114
|
-
remaining_employees
|
119
|
+
remaining_employees&.map(&:emp_id)
|
115
120
|
#=> ["test_emp_999"]
|
116
121
|
|
117
122
|
## Index update methods work correctly
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# Tests both multi_index (parent-context) and unique_index (class-level) indexing
|
5
5
|
#
|
6
6
|
|
7
|
-
require_relative '../../helpers/test_helpers'
|
7
|
+
require_relative '../../support/helpers/test_helpers'
|
8
8
|
|
9
9
|
# Test classes for indexing functionality
|
10
10
|
class ::TestUser < Familia::Horreum
|
@@ -55,13 +55,18 @@ end
|
|
55
55
|
|
56
56
|
# Setup
|
57
57
|
@user1 = TestUser.new(user_id: 'user_001', email: 'alice@example.com', username: 'alice', department: 'engineering', role: 'developer')
|
58
|
+
@user1.save
|
58
59
|
@user2 = TestUser.new(user_id: 'user_002', email: 'bob@example.com', username: 'bob', department: 'marketing', role: 'manager')
|
60
|
+
@user2.save
|
59
61
|
@user3 = TestUser.new(user_id: 'user_003', email: 'charlie@example.com', username: 'charlie', department: 'engineering', role: 'lead')
|
62
|
+
@user3.save
|
60
63
|
|
61
64
|
@company_id = "comp_#{rand(10000000)}"
|
62
65
|
@company = TestCompany.create(company_id: @company_id, name: 'Acme Corp')
|
63
66
|
@emp1 = TestEmployee.new(emp_id: 'emp_001', email: 'alice@acme.com', department: 'engineering', manager_id: 'mgr_001', badge_number: 'BADGE001')
|
67
|
+
@emp1.save
|
64
68
|
@emp2 = TestEmployee.new(emp_id: 'emp_002', email: 'bob@acme.com', department: 'sales', manager_id: 'mgr_002', badge_number: 'BADGE002')
|
69
|
+
@emp2.save
|
65
70
|
|
66
71
|
|
67
72
|
## Context-scoped methods require context parameter
|
@@ -7,7 +7,7 @@ RSpec.describe 'participation_commands_verification_try' do
|
|
7
7
|
Timecop.freeze(Time.parse("2024-01-15 10:30:00"))
|
8
8
|
puts Time.now # Always returns 2024-01-15 10:30:00
|
9
9
|
puts Date.today # Always returns 2024-01-15
|
10
|
-
require_relative '../../../lib/middleware/
|
10
|
+
require_relative '../../../lib/middleware/database_logger'
|
11
11
|
require_relative '../../../lib/familia'
|
12
12
|
Familia.enable_database_logging = true
|
13
13
|
Familia.enable_database_counter = true
|
@@ -17,7 +17,7 @@ puts Date.today # Always returns 2024-01-15
|
|
17
17
|
|
18
18
|
|
19
19
|
# Load middleware first
|
20
|
-
require_relative '../../../lib/middleware/
|
20
|
+
require_relative '../../../lib/middleware/database_logger'
|
21
21
|
|
22
22
|
# Load Familia
|
23
23
|
require_relative '../../../lib/familia'
|
@@ -83,7 +83,7 @@ instantiation_commands.empty?
|
|
83
83
|
database_commands = DatabaseLogger.capture_commands do
|
84
84
|
@customer.save
|
85
85
|
end
|
86
|
-
database_commands.map { |cmd| cmd
|
86
|
+
database_commands.map { |cmd| cmd.command } if database_commands
|
87
87
|
##=> [["hmset", "reverse_index_customer:ri_cust_123:object", "customer_id", "ri_cust_123", "name", "Reverse Index Test Customer"], ["zadd", "reverse_index_customer:instances", "1705343400.0", "ri_cust_123"]]
|
88
88
|
|
89
89
|
|
@@ -91,14 +91,14 @@ database_commands.map { |cmd| cmd[:command] } if database_commands
|
|
91
91
|
database_commands = DatabaseLogger.capture_commands do
|
92
92
|
@domain1.save
|
93
93
|
end
|
94
|
-
database_commands[0]
|
94
|
+
database_commands[0].command if database_commands && database_commands[0]
|
95
95
|
##=> ["hmset", "reverse_index_domain:ri_dom_1:object", "domain_id", "ri_dom_1", "display_domain", "example1.com", "created_at", "1705343400.0"]
|
96
96
|
|
97
97
|
## Domain2 save functionality
|
98
98
|
database_commands = DatabaseLogger.capture_commands do
|
99
99
|
@domain2.save
|
100
100
|
end
|
101
|
-
database_commands[0]
|
101
|
+
database_commands[0].command if database_commands && database_commands[0]
|
102
102
|
##=> ["hmset", "reverse_index_domain:ri_dom_2:object", "domain_id", "ri_dom_2", "display_domain", "example2.com", "created_at", "1705343401.0"]
|
103
103
|
|
104
104
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# Tests for performance improvements in participation functionality
|
4
4
|
# Verifies reverse index functionality and robust type comparison
|
5
5
|
|
6
|
-
require_relative '../../helpers/test_helpers'
|
6
|
+
require_relative '../../support/helpers/test_helpers'
|
7
7
|
|
8
8
|
# Test classes for performance improvements
|
9
9
|
class PerfTestCustomer < Familia::Horreum
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# Tests for participation reverse index functionality
|
4
4
|
# Verifies performance improvements and correct behavior
|
5
5
|
|
6
|
-
require_relative '../../helpers/test_helpers'
|
6
|
+
require_relative '../../support/helpers/test_helpers'
|
7
7
|
|
8
8
|
# Test classes for reverse index functionality
|
9
9
|
class ReverseIndexCustomer < Familia::Horreum
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# Testing new class_participates_in and unique_index methods
|
5
5
|
# Testing breaking changes and argument validation
|
6
6
|
|
7
|
-
require_relative '../../helpers/test_helpers'
|
7
|
+
require_relative '../../support/helpers/test_helpers'
|
8
8
|
|
9
9
|
# Test classes for new API
|
10
10
|
class ::ApiTestUser < Familia::Horreum
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Simplified edge case testing for Relationships v2 - focusing on core functionality
|
2
2
|
|
3
|
-
require_relative '../../helpers/test_helpers'
|
3
|
+
require_relative '../../support/helpers/test_helpers'
|
4
4
|
|
5
5
|
# Test classes for edge case testing
|
6
6
|
class EdgeTestCustomer < Familia::Horreum
|
@@ -41,14 +41,14 @@ end
|
|
41
41
|
@domain1 = EdgeTestDomain.new(
|
42
42
|
domain_id: 'edge_dom_1',
|
43
43
|
display_domain: 'edge1.example.com',
|
44
|
-
created_at: Time.new(2025, 6, 15, 12, 0, 0),
|
44
|
+
created_at: Time.new(2025, 6, 15, 12, 0, 0).to_i, # Convert Time to Integer for JSON serialization
|
45
45
|
score_value: 10
|
46
46
|
)
|
47
47
|
|
48
48
|
@domain2 = EdgeTestDomain.new(
|
49
49
|
domain_id: 'edge_dom_2',
|
50
50
|
display_domain: 'edge2.example.com',
|
51
|
-
created_at: Time.new(2025, 7, 20, 15, 30, 0),
|
51
|
+
created_at: Time.new(2025, 7, 20, 15, 30, 0).to_i, # Convert Time to Integer for JSON serialization
|
52
52
|
score_value: 25
|
53
53
|
)
|
54
54
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# Simplified Familia v2 relationship functionality tests - focusing on core working features
|
4
4
|
#
|
5
5
|
|
6
|
-
require_relative '../../helpers/test_helpers'
|
6
|
+
require_relative '../../support/helpers/test_helpers'
|
7
7
|
|
8
8
|
# Test classes for Familia v2 relationship functionality
|
9
9
|
class TestCustomer < Familia::Horreum
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# These tryouts test the safe dumping functionality.
|
4
4
|
|
5
|
-
require_relative '../../helpers/test_helpers'
|
5
|
+
require_relative '../../support/helpers/test_helpers'
|
6
6
|
|
7
7
|
## By default Familia::Base has no safe_dump_fields method
|
8
8
|
Familia::Base.respond_to?(:safe_dump_fields)
|
@@ -12,7 +12,7 @@
|
|
12
12
|
# - Operation guards prevent unsafe scenarios before fiber issues arise
|
13
13
|
# - Method aliases work correctly
|
14
14
|
|
15
|
-
require_relative '
|
15
|
+
require_relative '../../support/helpers/test_helpers'
|
16
16
|
|
17
17
|
## Transaction method works without previous_conn preservation
|
18
18
|
customer = Customer.new(custid: 'tx_test')
|
@@ -8,7 +8,7 @@
|
|
8
8
|
# - Fresh connections (provider/create) → safe for all operations
|
9
9
|
# - Transaction connections → safe for reentrant transactions only
|
10
10
|
|
11
|
-
require_relative '
|
11
|
+
require_relative '../../support/helpers/test_helpers'
|
12
12
|
|
13
13
|
## FiberTransactionHandler constraints
|
14
14
|
Familia::Connection::FiberTransactionHandler.allows_transaction
|
@@ -5,7 +5,7 @@
|
|
5
5
|
# Tests for isolated database connections that don't interfere
|
6
6
|
# with the cached connection pool or existing model connections.
|
7
7
|
|
8
|
-
require_relative '
|
8
|
+
require_relative '../../support/helpers/test_helpers'
|
9
9
|
|
10
10
|
# Clean up any existing test data in all test databases
|
11
11
|
(0..2).each do |db|
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# try/integration/connection/middleware_reconnect_try.rb
|
2
|
+
#
|
3
|
+
# Tests for Familia.reconnect! method that refreshes connection pools
|
4
|
+
# with current middleware configuration
|
5
|
+
|
6
|
+
require_relative '../../support/helpers/test_helpers'
|
7
|
+
require 'connection_pool'
|
8
|
+
|
9
|
+
# Disable logging for cleaner test output
|
10
|
+
Familia.enable_database_logging = false
|
11
|
+
|
12
|
+
# Test model for middleware reconnection testing
|
13
|
+
class ReconnectTestUser < Familia::Horreum
|
14
|
+
identifier_field :user_id
|
15
|
+
field :user_id
|
16
|
+
field :name
|
17
|
+
|
18
|
+
def init
|
19
|
+
@user_id ||= SecureRandom.hex(4)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
## Test 5: Middleware re-registration flag is reset and re-set
|
24
|
+
Familia.enable_database_logging = true
|
25
|
+
Familia.instance_variable_set(:@middleware_registered, true)
|
26
|
+
Familia.reconnect!
|
27
|
+
was_registered = Familia.instance_variable_get(:@middleware_registered)
|
28
|
+
was_registered
|
29
|
+
#=> true
|
30
|
+
|
31
|
+
## Test 6: reconnect! safely handles no middleware enabled
|
32
|
+
Familia.enable_database_logging = false
|
33
|
+
Familia.enable_database_counter = false
|
34
|
+
Familia.reconnect!
|
35
|
+
chain_cleared = Familia.instance_variable_get(:@connection_chain).nil?
|
36
|
+
chain_cleared
|
37
|
+
#=> true
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
## Setup: Clean database
|
42
|
+
ReconnectTestUser.dbclient.flushdb
|
43
|
+
#=> "OK"
|
44
|
+
|
45
|
+
## Test 1: Basic reconnect functionality clears chain and increments version
|
46
|
+
Familia.enable_database_logging = true
|
47
|
+
initial = Familia.middleware_version
|
48
|
+
Familia.reconnect!
|
49
|
+
chain_cleared = Familia.instance_variable_get(:@connection_chain).nil?
|
50
|
+
version_incremented = Familia.middleware_version > initial
|
51
|
+
[chain_cleared, version_incremented]
|
52
|
+
#=> [true, true]
|
53
|
+
|
54
|
+
## Test 2: Reconnect works with connection providers
|
55
|
+
|
56
|
+
# Create a simple connection provider
|
57
|
+
Familia.connection_provider = ->(uri) { Redis.new(url: uri) }
|
58
|
+
|
59
|
+
## Reconnect clears chain even with provider
|
60
|
+
Familia.reconnect!
|
61
|
+
Familia.instance_variable_get(:@connection_chain)
|
62
|
+
#=> nil
|
63
|
+
|
64
|
+
## Test 3: Verify new connections work after reconnect
|
65
|
+
|
66
|
+
# Create user to trigger connection
|
67
|
+
@user = ReconnectTestUser.new(name: "Bob")
|
68
|
+
@user.save
|
69
|
+
#=> true
|
70
|
+
|
71
|
+
## User should be retrievable
|
72
|
+
@retrieved = ReconnectTestUser.find(@user.identifier)
|
73
|
+
@retrieved.name
|
74
|
+
#=> "Bob"
|
75
|
+
|
76
|
+
## Test 4: Multiple reconnects are safe
|
77
|
+
Familia.reconnect!
|
78
|
+
Familia.reconnect!
|
79
|
+
Familia.reconnect!
|
80
|
+
|
81
|
+
## Connection chain should still be cleared (will rebuild on next use)
|
82
|
+
Familia.instance_variable_get(:@connection_chain)
|
83
|
+
#=> nil
|
84
|
+
|
85
|
+
## Cleanup
|
86
|
+
Familia.enable_database_logging = false
|
87
|
+
Familia.connection_provider = nil
|
@@ -12,7 +12,7 @@
|
|
12
12
|
# This prevents bugs where middleware/cached connections return "QUEUED" instead
|
13
13
|
# of actual values, breaking conditional logic and business rules.
|
14
14
|
|
15
|
-
require_relative '
|
15
|
+
require_relative '../../support/helpers/test_helpers'
|
16
16
|
|
17
17
|
## FiberConnectionHandler blocks transactions in strict mode
|
18
18
|
begin
|
@@ -10,7 +10,7 @@
|
|
10
10
|
# - Return the connection from the successful handler
|
11
11
|
# - Return nil if no handler provides a connection
|
12
12
|
|
13
|
-
require_relative '
|
13
|
+
require_relative '../../support/helpers/test_helpers'
|
14
14
|
|
15
15
|
# Setup - clear any existing fiber state
|
16
16
|
Fiber[:familia_connection_handler_class] = nil
|
@@ -8,7 +8,7 @@
|
|
8
8
|
# with Familia's existing features when connection handlers don't support
|
9
9
|
# transactions (e.g., cached connections, middleware connections).
|
10
10
|
|
11
|
-
require_relative '
|
11
|
+
require_relative '../../support/helpers/test_helpers'
|
12
12
|
|
13
13
|
# Setup - store original values
|
14
14
|
$original_transaction_mode = Familia.transaction_mode
|
@@ -5,7 +5,7 @@
|
|
5
5
|
#
|
6
6
|
# Permissive mode: Silently uses IndividualCommandProxy for fallback
|
7
7
|
|
8
|
-
require_relative '
|
8
|
+
require_relative '../../support/helpers/test_helpers'
|
9
9
|
|
10
10
|
# Test class for permissive mode testing
|
11
11
|
class PermissiveModeTestCustomer < Familia::Horreum
|
@@ -5,7 +5,7 @@
|
|
5
5
|
#
|
6
6
|
# Strict mode: Raises OperationModeError when transaction unavailable
|
7
7
|
|
8
|
-
require_relative '
|
8
|
+
require_relative '../../support/helpers/test_helpers'
|
9
9
|
|
10
10
|
# Test class for strict mode testing
|
11
11
|
class StrictModeTestCustomer < Familia::Horreum
|
@@ -5,7 +5,7 @@
|
|
5
5
|
#
|
6
6
|
# Warn mode: Logs warning and uses IndividualCommandProxy for fallback
|
7
7
|
|
8
|
-
require_relative '
|
8
|
+
require_relative '../../support/helpers/test_helpers'
|
9
9
|
|
10
10
|
# Test class for warn mode testing
|
11
11
|
class WarnModeTestCustomer < Familia::Horreum
|
@@ -10,7 +10,7 @@
|
|
10
10
|
# The IndividualCommandProxy executes Redis commands immediately instead of queuing
|
11
11
|
# them in a transaction, maintaining the same MultiResult interface for consistency.
|
12
12
|
|
13
|
-
require_relative '
|
13
|
+
require_relative '../../support/helpers/test_helpers'
|
14
14
|
|
15
15
|
# Setup - ensure clean state
|
16
16
|
@original_transaction_mode = Familia.transaction_mode
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# Comprehensive test coverage for the create method
|
4
4
|
# Tests the correct exception type and error message handling
|
5
5
|
|
6
|
-
require_relative '../helpers/test_helpers'
|
6
|
+
require_relative '../support/helpers/test_helpers'
|
7
7
|
|
8
8
|
# Test class for create method behavior
|
9
9
|
class CreateTestModel < Familia::Horreum
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# Database consistency verification and edge case testing
|
4
4
|
# Complements persistence_operations_try.rb with deeper consistency checks
|
5
5
|
|
6
|
-
require_relative '../helpers/test_helpers'
|
6
|
+
require_relative '../support/helpers/test_helpers'
|
7
7
|
|
8
8
|
# Test class with different field types for consistency verification
|
9
9
|
class ConsistencyTestModel < Familia::Horreum
|
@@ -55,15 +55,18 @@ key_parts = dbkey.split(':')
|
|
55
55
|
# Refresh and verify data integrity
|
56
56
|
@serial_test.refresh!
|
57
57
|
[@serial_test.name, @serial_test.active, @serial_test.metadata]
|
58
|
-
#=> [
|
58
|
+
#=> ["Serialization Test", true, {"key"=>"value", "array"=>[1, 2, 3]}]
|
59
59
|
|
60
60
|
## Hash field count matches object field count
|
61
|
+
@serial_test = ConsistencyTestModel.new(id: next_test_id)
|
62
|
+
@serial_test.save
|
61
63
|
expected_fields = @serial_test.class.persistent_fields.length
|
62
64
|
redis_field_count = Familia.dbclient.hlen(@serial_test.dbkey)
|
63
65
|
actual_object_fields = @serial_test.to_h.keys.length
|
64
|
-
#
|
65
|
-
|
66
|
-
|
66
|
+
# The JSON Serializer stores all fields (including nil as "null")
|
67
|
+
# Expected fields (5) >= redis count (5) >= to_h count (5, even though email is nil)
|
68
|
+
[expected_fields, redis_field_count, actual_object_fields]
|
69
|
+
#=> [5, 5, 5]
|
67
70
|
|
68
71
|
## Memory vs persistence state consistency after save
|
69
72
|
@consistency_obj = ConsistencyTestModel.new(id: next_test_id, name: 'Memory Test', email: 'test@example.com')
|
@@ -73,9 +76,9 @@ actual_object_fields = @serial_test.to_h.keys.length
|
|
73
76
|
memory_name = @consistency_obj.name
|
74
77
|
memory_email = @consistency_obj.email
|
75
78
|
|
76
|
-
# Get persistence state
|
77
|
-
redis_name = Familia.dbclient.hget(@consistency_obj.dbkey, 'name')
|
78
|
-
redis_email = Familia.dbclient.hget(@consistency_obj.dbkey, 'email')
|
79
|
+
# Get persistence state (deserialize from JSON storage)
|
80
|
+
redis_name = @consistency_obj.deserialize_value(Familia.dbclient.hget(@consistency_obj.dbkey, 'name'))
|
81
|
+
redis_email = @consistency_obj.deserialize_value(Familia.dbclient.hget(@consistency_obj.dbkey, 'email'))
|
79
82
|
|
80
83
|
[memory_name == redis_name, memory_email == redis_email]
|
81
84
|
#=> [true, true]
|