familia 2.0.0.pre14 → 2.0.0.pre16
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/.github/workflows/code-quality.yml +138 -0
- data/.github/workflows/code-smellage.yml +145 -0
- data/.github/workflows/docs.yml +31 -8
- data/.gitignore +1 -1
- data/.pre-commit-config.yaml +7 -1
- data/.reek.yml +98 -0
- data/.rubocop.yml +48 -10
- data/.talismanrc +9 -0
- data/.yardopts +18 -13
- data/CHANGELOG.rst +66 -6
- data/CLAUDE.md +1 -1
- data/Gemfile +6 -5
- data/Gemfile.lock +99 -23
- data/LICENSE.txt +1 -1
- data/README.md +285 -85
- data/changelog.d/README.md +2 -2
- data/docs/archive/FAMILIA_RELATIONSHIPS.md +22 -22
- data/docs/archive/FAMILIA_TECHNICAL.md +41 -41
- data/docs/archive/FAMILIA_UPDATE.md +3 -3
- data/docs/archive/README.md +3 -2
- data/docs/{guides/API-Reference.md → archive/api-reference.md} +87 -101
- data/docs/conf.py +29 -0
- data/docs/guides/{Field-System-Guide.md → core-field-system.md} +9 -9
- data/docs/guides/feature-encrypted-fields.md +785 -0
- data/docs/guides/{Expiration-Feature-Guide.md → feature-expiration.md} +11 -2
- data/docs/guides/feature-external-identifiers.md +637 -0
- data/docs/guides/feature-object-identifiers.md +435 -0
- data/docs/guides/{Quantization-Feature-Guide.md → feature-quantization.md} +94 -29
- data/docs/guides/feature-relationships-methods.md +684 -0
- data/docs/guides/feature-relationships.md +200 -0
- data/docs/guides/{Features-System-Developer-Guide.md → feature-system-devs.md} +4 -4
- data/docs/guides/{Feature-System-Guide.md → feature-system.md} +5 -5
- data/docs/guides/{Transient-Fields-Guide.md → feature-transient-fields.md} +2 -2
- data/docs/guides/{Implementation-Guide.md → implementation.md} +3 -3
- data/docs/guides/index.md +176 -0
- data/docs/guides/{Security-Model.md → security-model.md} +1 -1
- data/docs/migrating/v2.0.0-pre.md +1 -1
- data/docs/migrating/v2.0.0-pre11.md +4 -4
- data/docs/migrating/v2.0.0-pre12.md +2 -2
- data/docs/migrating/v2.0.0-pre13.md +1 -1
- data/docs/migrating/v2.0.0-pre5.md +33 -12
- data/docs/migrating/v2.0.0-pre6.md +2 -2
- data/docs/migrating/v2.0.0-pre7.md +8 -8
- data/docs/overview.md +623 -19
- data/docs/reference/api-technical.md +1365 -0
- data/examples/autoloader/mega_customer/features/deprecated_fields.rb +7 -0
- data/examples/autoloader/mega_customer/safe_dump_fields.rb +1 -1
- data/examples/autoloader/mega_customer.rb +3 -1
- data/examples/encrypted_fields.rb +378 -0
- data/examples/json_usage_patterns.rb +144 -0
- data/examples/relationships.rb +13 -13
- data/examples/safe_dump.rb +6 -6
- data/examples/single_connection_transaction_confusions.rb +379 -0
- data/lib/familia/base.rb +49 -10
- data/lib/familia/connection/handlers.rb +223 -0
- data/lib/familia/connection/individual_command_proxy.rb +64 -0
- data/lib/familia/connection/middleware.rb +75 -0
- data/lib/familia/connection/operation_core.rb +93 -0
- data/lib/familia/connection/operations.rb +277 -0
- data/lib/familia/connection/pipeline_core.rb +87 -0
- data/lib/familia/connection/transaction_core.rb +100 -0
- data/lib/familia/connection.rb +60 -186
- data/lib/familia/data_type/commands.rb +53 -51
- data/lib/familia/data_type/serialization.rb +108 -107
- data/lib/familia/data_type/types/counter.rb +1 -1
- data/lib/familia/data_type/types/hashkey.rb +13 -10
- data/lib/familia/data_type/types/{list.rb → listkey.rb} +13 -5
- data/lib/familia/data_type/types/lock.rb +3 -2
- data/lib/familia/data_type/types/sorted_set.rb +26 -15
- data/lib/familia/data_type/types/{string.rb → stringkey.rb} +7 -5
- data/lib/familia/data_type/types/unsorted_set.rb +20 -27
- data/lib/familia/data_type.rb +75 -47
- data/lib/familia/distinguisher.rb +85 -0
- data/lib/familia/encryption/encrypted_data.rb +15 -24
- data/lib/familia/encryption/manager.rb +6 -4
- data/lib/familia/encryption/providers/aes_gcm_provider.rb +1 -1
- data/lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb +7 -9
- data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +4 -5
- data/lib/familia/encryption/request_cache.rb +7 -7
- data/lib/familia/encryption.rb +2 -3
- data/lib/familia/errors.rb +9 -3
- data/lib/familia/{autoloader.rb → features/autoloader.rb} +49 -23
- data/lib/familia/features/encrypted_fields/concealed_string.rb +3 -4
- data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +13 -14
- data/lib/familia/features/encrypted_fields.rb +68 -66
- data/lib/familia/features/expiration/extensions.rb +61 -0
- data/lib/familia/features/expiration.rb +35 -87
- data/lib/familia/features/external_identifier.rb +11 -12
- data/lib/familia/features/object_identifier.rb +58 -20
- data/lib/familia/features/quantization.rb +17 -22
- data/lib/familia/features/relationships/README.md +97 -0
- data/lib/familia/features/relationships/collection_operations.rb +104 -0
- data/lib/familia/features/relationships/indexing/multi_index_generators.rb +202 -0
- data/lib/familia/features/relationships/indexing/unique_index_generators.rb +301 -0
- data/lib/familia/features/relationships/indexing.rb +176 -256
- data/lib/familia/features/relationships/indexing_relationship.rb +35 -0
- data/lib/familia/features/relationships/participation/participant_methods.rb +160 -0
- data/lib/familia/features/relationships/participation/target_methods.rb +225 -0
- data/lib/familia/features/relationships/participation.rb +656 -0
- data/lib/familia/features/relationships/participation_relationship.rb +31 -0
- data/lib/familia/features/relationships/score_encoding.rb +20 -20
- data/lib/familia/features/relationships.rb +69 -271
- data/lib/familia/features/safe_dump.rb +127 -132
- data/lib/familia/features/transient_fields/redacted_string.rb +6 -6
- data/lib/familia/features/transient_fields/transient_field_type.rb +5 -5
- data/lib/familia/features/transient_fields.rb +5 -5
- data/lib/familia/features.rb +21 -21
- data/lib/familia/field_type.rb +24 -4
- data/lib/familia/horreum/core/connection.rb +229 -26
- data/lib/familia/horreum/core/database_commands.rb +27 -17
- data/lib/familia/horreum/core/serialization.rb +40 -20
- data/lib/familia/horreum/core/utils.rb +2 -1
- data/lib/familia/horreum/shared/settings.rb +2 -1
- data/lib/familia/horreum/subclass/definition.rb +33 -45
- data/lib/familia/horreum/subclass/management.rb +72 -24
- data/lib/familia/horreum/subclass/related_fields_management.rb +82 -21
- data/lib/familia/horreum.rb +196 -114
- data/lib/familia/json_serializer.rb +0 -1
- data/lib/familia/logging.rb +11 -114
- data/lib/familia/refinements/dear_json.rb +122 -0
- data/lib/familia/refinements/logger_trace.rb +20 -17
- data/lib/familia/refinements/stylize_words.rb +65 -0
- data/lib/familia/refinements/time_literals.rb +60 -52
- data/lib/familia/refinements.rb +2 -1
- data/lib/familia/secure_identifier.rb +60 -28
- data/lib/familia/settings.rb +83 -7
- data/lib/familia/utils.rb +5 -87
- data/lib/familia/verifiable_identifier.rb +4 -4
- data/lib/familia/version.rb +1 -1
- data/lib/familia.rb +72 -15
- data/lib/middleware/database_middleware.rb +56 -14
- data/lib/{familia/multi_result.rb → multi_result.rb} +23 -16
- data/try/configuration/scenarios_try.rb +1 -1
- data/try/connection/fiber_context_preservation_try.rb +250 -0
- data/try/connection/handler_constraints_try.rb +59 -0
- data/try/connection/operation_mode_guards_try.rb +208 -0
- data/try/connection/pipeline_fallback_integration_try.rb +128 -0
- data/try/connection/responsibility_chain_tracking_try.rb +72 -0
- data/try/connection/transaction_fallback_integration_try.rb +288 -0
- data/try/connection/transaction_mode_permissive_try.rb +153 -0
- data/try/connection/transaction_mode_strict_try.rb +98 -0
- data/try/connection/transaction_mode_warn_try.rb +131 -0
- data/try/connection/transaction_modes_try.rb +249 -0
- data/try/core/autoloader_try.rb +129 -11
- data/try/core/connection_try.rb +7 -7
- data/try/core/conventional_inheritance_try.rb +130 -0
- data/try/core/create_method_try.rb +15 -23
- data/try/core/database_consistency_try.rb +10 -10
- data/try/core/errors_try.rb +8 -11
- data/try/core/familia_extended_try.rb +2 -2
- data/try/core/familia_members_methods_try.rb +76 -0
- data/try/core/isolated_dbclient_try.rb +165 -0
- data/try/core/middleware_try.rb +16 -16
- data/try/core/persistence_operations_try.rb +4 -4
- data/try/core/pools_try.rb +42 -26
- data/try/core/secure_identifier_try.rb +28 -24
- data/try/core/time_utils_try.rb +10 -10
- data/try/core/tools_try.rb +1 -1
- data/try/core/utils_try.rb +2 -2
- data/try/data_types/boolean_try.rb +4 -4
- data/try/data_types/datatype_base_try.rb +0 -2
- data/try/data_types/list_try.rb +10 -10
- data/try/data_types/sorted_set_try.rb +5 -5
- data/try/data_types/string_try.rb +12 -12
- data/try/data_types/unsortedset_try.rb +33 -0
- data/try/debugging/cache_behavior_tracer.rb +7 -7
- data/try/debugging/debug_aad_process.rb +1 -1
- data/try/debugging/debug_concealed_internal.rb +1 -1
- data/try/debugging/debug_cross_context.rb +1 -1
- data/try/debugging/debug_fresh_cross_context.rb +1 -1
- data/try/debugging/encryption_method_tracer.rb +10 -10
- data/try/edge_cases/hash_symbolization_try.rb +1 -1
- data/try/edge_cases/ttl_side_effects_try.rb +1 -1
- data/try/encryption/config_persistence_try.rb +2 -2
- data/try/encryption/encryption_core_try.rb +19 -19
- data/try/encryption/instance_variable_scope_try.rb +1 -1
- data/try/encryption/module_loading_try.rb +2 -2
- data/try/encryption/providers/aes_gcm_provider_try.rb +1 -1
- data/try/encryption/providers/xchacha20_poly1305_provider_try.rb +1 -1
- data/try/encryption/secure_memory_handling_try.rb +1 -1
- data/try/features/encrypted_fields/concealed_string_core_try.rb +11 -7
- data/try/features/encrypted_fields/encrypted_fields_core_try.rb +1 -1
- data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +3 -3
- data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +10 -10
- data/try/features/encrypted_fields/encrypted_fields_security_try.rb +14 -14
- data/try/features/encrypted_fields/error_conditions_try.rb +7 -7
- data/try/features/encrypted_fields/fresh_key_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 +7 -7
- data/try/features/encrypted_fields/universal_serialization_safety_try.rb +13 -20
- data/try/features/external_identifier/external_identifier_try.rb +1 -1
- data/try/features/feature_dependencies_try.rb +3 -3
- data/try/features/object_identifier/object_identifier_integration_try.rb +28 -34
- data/try/features/object_identifier/object_identifier_try.rb +10 -0
- data/try/features/quantization/quantization_try.rb +1 -1
- data/try/features/relationships/indexing_commands_verification_try.rb +136 -0
- data/try/features/relationships/indexing_try.rb +433 -0
- data/try/features/relationships/participation_commands_verification_spec.rb +102 -0
- data/try/features/relationships/participation_commands_verification_try.rb +105 -0
- data/try/features/relationships/participation_performance_improvements_try.rb +124 -0
- data/try/features/relationships/participation_reverse_index_try.rb +196 -0
- data/try/features/relationships/relationships_api_changes_try.rb +72 -71
- data/try/features/relationships/relationships_edge_cases_try.rb +15 -18
- data/try/features/relationships/relationships_performance_minimal_try.rb +2 -2
- data/try/features/relationships/relationships_performance_simple_try.rb +8 -8
- data/try/features/relationships/relationships_performance_try.rb +20 -20
- data/try/features/relationships/relationships_try.rb +27 -38
- data/try/features/safe_dump/safe_dump_advanced_try.rb +2 -2
- data/try/features/transient_fields/refresh_reset_try.rb +1 -1
- data/try/features/transient_fields/simple_refresh_test.rb +1 -1
- data/try/helpers/test_cleanup.rb +86 -0
- data/try/helpers/test_helpers.rb +3 -3
- data/try/horreum/base_try.rb +3 -2
- data/try/horreum/commands_try.rb +1 -1
- data/try/horreum/destroy_related_fields_cleanup_try.rb +330 -0
- data/try/horreum/initialization_try.rb +11 -7
- data/try/horreum/relations_try.rb +21 -13
- data/try/horreum/serialization_try.rb +12 -11
- data/try/integration/cross_component_try.rb +3 -3
- data/try/memory/memory_basic_test.rb +1 -1
- data/try/memory/memory_docker_ruby_dump.sh +1 -1
- data/try/models/customer_safe_dump_try.rb +1 -1
- data/try/models/customer_try.rb +8 -10
- data/try/models/datatype_base_try.rb +3 -3
- data/try/models/familia_object_try.rb +9 -8
- data/try/performance/benchmarks_try.rb +2 -2
- data/try/prototypes/atomic_saves_v1_context_proxy.rb +2 -2
- data/try/prototypes/atomic_saves_v3_connection_pool.rb +3 -3
- data/try/prototypes/atomic_saves_v4.rb +1 -1
- data/try/prototypes/lib/atomic_saves_v2_connection_switching_helpers.rb +4 -4
- data/try/prototypes/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -4
- data/try/prototypes/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -4
- data/try/prototypes/pooling/lib/connection_pool_metrics.rb +5 -5
- data/try/prototypes/pooling/lib/connection_pool_stress_test.rb +26 -26
- data/try/prototypes/pooling/lib/connection_pool_threading_models.rb +7 -7
- data/try/prototypes/pooling/lib/visualize_stress_results.rb +1 -1
- data/try/prototypes/pooling/pool_siege.rb +11 -11
- data/try/prototypes/pooling/run_stress_tests.rb +7 -7
- data/try/refinements/dear_json_array_methods_try.rb +53 -0
- data/try/refinements/dear_json_hash_methods_try.rb +54 -0
- data/try/refinements/logger_trace_methods_try.rb +44 -0
- data/try/refinements/time_literals_numeric_methods_try.rb +141 -0
- data/try/refinements/time_literals_string_methods_try.rb +80 -0
- metadata +77 -45
- data/.rubocop_todo.yml +0 -208
- data/docs/connection_pooling.md +0 -192
- data/docs/guides/Connection-Pooling-Guide.md +0 -437
- data/docs/guides/Encrypted-Fields-Overview.md +0 -101
- data/docs/guides/Feature-System-Autoloading.md +0 -228
- data/docs/guides/Home.md +0 -116
- data/docs/guides/Relationships-Guide.md +0 -737
- data/docs/guides/relationships-methods.md +0 -266
- data/docs/reference/auditing_database_commands.rb +0 -228
- data/examples/permissions.rb +0 -240
- data/lib/familia/features/autoloadable.rb +0 -113
- data/lib/familia/features/relationships/cascading.rb +0 -437
- data/lib/familia/features/relationships/membership.rb +0 -497
- data/lib/familia/features/relationships/permission_management.rb +0 -264
- data/lib/familia/features/relationships/querying.rb +0 -615
- data/lib/familia/features/relationships/redis_operations.rb +0 -274
- data/lib/familia/features/relationships/tracking.rb +0 -418
- data/lib/familia/refinements/snake_case.rb +0 -40
- data/lib/familia/validation/command_recorder.rb +0 -336
- data/lib/familia/validation/expectations.rb +0 -519
- data/lib/familia/validation/validation_helpers.rb +0 -443
- data/lib/familia/validation/validator.rb +0 -412
- data/lib/familia/validation.rb +0 -140
- data/try/data_types/set_try.rb +0 -33
- data/try/features/autoloadable/autoloadable_try.rb +0 -61
- data/try/features/relationships/categorical_permissions_try.rb +0 -515
- data/try/features/safe_dump/safe_dump_autoloading_try.rb +0 -111
- data/try/validation/atomic_operations_try.rb.disabled +0 -320
- data/try/validation/command_validation_try.rb.disabled +0 -207
- data/try/validation/performance_validation_try.rb.disabled +0 -324
- data/try/validation/real_world_scenarios_try.rb.disabled +0 -390
@@ -0,0 +1,131 @@
|
|
1
|
+
# Transaction Mode: Warn Tryouts
|
2
|
+
#
|
3
|
+
# Tests warn transaction mode behavior where operations log a warning
|
4
|
+
# and execute commands individually when transactions are unavailable.
|
5
|
+
#
|
6
|
+
# Warn mode: Logs warning and uses IndividualCommandProxy for fallback
|
7
|
+
|
8
|
+
require_relative '../helpers/test_helpers'
|
9
|
+
|
10
|
+
# Test class for warn mode testing
|
11
|
+
class WarnModeTestCustomer < Familia::Horreum
|
12
|
+
identifier_field :custid
|
13
|
+
field :custid
|
14
|
+
field :name
|
15
|
+
field :email
|
16
|
+
end
|
17
|
+
|
18
|
+
## Warn mode can be configured
|
19
|
+
Familia.configure { |config| config.transaction_mode = :warn }
|
20
|
+
Familia.transaction_mode
|
21
|
+
#=> :warn
|
22
|
+
|
23
|
+
## Warn mode executes individual commands with CachedConnectionHandler
|
24
|
+
begin
|
25
|
+
# Force CachedConnectionHandler
|
26
|
+
WarnModeTestCustomer.instance_variable_set(:@dbclient, Familia.create_dbclient)
|
27
|
+
|
28
|
+
customer = WarnModeTestCustomer.new(custid: 'warn_test')
|
29
|
+
result = customer.transaction do |conn|
|
30
|
+
# Should be IndividualCommandProxy
|
31
|
+
conn.class == Familia::Connection::IndividualCommandProxy &&
|
32
|
+
conn.hset(customer.dbkey, 'name', 'Warn Mode Works') &&
|
33
|
+
conn.hget(customer.dbkey, 'name')
|
34
|
+
end
|
35
|
+
|
36
|
+
result.is_a?(MultiResult) && result.results.last == 'Warn Mode Works'
|
37
|
+
ensure
|
38
|
+
WarnModeTestCustomer.remove_instance_variable(:@dbclient)
|
39
|
+
end
|
40
|
+
#=> true
|
41
|
+
|
42
|
+
## Warn mode executes individual commands with FiberConnectionHandler
|
43
|
+
begin
|
44
|
+
# Simulate middleware connection
|
45
|
+
Fiber[:familia_connection] = [Customer.create_dbclient, Familia.middleware_version]
|
46
|
+
Fiber[:familia_connection_handler_class] = Familia::Connection::FiberConnectionHandler
|
47
|
+
customer = WarnModeTestCustomer.new(custid: 'fiber_warn_test')
|
48
|
+
|
49
|
+
result = customer.transaction do |conn|
|
50
|
+
conn.class == Familia::Connection::IndividualCommandProxy &&
|
51
|
+
conn.hset(customer.dbkey, 'source', 'fiber_warn') &&
|
52
|
+
conn.hget(customer.dbkey, 'source')
|
53
|
+
end
|
54
|
+
|
55
|
+
result.is_a?(MultiResult) && result.results.last == 'fiber_warn'
|
56
|
+
ensure
|
57
|
+
Fiber[:familia_connection] = nil
|
58
|
+
Fiber[:familia_connection_handler_class] = nil
|
59
|
+
end
|
60
|
+
#=> true
|
61
|
+
|
62
|
+
## Warn mode still uses normal transactions with CreateConnectionHandler
|
63
|
+
begin
|
64
|
+
customer = WarnModeTestCustomer.new(custid: 'normal_warn_test')
|
65
|
+
result = customer.transaction do |conn|
|
66
|
+
# Should be Redis::MultiConnection for normal transactions
|
67
|
+
conn.class == Redis::MultiConnection &&
|
68
|
+
conn.hset(customer.dbkey, 'type', 'normal in warn mode') &&
|
69
|
+
conn.hget(customer.dbkey, 'type')
|
70
|
+
end
|
71
|
+
result.is_a?(MultiResult) && result.results.last == 'normal in warn mode'
|
72
|
+
end
|
73
|
+
#=> true
|
74
|
+
|
75
|
+
## IndividualCommandProxy collects results correctly in warn mode
|
76
|
+
begin
|
77
|
+
WarnModeTestCustomer.instance_variable_set(:@dbclient, Familia.create_dbclient)
|
78
|
+
|
79
|
+
customer = WarnModeTestCustomer.new(custid: 'proxy_warn_test')
|
80
|
+
result = customer.transaction do |conn|
|
81
|
+
conn.hset(customer.dbkey, 'field1', 'value1')
|
82
|
+
conn.hset(customer.dbkey, 'field2', 'value2')
|
83
|
+
conn.hget(customer.dbkey, 'field1')
|
84
|
+
conn.hget(customer.dbkey, 'field2')
|
85
|
+
end
|
86
|
+
|
87
|
+
# Check that results are collected properly
|
88
|
+
result.is_a?(MultiResult) &&
|
89
|
+
result.results.size == 4 &&
|
90
|
+
result.results.include?('value1') &&
|
91
|
+
result.results.include?('value2')
|
92
|
+
ensure
|
93
|
+
WarnModeTestCustomer.remove_instance_variable(:@dbclient)
|
94
|
+
end
|
95
|
+
#=> true
|
96
|
+
|
97
|
+
## Save operations work in warn mode with fallback
|
98
|
+
begin
|
99
|
+
WarnModeTestCustomer.instance_variable_set(:@dbclient, Familia.create_dbclient)
|
100
|
+
|
101
|
+
customer = WarnModeTestCustomer.new(
|
102
|
+
custid: 'save_warn_test',
|
103
|
+
name: 'Save Test User',
|
104
|
+
email: 'save@example.com'
|
105
|
+
)
|
106
|
+
|
107
|
+
# Save should work using individual commands
|
108
|
+
save_result = customer.save
|
109
|
+
save_result && customer.exists?
|
110
|
+
ensure
|
111
|
+
WarnModeTestCustomer.remove_instance_variable(:@dbclient)
|
112
|
+
end
|
113
|
+
#=> true
|
114
|
+
|
115
|
+
## Model transactions respect warn mode with cached connections
|
116
|
+
begin
|
117
|
+
# Test that cached connections on models respect warn mode
|
118
|
+
WarnModeTestCustomer.instance_variable_set(:@dbclient, Familia.create_dbclient)
|
119
|
+
|
120
|
+
customer = WarnModeTestCustomer.new(custid: 'model_warn_test')
|
121
|
+
result = customer.transaction do |conn|
|
122
|
+
conn.class == Familia::Connection::IndividualCommandProxy &&
|
123
|
+
conn.hset(customer.dbkey, 'mode', 'warn_fallback') &&
|
124
|
+
conn.hget(customer.dbkey, 'mode')
|
125
|
+
end
|
126
|
+
|
127
|
+
result.is_a?(MultiResult) && result.results.last == 'warn_fallback'
|
128
|
+
ensure
|
129
|
+
WarnModeTestCustomer.remove_instance_variable(:@dbclient)
|
130
|
+
end
|
131
|
+
#=> true
|
@@ -0,0 +1,249 @@
|
|
1
|
+
# Transaction Modes Tryouts
|
2
|
+
#
|
3
|
+
# Tests the configurable transaction mode system that provides graceful fallback
|
4
|
+
# when connection handlers don't support transactions. Three modes available:
|
5
|
+
#
|
6
|
+
# - :strict (default): Raise OperationModeError when transaction unavailable
|
7
|
+
# - :warn: Log warning and execute commands individually with IndividualCommandProxy
|
8
|
+
# - :permissive: Silently execute commands individually
|
9
|
+
#
|
10
|
+
# The IndividualCommandProxy executes Redis commands immediately instead of queuing
|
11
|
+
# them in a transaction, maintaining the same MultiResult interface for consistency.
|
12
|
+
|
13
|
+
require_relative '../helpers/test_helpers'
|
14
|
+
|
15
|
+
# Setup - ensure clean state
|
16
|
+
@original_transaction_mode = Familia.transaction_mode
|
17
|
+
@test_customer_class = nil
|
18
|
+
|
19
|
+
# Create a test customer class for isolation
|
20
|
+
class TransactionModeTestCustomer < Familia::Horreum
|
21
|
+
identifier_field :custid
|
22
|
+
field :custid
|
23
|
+
field :name
|
24
|
+
field :email
|
25
|
+
end
|
26
|
+
|
27
|
+
## Default transaction mode is warn (user-friendly)
|
28
|
+
Familia.transaction_mode
|
29
|
+
#=> :warn
|
30
|
+
|
31
|
+
## Transaction mode can be configured to warn
|
32
|
+
Familia.configure do |config|
|
33
|
+
config.transaction_mode = :warn
|
34
|
+
end
|
35
|
+
Familia.transaction_mode
|
36
|
+
#=> :warn
|
37
|
+
|
38
|
+
## Transaction mode can be configured to permissive
|
39
|
+
Familia.configure do |config|
|
40
|
+
config.transaction_mode = :permissive
|
41
|
+
end
|
42
|
+
Familia.transaction_mode
|
43
|
+
#=> :permissive
|
44
|
+
|
45
|
+
## Reset to strict mode for remaining tests
|
46
|
+
Familia.configure { |config| config.transaction_mode = :strict }
|
47
|
+
|
48
|
+
## Strict mode raises error with CachedConnectionHandler
|
49
|
+
begin
|
50
|
+
# Ensure we're in strict mode first
|
51
|
+
Familia.configure { |config| config.transaction_mode = :strict }
|
52
|
+
|
53
|
+
# Force CachedConnectionHandler by setting @dbclient
|
54
|
+
TransactionModeTestCustomer.instance_variable_set(:@dbclient, Familia.create_dbclient)
|
55
|
+
|
56
|
+
customer = TransactionModeTestCustomer.new(custid: 'strict_test')
|
57
|
+
customer.transaction do |conn|
|
58
|
+
conn.hset(customer.dbkey, 'name', 'Should Not Work')
|
59
|
+
end
|
60
|
+
false # Should not reach here
|
61
|
+
rescue Familia::OperationModeError => e
|
62
|
+
e.message.include?('Cannot start transaction with') && e.message.include?('CachedConnectionHandler')
|
63
|
+
ensure
|
64
|
+
# Clean up cached connection
|
65
|
+
TransactionModeTestCustomer.remove_instance_variable(:@dbclient)
|
66
|
+
end
|
67
|
+
#=> true
|
68
|
+
|
69
|
+
## Warn mode logs warning and executes individual commands
|
70
|
+
begin
|
71
|
+
Familia.configure { |config| config.transaction_mode = :warn }
|
72
|
+
|
73
|
+
# Force CachedConnectionHandler
|
74
|
+
TransactionModeTestCustomer.instance_variable_set(:@dbclient, Familia.create_dbclient)
|
75
|
+
|
76
|
+
customer = TransactionModeTestCustomer.new(custid: 'warn_test')
|
77
|
+
|
78
|
+
# Capture log output would be ideal, but test the core functionality
|
79
|
+
result = customer.transaction do |conn|
|
80
|
+
# This should be an IndividualCommandProxy
|
81
|
+
conn.class == Familia::Connection::IndividualCommandProxy &&
|
82
|
+
conn.hset(customer.dbkey, 'name', 'Warn Mode Works') &&
|
83
|
+
conn.hget(customer.dbkey, 'name')
|
84
|
+
end
|
85
|
+
|
86
|
+
# Should return MultiResult with individual command results
|
87
|
+
result.is_a?(MultiResult) && result.results.last == 'Warn Mode Works'
|
88
|
+
ensure
|
89
|
+
TransactionModeTestCustomer.remove_instance_variable(:@dbclient)
|
90
|
+
Familia.configure { |config| config.transaction_mode = :strict }
|
91
|
+
end
|
92
|
+
#=> true
|
93
|
+
|
94
|
+
## Permissive mode silently executes individual commands
|
95
|
+
begin
|
96
|
+
Familia.configure { |config| config.transaction_mode = :permissive }
|
97
|
+
|
98
|
+
# Force CachedConnectionHandler
|
99
|
+
TransactionModeTestCustomer.instance_variable_set(:@dbclient, Familia.create_dbclient)
|
100
|
+
|
101
|
+
customer = TransactionModeTestCustomer.new(custid: 'permissive_test')
|
102
|
+
|
103
|
+
result = customer.transaction do |conn|
|
104
|
+
# Should be IndividualCommandProxy
|
105
|
+
conn.class == Familia::Connection::IndividualCommandProxy &&
|
106
|
+
conn.hset(customer.dbkey, 'email', 'permissive@example.com') &&
|
107
|
+
conn.hget(customer.dbkey, 'email')
|
108
|
+
end
|
109
|
+
|
110
|
+
# Should return MultiResult
|
111
|
+
result.is_a?(MultiResult) && result.results.last == 'permissive@example.com'
|
112
|
+
ensure
|
113
|
+
TransactionModeTestCustomer.remove_instance_variable(:@dbclient)
|
114
|
+
Familia.configure { |config| config.transaction_mode = :strict }
|
115
|
+
end
|
116
|
+
#=> true
|
117
|
+
|
118
|
+
## Normal transactions still work with CreateConnectionHandler
|
119
|
+
begin
|
120
|
+
customer = TransactionModeTestCustomer.new(custid: 'normal_test')
|
121
|
+
|
122
|
+
result = customer.transaction do |conn|
|
123
|
+
# Should be Redis::MultiConnection for normal transactions
|
124
|
+
conn.class == Redis::MultiConnection &&
|
125
|
+
conn.hset(customer.dbkey, 'type', 'normal transaction') &&
|
126
|
+
conn.hget(customer.dbkey, 'type')
|
127
|
+
end
|
128
|
+
|
129
|
+
result.is_a?(MultiResult) && result.results.last == 'normal transaction'
|
130
|
+
end
|
131
|
+
#=> true
|
132
|
+
|
133
|
+
## IndividualCommandProxy collects results correctly
|
134
|
+
begin
|
135
|
+
Familia.configure { |config| config.transaction_mode = :permissive }
|
136
|
+
TransactionModeTestCustomer.instance_variable_set(:@dbclient, Familia.create_dbclient)
|
137
|
+
|
138
|
+
customer = TransactionModeTestCustomer.new(custid: 'proxy_test')
|
139
|
+
|
140
|
+
result = customer.transaction do |conn|
|
141
|
+
conn.hset(customer.dbkey, 'field1', 'value1')
|
142
|
+
conn.hget(customer.dbkey, 'field1')
|
143
|
+
end
|
144
|
+
|
145
|
+
# Check that results are collected and it's a MultiResult
|
146
|
+
result.is_a?(MultiResult) && result.results.size >= 2
|
147
|
+
ensure
|
148
|
+
TransactionModeTestCustomer.remove_instance_variable(:@dbclient)
|
149
|
+
Familia.configure { |config| config.transaction_mode = :strict }
|
150
|
+
end
|
151
|
+
#=> true
|
152
|
+
|
153
|
+
## MultiResult success detection works with individual commands
|
154
|
+
begin
|
155
|
+
Familia.configure { |config| config.transaction_mode = :permissive }
|
156
|
+
TransactionModeTestCustomer.instance_variable_set(:@dbclient, Familia.create_dbclient)
|
157
|
+
|
158
|
+
customer = TransactionModeTestCustomer.new(custid: 'success_test')
|
159
|
+
|
160
|
+
result = customer.transaction do |conn|
|
161
|
+
conn.hset(customer.dbkey, 'status', 'active') # Returns 1
|
162
|
+
end
|
163
|
+
|
164
|
+
# Should be successful since 1 is considered success
|
165
|
+
result.successful?
|
166
|
+
ensure
|
167
|
+
TransactionModeTestCustomer.remove_instance_variable(:@dbclient)
|
168
|
+
Familia.configure { |config| config.transaction_mode = :strict }
|
169
|
+
end
|
170
|
+
#=> true
|
171
|
+
|
172
|
+
## Global transaction methods also respect transaction modes
|
173
|
+
begin
|
174
|
+
Familia.configure { |config| config.transaction_mode = :permissive }
|
175
|
+
|
176
|
+
# Force a handler that doesn't support transactions
|
177
|
+
original_provider = Familia.connection_provider
|
178
|
+
test_connection = Familia.create_dbclient
|
179
|
+
Familia.connection_provider = ->(_uri) { test_connection }
|
180
|
+
|
181
|
+
# Global transaction should also fallback
|
182
|
+
result = Familia.transaction do |conn|
|
183
|
+
conn.set('global_test_key', 'global_test_value')
|
184
|
+
conn.get('global_test_key')
|
185
|
+
end
|
186
|
+
|
187
|
+
result.is_a?(MultiResult) && result.results.last == 'global_test_value'
|
188
|
+
ensure
|
189
|
+
Familia.connection_provider = original_provider
|
190
|
+
Familia.configure { |config| config.transaction_mode = :strict }
|
191
|
+
end
|
192
|
+
#=> true
|
193
|
+
|
194
|
+
## Transaction fallback preserves connection context
|
195
|
+
begin
|
196
|
+
Familia.configure { |config| config.transaction_mode = :permissive }
|
197
|
+
|
198
|
+
# Test with logical database setting
|
199
|
+
class DatabaseTestCustomer < Familia::Horreum
|
200
|
+
logical_database 5
|
201
|
+
identifier_field :custid
|
202
|
+
field :custid
|
203
|
+
end
|
204
|
+
|
205
|
+
DatabaseTestCustomer.instance_variable_set(:@dbclient, Familia.create_dbclient)
|
206
|
+
customer = DatabaseTestCustomer.new(custid: 'db_test')
|
207
|
+
|
208
|
+
result = customer.transaction do |conn|
|
209
|
+
# Commands should execute on the correct database
|
210
|
+
conn.set('db_test_key', 'db_test_value')
|
211
|
+
conn.get('db_test_key')
|
212
|
+
end
|
213
|
+
|
214
|
+
result.results.last == 'db_test_value'
|
215
|
+
ensure
|
216
|
+
DatabaseTestCustomer.remove_instance_variable(:@dbclient) if DatabaseTestCustomer.instance_variable_defined?(:@dbclient)
|
217
|
+
Familia.configure { |config| config.transaction_mode = :strict }
|
218
|
+
end
|
219
|
+
#=> true
|
220
|
+
|
221
|
+
## Transaction modes work with nested calls
|
222
|
+
begin
|
223
|
+
Familia.configure { |config| config.transaction_mode = :permissive }
|
224
|
+
TransactionModeTestCustomer.instance_variable_set(:@dbclient, Familia.create_dbclient)
|
225
|
+
|
226
|
+
customer = TransactionModeTestCustomer.new(custid: 'nested_test')
|
227
|
+
|
228
|
+
# Test that nested transactions work
|
229
|
+
outer_result = customer.transaction do |outer_conn|
|
230
|
+
outer_conn.hset(customer.dbkey, 'outer', 'value')
|
231
|
+
|
232
|
+
inner_result = customer.transaction do |inner_conn|
|
233
|
+
inner_conn.hset(customer.dbkey, 'inner', 'nested')
|
234
|
+
end
|
235
|
+
|
236
|
+
# Inner transaction should return MultiResult
|
237
|
+
inner_result.is_a?(MultiResult)
|
238
|
+
end
|
239
|
+
|
240
|
+
# Outer transaction should also return MultiResult
|
241
|
+
outer_result.is_a?(MultiResult)
|
242
|
+
ensure
|
243
|
+
TransactionModeTestCustomer.remove_instance_variable(:@dbclient)
|
244
|
+
Familia.configure { |config| config.transaction_mode = :strict }
|
245
|
+
end
|
246
|
+
#=> true
|
247
|
+
|
248
|
+
# Cleanup - restore original transaction mode
|
249
|
+
Familia.configure { |config| config.transaction_mode = @original_transaction_mode }
|
data/try/core/autoloader_try.rb
CHANGED
@@ -1,10 +1,30 @@
|
|
1
1
|
# try/core/autoloader_try.rb
|
2
2
|
|
3
|
+
# Tests for Familia::Features::Autoloader
|
4
|
+
#
|
5
|
+
# TESTING STRATEGY:
|
6
|
+
# Autoloading is inherently tricky to test because:
|
7
|
+
# 1. Files are loaded once and cached by Ruby's require system
|
8
|
+
# 2. We need to simulate different directory structures
|
9
|
+
# 3. We need to verify that files are actually loaded (not just found)
|
10
|
+
#
|
11
|
+
# SOLUTION:
|
12
|
+
# Use temporary directories with Dir.mktmpdir to create isolated test
|
13
|
+
# environments and write test files that set global variables when
|
14
|
+
# loaded ($test_feature_loaded = true). Globals are reset before each
|
15
|
+
# test and FileUtils.rm_rf to clean up temp directories after each test.
|
16
|
+
#
|
17
|
+
# This approach allows us to:
|
18
|
+
# - Test actual file loading behavior (not just glob patterns) that verify
|
19
|
+
# the directory patterns that autoloader.included generates and also the
|
20
|
+
# exclusion logic works correctly.
|
21
|
+
|
3
22
|
require_relative '../../lib/familia'
|
4
23
|
require 'fileutils'
|
5
24
|
require 'tmpdir'
|
6
25
|
|
7
|
-
# Create test directory structure for
|
26
|
+
# SETUP: Create test directory structure for basic autoloader testing
|
27
|
+
# This simulates the lib/familia/features/ directory structure
|
8
28
|
@test_dir = Dir.mktmpdir('familia_autoloader_test')
|
9
29
|
@features_dir = File.join(@test_dir, 'features')
|
10
30
|
@test_file1 = File.join(@features_dir, 'test_feature1.rb')
|
@@ -30,16 +50,16 @@ File.write(@excluded_file, <<~RUBY)
|
|
30
50
|
$autoloader_file_loaded = true
|
31
51
|
RUBY
|
32
52
|
|
33
|
-
## Test that Familia::Autoloader exists and is a module
|
34
|
-
Familia::Autoloader.is_a?(Module)
|
53
|
+
## Test that Familia::Features::Autoloader exists and is a module
|
54
|
+
Familia::Features::Autoloader.is_a?(Module)
|
35
55
|
#=> true
|
36
56
|
|
37
57
|
## Test that autoload_files class method exists
|
38
|
-
Familia::Autoloader.respond_to?(:autoload_files)
|
58
|
+
Familia::Features::Autoloader.respond_to?(:autoload_files)
|
39
59
|
#=> true
|
40
60
|
|
41
61
|
## Test that included class method exists
|
42
|
-
Familia::Autoloader.respond_to?(:included)
|
62
|
+
Familia::Features::Autoloader.respond_to?(:included)
|
43
63
|
#=> true
|
44
64
|
|
45
65
|
## Test autoload_files with single pattern
|
@@ -47,11 +67,12 @@ $test_feature1_loaded = false
|
|
47
67
|
$test_feature2_loaded = false
|
48
68
|
$autoloader_file_loaded = false
|
49
69
|
|
50
|
-
Familia::Autoloader.autoload_files(File.join(@features_dir, '*.rb'))
|
70
|
+
Familia::Features::Autoloader.autoload_files(File.join(@features_dir, '*.rb'))
|
51
71
|
$test_feature1_loaded && $test_feature2_loaded
|
52
72
|
#=> true
|
53
73
|
|
54
74
|
## Test that autoload_files respects exclusions (using fresh files)
|
75
|
+
# Create a separate test environment to avoid conflicts with cached requires
|
55
76
|
@exclude_test_dir = Dir.mktmpdir('familia_autoloader_exclude_test')
|
56
77
|
@exclude_features_dir = File.join(@exclude_test_dir, 'features')
|
57
78
|
@include_file = File.join(@exclude_features_dir, 'include_me.rb')
|
@@ -64,7 +85,7 @@ File.write(@exclude_file, '$exclude_me_loaded = true')
|
|
64
85
|
$include_me_loaded = false
|
65
86
|
$exclude_me_loaded = false
|
66
87
|
|
67
|
-
Familia::Autoloader.autoload_files(
|
88
|
+
Familia::Features::Autoloader.autoload_files(
|
68
89
|
File.join(@exclude_features_dir, '*.rb'),
|
69
90
|
exclude: ['autoloader.rb']
|
70
91
|
)
|
@@ -74,6 +95,7 @@ $include_me_loaded && !$exclude_me_loaded
|
|
74
95
|
#=> true
|
75
96
|
|
76
97
|
## Test autoload_files with array of patterns (using fresh files)
|
98
|
+
# Test that multiple glob patterns can be processed in a single call
|
77
99
|
@pattern_test_dir = Dir.mktmpdir('familia_autoloader_pattern_test')
|
78
100
|
@pattern_dir1 = File.join(@pattern_test_dir, 'dir1')
|
79
101
|
@pattern_dir2 = File.join(@pattern_test_dir, 'dir2')
|
@@ -88,7 +110,7 @@ File.write(@pattern_file2, '$pattern2_loaded = true')
|
|
88
110
|
$pattern1_loaded = false
|
89
111
|
$pattern2_loaded = false
|
90
112
|
|
91
|
-
Familia::Autoloader.autoload_files([
|
113
|
+
Familia::Features::Autoloader.autoload_files([
|
92
114
|
File.join(@pattern_dir1, '*.rb'),
|
93
115
|
File.join(@pattern_dir2, '*.rb')
|
94
116
|
])
|
@@ -99,14 +121,110 @@ $pattern1_loaded && $pattern2_loaded
|
|
99
121
|
## Test that included method loads features from features directory
|
100
122
|
# Create a mock module that includes Autoloader
|
101
123
|
@mock_features_module = Module.new do
|
102
|
-
include Familia::Autoloader
|
124
|
+
include Familia::Features::Autoloader
|
103
125
|
end
|
104
126
|
|
105
|
-
|
106
|
-
Familia::Features.ancestors.include?(Familia::Autoloader)
|
127
|
+
## The Features module already includes Autoloader, so test indirectly
|
128
|
+
Familia::Features.ancestors.include?(Familia::Features::Autoloader)
|
129
|
+
#=> true
|
130
|
+
|
131
|
+
## Test normalize_to_config_name method exists
|
132
|
+
# This method was added to fix issues with namespaced classes after commit d319d9d
|
133
|
+
# moved the namespace splitting logic from snake_case to config_name
|
134
|
+
Familia::Features::Autoloader.respond_to?(:normalize_to_config_name)
|
135
|
+
#=> true
|
136
|
+
|
137
|
+
## Test normalize_to_config_name with simple class name
|
138
|
+
Familia::Features::Autoloader.normalize_to_config_name('Customer')
|
139
|
+
#=> 'customer'
|
140
|
+
|
141
|
+
## Test normalize_to_config_name with PascalCase class name
|
142
|
+
Familia::Features::Autoloader.normalize_to_config_name('ApiTestUser')
|
143
|
+
#=> 'api_test_user'
|
144
|
+
|
145
|
+
## Test normalize_to_config_name with namespaced class name (single level)
|
146
|
+
Familia::Features::Autoloader.normalize_to_config_name('V2::Customer')
|
147
|
+
#=> 'customer'
|
148
|
+
|
149
|
+
## Test normalize_to_config_name with deeply namespaced class name
|
150
|
+
Familia::Features::Autoloader.normalize_to_config_name('My::Deep::Nested::Module::ApiTestUser')
|
151
|
+
#=> 'api_test_user'
|
152
|
+
|
153
|
+
## Test normalize_to_config_name with leading double colon
|
154
|
+
Familia::Features::Autoloader.normalize_to_config_name('::Customer')
|
155
|
+
#=> 'customer'
|
156
|
+
|
157
|
+
## Test normalize_to_config_name handles edge case with anonymous class representation
|
158
|
+
Familia::Features::Autoloader.normalize_to_config_name('#<Class:0x0001991a8>::ApiTestUser')
|
159
|
+
#=> 'api_test_user'
|
160
|
+
|
161
|
+
## Test that autoloader directory patterns work with namespaced classes
|
162
|
+
# This tests the core fix: ensuring that namespaced classes like TestNamespace::ApiTestModule
|
163
|
+
# correctly generate directory patterns using only the demodularized name (api_test_module)
|
164
|
+
# rather than the full namespaced name
|
165
|
+
# Create a test directory structure that simulates what would happen
|
166
|
+
# when a namespaced class includes the autoloader
|
167
|
+
@namespace_pattern_test_dir = Dir.mktmpdir('familia_autoloader_namespace_test')
|
168
|
+
@base_path = @namespace_pattern_test_dir
|
169
|
+
@config_name = 'api_test_module' # This would be the result of normalize_to_config_name
|
170
|
+
|
171
|
+
# Create directory structure for different patterns
|
172
|
+
@features_global_dir = File.join(@base_path, 'features')
|
173
|
+
@features_config_dir = File.join(@base_path, @config_name, 'features')
|
174
|
+
@features_file = File.join(@base_path, @config_name, 'features.rb')
|
175
|
+
|
176
|
+
FileUtils.mkdir_p(@features_global_dir)
|
177
|
+
FileUtils.mkdir_p(@features_config_dir)
|
178
|
+
|
179
|
+
# Write test files for each pattern
|
180
|
+
@global_feature = File.join(@features_global_dir, 'global_feature.rb')
|
181
|
+
@config_feature = File.join(@features_config_dir, 'config_feature.rb')
|
182
|
+
|
183
|
+
File.write(@global_feature, '$global_feature_loaded = true')
|
184
|
+
File.write(@config_feature, '$config_feature_loaded = true')
|
185
|
+
File.write(@features_file, '$features_file_loaded = true')
|
186
|
+
|
187
|
+
# These are the exact patterns that autoloader.included generates:
|
188
|
+
# 1. Global features dir: base_path/features/*.rb
|
189
|
+
# 2. Config-specific features dir: base_path/config_name/features/*.rb
|
190
|
+
# 3. Config-specific features file: base_path/config_name/features.rb
|
191
|
+
@dir_patterns = [
|
192
|
+
File.join(@base_path, 'features', '*.rb'),
|
193
|
+
File.join(@base_path, @config_name, 'features', '*.rb'),
|
194
|
+
File.join(@base_path, @config_name, 'features.rb'),
|
195
|
+
]
|
196
|
+
# Verify all three patterns are correctly constructed
|
197
|
+
@dir_patterns.length
|
198
|
+
#=> 3
|
199
|
+
|
200
|
+
# Reset test flags - critical for testing actual file loading behavior
|
201
|
+
$global_feature_loaded = false
|
202
|
+
$config_feature_loaded = false
|
203
|
+
$features_file_loaded = false
|
204
|
+
|
205
|
+
## Test that global features pattern matches correctly
|
206
|
+
Dir.glob(@dir_patterns[0]).length
|
207
|
+
#=> 1
|
208
|
+
|
209
|
+
## Test that config-specific features pattern matches correctly
|
210
|
+
Dir.glob(@dir_patterns[1]).length
|
211
|
+
#=> 1
|
212
|
+
|
213
|
+
## Test that config-specific features.rb file exists
|
214
|
+
File.exist?(@dir_patterns[2])
|
215
|
+
#=> true
|
216
|
+
|
217
|
+
## Test loading all patterns simulates autoloader.included behavior
|
218
|
+
# This simulates what happens when a class includes Familia::Features::Autoloader
|
219
|
+
# All three file patterns should be processed and their contents loaded
|
220
|
+
Familia::Features::Autoloader.autoload_files(@dir_patterns)
|
221
|
+
|
222
|
+
# Verify all three test files were actually loaded (not just found)
|
223
|
+
$global_feature_loaded && $config_feature_loaded && $features_file_loaded
|
107
224
|
#=> true
|
108
225
|
|
109
226
|
# Cleanup test files and directories
|
110
227
|
FileUtils.rm_rf(@test_dir)
|
111
228
|
FileUtils.rm_rf(@exclude_test_dir)
|
112
229
|
FileUtils.rm_rf(@pattern_test_dir)
|
230
|
+
FileUtils.rm_rf(@namespace_pattern_test_dir)
|
data/try/core/connection_try.rb
CHANGED
@@ -20,23 +20,23 @@ uri.host
|
|
20
20
|
#=> "localhost"
|
21
21
|
|
22
22
|
## Can establish Database connection
|
23
|
+
Familia.create_dbclient
|
24
|
+
#=:> Redis
|
25
|
+
|
26
|
+
## Can establish Database connection with deprecated method
|
23
27
|
Familia.connect
|
24
28
|
#=:> Redis
|
25
29
|
|
26
|
-
## Can
|
30
|
+
## Can create connection to different URI
|
27
31
|
## Doesn't confirm the logical DB number, dbclient.options raises an error?
|
28
32
|
test_uri = 'redis://localhost:6379/2'
|
29
|
-
Familia.
|
33
|
+
Familia.create_dbclient(test_uri)
|
30
34
|
#=:> Redis
|
31
35
|
|
32
36
|
## Database client responds to basic commands
|
33
37
|
Familia.dbclient.ping
|
34
38
|
#=> "PONG"
|
35
39
|
|
36
|
-
## Multiple connections are managed separately
|
37
|
-
Familia.database_clients.size >= 1
|
38
|
-
#=> true
|
39
|
-
|
40
40
|
## Can enable Database logging
|
41
41
|
Familia.enable_database_logging = true
|
42
42
|
Familia.enable_database_logging
|
@@ -48,7 +48,7 @@ Familia.enable_database_counter
|
|
48
48
|
#=> true
|
49
49
|
|
50
50
|
## Middleware gets registered when enabled
|
51
|
-
dbclient = Familia.
|
51
|
+
dbclient = Familia.create_dbclient('redis://localhost:6379/3')
|
52
52
|
dbclient.ping
|
53
53
|
#=> "PONG"
|
54
54
|
|