familia 2.0.0.pre16 → 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/.github/workflows/ci.yml +2 -2
- data/.github/workflows/{code-smellage.yml → code-smells.yml} +3 -63
- data/.gitignore +2 -0
- data/.rubocop.yml +6 -0
- data/CHANGELOG.rst +82 -0
- data/CLAUDE.md +47 -2
- data/Gemfile.lock +1 -1
- data/README.md +13 -0
- data/bin/irb +1 -1
- data/docs/archive/FAMILIA_TECHNICAL.md +1 -1
- data/docs/guides/core-field-system.md +48 -26
- data/docs/migrating/v2.0.0-pre18.md +58 -0
- data/docs/overview.md +2 -2
- data/docs/qodo-merge-compliance.md +96 -0
- data/docs/reference/api-technical.md +1 -1
- data/examples/encrypted_fields.rb +1 -1
- data/examples/safe_dump.rb +1 -1
- data/lib/familia/base.rb +6 -6
- data/lib/familia/connection/middleware.rb +58 -4
- data/lib/familia/connection.rb +1 -1
- data/lib/familia/data_type/class_methods.rb +63 -0
- data/lib/familia/data_type/connection.rb +83 -0
- 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/settings.rb +96 -0
- data/lib/familia/data_type/types/hashkey.rb +2 -1
- data/lib/familia/data_type/types/sorted_set.rb +113 -10
- data/lib/familia/data_type/types/stringkey.rb +0 -4
- data/lib/familia/data_type.rb +8 -195
- 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/encrypted_fields.rb +5 -2
- data/lib/familia/features/external_identifier.rb +49 -8
- data/lib/familia/features/object_identifier.rb +84 -12
- data/lib/familia/features/relationships/indexing/multi_index_generators.rb +9 -9
- data/lib/familia/features/relationships/indexing/unique_index_generators.rb +45 -26
- data/lib/familia/features/relationships/indexing.rb +7 -1
- data/lib/familia/features/relationships/participation/participant_methods.rb +6 -2
- data/lib/familia/features/safe_dump.rb +2 -3
- data/lib/familia/features/transient_fields.rb +7 -2
- data/lib/familia/features.rb +6 -1
- data/lib/familia/field_type.rb +0 -18
- data/lib/familia/horreum/{core/connection.rb → connection.rb} +21 -0
- data/lib/familia/horreum/{core/database_commands.rb → database_commands.rb} +1 -1
- data/lib/familia/horreum/{subclass/definition.rb → definition.rb} +102 -56
- data/lib/familia/horreum/{subclass/management.rb → management.rb} +18 -15
- data/lib/familia/horreum/{core/serialization.rb → persistence.rb} +73 -170
- data/lib/familia/horreum/{subclass/related_fields_management.rb → related_fields.rb} +22 -2
- data/lib/familia/horreum/serialization.rb +190 -0
- data/lib/familia/horreum.rb +39 -14
- 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/field_groups_try.rb +244 -0
- 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 +16 -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 +3 -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 +3 -3
- 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 +12 -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 +6 -6
- 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 +2 -2
- 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 +15 -7
- data/try/{memory → support/memory}/memory_docker_ruby_dump.sh +1 -1
- 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 +5 -5
- data/try/{core → unit/core}/errors_try.rb +4 -4
- 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 +2 -2
- 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 +3 -3
- 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/unit/data_types/sorted_set_zadd_options_try.rb +625 -0
- 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/unit/horreum/auto_indexing_on_save_try.rb +212 -0
- 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 +3 -1
- data/try/unit/horreum/defensive_initialization_try.rb +86 -0
- data/try/{horreum → unit/horreum}/destroy_related_fields_cleanup_try.rb +3 -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 +3 -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
- data/try/valkey.conf +26 -0
- metadata +149 -132
- data/lib/familia/distinguisher.rb +0 -85
- data/lib/familia/horreum/core.rb +0 -21
- data/lib/familia/refinements/logger_trace.rb +0 -60
- data/try/refinements/logger_trace_methods_try.rb +0 -44
- /data/lib/familia/horreum/{shared/settings.rb → settings.rb} +0 -0
- /data/lib/familia/horreum/{core/utils.rb → utils.rb} +0 -0
- /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_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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5bbf0ac2fc6a1243d74f679c7027040be00783af625dd90d376637e32417394
|
4
|
+
data.tar.gz: 4b354347a0c2403490dc20fdc12f93b3e71b826cf0b2b08638f6fd884a883630
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 221116e1aa14bc7114cb51164727587dcb0e8435dd8b85bb7d14618393ef446446376fd7febf6dbc9993098e2c819b3b0aa6f3c8bedce1c965b99ec4c8832a7b
|
7
|
+
data.tar.gz: 457b0e5bfef1f203c8f2edf934d1ee37915df04c49b0cb8b097ab9732738186ba9e8e92496851699f0952426971d2d3d244e61e594719439672996a0ccde2050
|
data/.github/workflows/ci.yml
CHANGED
@@ -35,8 +35,8 @@ jobs:
|
|
35
35
|
--health-retries 5
|
36
36
|
ports:
|
37
37
|
# https://docs.github.com/en/actions/using-containerized-services/creating-redis-service-containers#running-jobs-in-containers
|
38
|
-
# Maps port 6379 on service container to the host
|
39
|
-
-
|
38
|
+
# Maps port 6379 on service container to 2525 on the host
|
39
|
+
- 2525:6379
|
40
40
|
|
41
41
|
steps:
|
42
42
|
- uses: actions/checkout@v4
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# ..github/workflows/code-smells.yml
|
2
|
+
---
|
3
|
+
name: Code Smells
|
2
4
|
|
3
5
|
on:
|
4
6
|
pull_request:
|
@@ -81,65 +83,3 @@ jobs:
|
|
81
83
|
reek-report.html
|
82
84
|
if-no-files-found: ignore
|
83
85
|
retention-days: 30
|
84
|
-
|
85
|
-
# Add other code quality checks here
|
86
|
-
additional-quality-checks:
|
87
|
-
name: Additional Quality Checks
|
88
|
-
runs-on: ubuntu-24.04
|
89
|
-
timeout-minutes: 5
|
90
|
-
|
91
|
-
steps:
|
92
|
-
- name: Checkout code
|
93
|
-
uses: actions/checkout@v4
|
94
|
-
|
95
|
-
- name: Set up Ruby
|
96
|
-
uses: ruby/setup-ruby@v1
|
97
|
-
with:
|
98
|
-
ruby-version: 3.4
|
99
|
-
bundler-cache: true
|
100
|
-
|
101
|
-
- name: Configure Bundler for secure gem installation
|
102
|
-
run: |
|
103
|
-
bundle config set --local path 'vendor/bundle'
|
104
|
-
bundle config set --local deployment 'false'
|
105
|
-
|
106
|
-
- name: Install dependencies
|
107
|
-
run: bundle install --jobs 4 --retry 3
|
108
|
-
|
109
|
-
- name: Check for TODO/FIXME comments
|
110
|
-
run: |
|
111
|
-
echo "=== Scanning for TODO/FIXME comments ==="
|
112
|
-
echo "This helps track technical debt and action items."
|
113
|
-
echo ""
|
114
|
-
|
115
|
-
# Find TODO/FIXME comments (excluding this workflow file)
|
116
|
-
find . -name "*.rb" -not -path "./vendor/*" -not -path "./tmp/*" | \
|
117
|
-
xargs grep -Hn -i -E "(TODO|FIXME|HACK|XXX|NOTE):" 2>/dev/null | \
|
118
|
-
head -20 || echo "No TODO/FIXME comments found"
|
119
|
-
continue-on-error: true
|
120
|
-
|
121
|
-
- name: Check Ruby file syntax
|
122
|
-
run: |
|
123
|
-
echo "=== Checking Ruby syntax ==="
|
124
|
-
echo "Validates that all Ruby files have correct syntax."
|
125
|
-
echo ""
|
126
|
-
|
127
|
-
find . -name "*.rb" -not -path "./vendor/*" -not -path "./tmp/*" | \
|
128
|
-
while read -r file; do
|
129
|
-
if ! ruby -c "$file" > /dev/null 2>&1; then
|
130
|
-
echo "Syntax error in: $file"
|
131
|
-
ruby -c "$file"
|
132
|
-
fi
|
133
|
-
done
|
134
|
-
continue-on-error: true
|
135
|
-
|
136
|
-
- name: Check for long lines
|
137
|
-
run: |
|
138
|
-
echo "=== Checking for long lines (>120 characters) ==="
|
139
|
-
echo "Identifies potentially hard-to-read code lines."
|
140
|
-
echo ""
|
141
|
-
|
142
|
-
find . -name "*.rb" -not -path "./vendor/*" -not -path "./tmp/*" | \
|
143
|
-
xargs grep -Hn "^.\{121,\}$" | \
|
144
|
-
head -10 || echo "No overly long lines found"
|
145
|
-
continue-on-error: true
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -124,6 +124,9 @@ Style/NegatedIfElseCondition:
|
|
124
124
|
Naming/AsciiIdentifiers:
|
125
125
|
Enabled: false
|
126
126
|
|
127
|
+
Naming/PredicateMethod:
|
128
|
+
Enabled: false
|
129
|
+
|
127
130
|
Style/StringLiterals:
|
128
131
|
Enabled: true
|
129
132
|
EnforcedStyle: single_quotes
|
@@ -135,6 +138,9 @@ Style/FrozenStringLiteralComment:
|
|
135
138
|
Naming/MemoizedInstanceVariableName:
|
136
139
|
Enabled: false
|
137
140
|
|
141
|
+
ThreadSafety/ClassAndModuleAttributes:
|
142
|
+
Enabled: false
|
143
|
+
|
138
144
|
ThreadSafety/ClassInstanceVariable:
|
139
145
|
Enabled: false
|
140
146
|
|
data/CHANGELOG.rst
CHANGED
@@ -12,6 +12,88 @@ Versioning <https://semver.org/spec/v2.0.0.html>`__.
|
|
12
12
|
|
13
13
|
<!--scriv-insert-here-->
|
14
14
|
|
15
|
+
.. _changelog-2.0.0.pre18:
|
16
|
+
|
17
|
+
2.0.0.pre18 — 2025-10-05
|
18
|
+
========================
|
19
|
+
|
20
|
+
Added
|
21
|
+
-----
|
22
|
+
|
23
|
+
- Added ``Familia.reconnect!`` method to refresh connection pools with current middleware configuration. This solves issues in test suites where middleware (like DatabaseLogger) is enabled after connection pools are created. The method clears the connection chain, increments the middleware version, and clears fiber-local connections, ensuring new connections include the latest middleware. See ``lib/familia/connection/middleware.rb:81-117``.
|
24
|
+
|
25
|
+
Changed
|
26
|
+
-------
|
27
|
+
|
28
|
+
- **BREAKING**: Implemented type-preserving JSON serialization for Horreum field values. Non-string values (Integer, Boolean, Float, nil, Hash, Array) are JSON-encoded for storage and JSON-decoded on retrieval. **Strings are stored as-is without JSON encoding** to avoid double-quoting and maintain Redis baseline simplicity. Type preservation is achieved through smart deserialization: values that parse as JSON restore to their original types, otherwise remain as strings.
|
29
|
+
|
30
|
+
- **BREAKING**: Changed default Hash key format from symbols to strings throughout the codebase (``symbolize: false`` default). This eliminates ambiguity with HTTP request parameters and IndifferentHash-style implementations, providing strict adherence to JSON parsing rules and avoiding key duplication issues.
|
31
|
+
|
32
|
+
- **BREAKING**: Fixed ``initialize_with_keyword_args`` to properly handle ``false`` and ``0`` values during object initialization. Previously, falsy values were incorrectly skipped due to truthiness checks. Now uses explicit nil checking with ``fetch`` to preserve all non-nil values including ``false`` and ``0``.
|
33
|
+
|
34
|
+
- **String serialization now uses JSON encoding**: All string values are JSON-encoded during storage (wrapped in quotes) for consistent type preservation. The lenient deserializer handles both new JSON-encoded strings and legacy plain strings automatically. PR #152
|
35
|
+
|
36
|
+
Removed
|
37
|
+
-------
|
38
|
+
|
39
|
+
- **BREAKING**: Removed ``dump_method`` and ``load_method`` configuration options from ``Familia::Base`` and ``Familia::Horreum::Definition``. JSON serialization is now hard-coded for consistency and type safety. Custom serialization methods are no longer supported.
|
40
|
+
|
41
|
+
Fixed
|
42
|
+
-----
|
43
|
+
|
44
|
+
- Fixed type coercion bugs where Integer fields (e.g., ``age: 35``) became Strings (``"35"``) and Boolean fields (e.g., ``active: true``) became Strings (``"true"``) after database round-trips. All primitive types now maintain their original types through ``find_by_dbkey``, ``refresh!``, and ``batch_update`` operations.
|
45
|
+
|
46
|
+
- Fixed ``deserialize_value`` to return all JSON-parsed types instead of filtering to Hash/Array only. This enables proper deserialization of primitive types (Integer, Boolean, Float, String) from Redis storage.
|
47
|
+
|
48
|
+
- Added JSON deserialization in ``find_by_dbkey`` using existing ``initialize_with_keyword_args_deserialize_value`` helper method to maintain DRY principles and ensure loaded objects receive properly typed field values rather than raw Redis strings.
|
49
|
+
|
50
|
+
- Optimized serialization to avoid double-encoding strings - strings stored directly in Redis as-is, only non-string types use JSON encoding. This reduces storage overhead and maintains Redis's string baseline semantics.
|
51
|
+
|
52
|
+
- Fixed encrypted fields with ``category: :encrypted`` appearing in ``to_h()`` output. These fields now correctly set ``loggable: false`` to prevent accidental exposure in logs, APIs, or external interfaces. PR #152
|
53
|
+
|
54
|
+
- Fixed middleware registration to only set ``@middleware_registered`` flag when middleware is actually enabled and registered. Previously, calling ``create_dbclient`` before enabling middleware would set the flag to ``true`` without registering anything, preventing later middleware enablement from working. The fix ensures ``register_middleware_once`` only sets the flag after successful registration. See ``lib/familia/connection/middleware.rb:124-146``.
|
55
|
+
|
56
|
+
Security
|
57
|
+
--------
|
58
|
+
|
59
|
+
- Encrypted fields defined via ``field :name, category: :encrypted`` now properly excluded from ``to_h()`` serialization, matching the security behavior of ``encrypted_field``. PR #152
|
60
|
+
|
61
|
+
Documentation
|
62
|
+
-------------
|
63
|
+
|
64
|
+
- Added comprehensive type preservation test suite (``try/unit/horreum/json_type_preservation_try.rb``) with 30 test cases covering Integer, Boolean, String, Float, Hash, Array, nested structures, nil handling, empty strings, zero values, round-trip consistency, ``batch_update``, and ``refresh!`` operations.
|
65
|
+
|
66
|
+
AI Assistance
|
67
|
+
-------------
|
68
|
+
|
69
|
+
- Claude Code (claude-sonnet-4-5) provided implementation guidance, identified the ``initialize_with_keyword_args`` falsy value bug, wrote comprehensive test suite, and coordinated multi-file changes across serialization, management, and base modules.
|
70
|
+
|
71
|
+
- Issue analysis, implementation guidance, test verification, and documentation for JSON serialization changes and encrypted field security fix.
|
72
|
+
|
73
|
+
- Claude Code (Sonnet 4.5) provided architecture analysis, implementation design, and identified critical issues through the second-opinion agent. Key contributions included recommending the simplified approach without pool shutdown lifecycle management, identifying the race condition risk in clearing ``@middleware_registered``, and suggesting the use of natural pool aging instead of explicit shutdown.
|
74
|
+
|
75
|
+
.. _changelog-2.0.0.pre17:
|
76
|
+
|
77
|
+
2.0.0.pre17 — 2025-10-03
|
78
|
+
========================
|
79
|
+
|
80
|
+
Added
|
81
|
+
-----
|
82
|
+
|
83
|
+
- **SortedSet#add**: Full ZADD option support (NX, XX, GT, LT, CH) for atomic conditional operations and accurate change tracking. This enables proper index management with timestamp preservation, update-only operations, conditional score updates, and analytics tracking. Closes issue #135.
|
84
|
+
|
85
|
+
Fixed
|
86
|
+
-----
|
87
|
+
|
88
|
+
- Restored objid provenance tracking when loading objects from Redis. The ``ObjectIdentifier`` feature now infers the generator type (:uuid_v7, :uuid_v4, :hex) from the objid format, enabling dependent features like ``ExternalIdentifier`` to derive external identifiers from loaded objects. PR #131
|
89
|
+
|
90
|
+
AI Assistance
|
91
|
+
-------------
|
92
|
+
|
93
|
+
- Claude Code assisted with implementing the ``infer_objid_generator`` method and updating the setter logic in ``lib/familia/features/object_identifier.rb``.
|
94
|
+
|
95
|
+
- Claude Code assisted with Redis ZADD option semantics research, mutual exclusivity validation design, comprehensive test case matrix creation (50+ test cases), and YAML documentation examples.
|
96
|
+
|
15
97
|
.. _changelog-2.0.0.pre16:
|
16
98
|
|
17
99
|
2.0.0.pre16 — 2025-09-30
|
data/CLAUDE.md
CHANGED
@@ -92,6 +92,44 @@ Familia uses a modular feature system where features are mixed into classes:
|
|
92
92
|
|
93
93
|
**Inheritance Chain**: `MyClass < Familia::Horreum` automatically extends `ClassMethods` and `Features`
|
94
94
|
|
95
|
+
**Common Pitfall: Overriding initialize**
|
96
|
+
|
97
|
+
⚠️ **Do NOT override `initialize` without calling `super`** - this breaks related field initialization.
|
98
|
+
|
99
|
+
**Bad - will cause crashes:**
|
100
|
+
```ruby
|
101
|
+
class User < Familia::Horreum
|
102
|
+
def initialize(email)
|
103
|
+
@email = email # Missing super! Related fields won't work
|
104
|
+
end
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
**Good - use the `init` hook instead:**
|
109
|
+
```ruby
|
110
|
+
class User < Familia::Horreum
|
111
|
+
def init(email = nil)
|
112
|
+
@email = email # Called after super, related fields work
|
113
|
+
end
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
117
|
+
**Good - call super explicitly:**
|
118
|
+
```ruby
|
119
|
+
class User < Familia::Horreum
|
120
|
+
def initialize(email = nil, **kwargs)
|
121
|
+
super(**kwargs) # ✓ Related fields initialized
|
122
|
+
@email = email
|
123
|
+
end
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
**Why this matters**: Familia's `initialize` method calls `initialize_relatives` to set up DataType objects (lists, sets, etc.). Without calling `super`, these objects remain nil and you'll get helpful errors pointing to the missing super call.
|
128
|
+
|
129
|
+
**When to use each approach:**
|
130
|
+
- **Use `init` hook** (preferred): For simple initialization logic that doesn't need to intercept constructor arguments. The `init` method is called automatically after `super` with the same arguments passed to `new`.
|
131
|
+
- **Use explicit `super`**: When you need full control over initialization order or need to transform arguments before passing to parent. Remember to pass `**kwargs` to preserve keyword argument handling.
|
132
|
+
|
95
133
|
**DataType Definition**: Use class methods to define keystore database-backed attributes:
|
96
134
|
```ruby
|
97
135
|
class User < Familia::Horreum
|
@@ -116,8 +154,15 @@ end
|
|
116
154
|
|
117
155
|
### Important Implementation Notes
|
118
156
|
|
119
|
-
**Field Initialization**: Objects can be initialized with positional args (brittle) or keyword args (robust). Keyword args are recommended.
|
120
|
-
|
157
|
+
**Field Initialization**: Objects can be initialized with positional args (brittle) or keyword args (robust). Keyword args are recommended. All non-nil values including `false` and `0` are preserved during initialization.
|
158
|
+
|
159
|
+
**Serialization**: All field values are JSON-encoded for storage and JSON-decoded on retrieval to preserve Ruby types (Integer, Boolean, String, Float, Hash, Array, nil). This ensures type preservation across the Redis storage boundary. For example:
|
160
|
+
- `age: 35` (Integer) stores as `"35"` in Redis and loads back as Integer `35`
|
161
|
+
- `active: true` (Boolean) stores as `"true"` in Redis and loads back as Boolean `true`
|
162
|
+
- `metadata: {key: "value"}` (Hash) stores as JSON and loads back as Hash with proper types
|
163
|
+
|
121
164
|
**Database Key Generation**: Automatic key generation using class name, identifier, and field/type names (aka dbkey). Pattern: `classname:identifier:fieldname`
|
165
|
+
|
122
166
|
**Memory Efficiency**: Only non-nil values are stored in keystore database to optimize memory usage.
|
167
|
+
|
123
168
|
**Thread Safety**: Data types are frozen after instantiation to ensure immutability.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -438,6 +438,19 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
438
438
|
4. Push to the branch (`git push origin feature/amazing-feature`)
|
439
439
|
5. Open a Pull Request
|
440
440
|
|
441
|
+
### PR Compliance Checks
|
442
|
+
|
443
|
+
Pull requests are automatically reviewed by [Qodo Merge](https://qodo.ai) with compliance checks for:
|
444
|
+
- **Error Handling** - External API calls and database operations must have proper error handling
|
445
|
+
- **Test Coverage** - New features must include tests using the Tryouts framework
|
446
|
+
- **Changelog Fragments** - User-facing changes should include a changelog entry
|
447
|
+
- **Documentation** - API changes must update documentation
|
448
|
+
- **Backward Compatibility** - Breaking changes must be documented
|
449
|
+
- **Thread Safety** - Shared state must be properly synchronized
|
450
|
+
- **Database Key Naming** - Keys must follow Familia conventions
|
451
|
+
|
452
|
+
See [docs/qodo-merge-compliance.md](docs/qodo-merge-compliance.md) for details.
|
453
|
+
|
441
454
|
## License
|
442
455
|
|
443
456
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
data/bin/irb
CHANGED
@@ -722,7 +722,7 @@ require 'familia'
|
|
722
722
|
|
723
723
|
# Use separate Valkey/Redis database for tests
|
724
724
|
Familia.configure do |config|
|
725
|
-
config.redis_uri = ENV.fetch('REDIS_TEST_URI', 'redis://localhost:
|
725
|
+
config.redis_uri = ENV.fetch('REDIS_TEST_URI', 'redis://localhost:2525/3')
|
726
726
|
end
|
727
727
|
|
728
728
|
module TestHelpers
|
@@ -50,17 +50,20 @@ customer.email = "admin@acme.com" # Custom method name
|
|
50
50
|
customer.name!("Updated Corp") # Fast writer (immediate DB persistence)
|
51
51
|
```
|
52
52
|
|
53
|
-
### Field
|
53
|
+
### Special Field Types
|
54
54
|
|
55
|
-
|
55
|
+
Use dedicated field methods provided by features for special field behaviors:
|
56
56
|
|
57
57
|
```ruby
|
58
58
|
class Document < Familia::Horreum
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
field :
|
63
|
-
|
59
|
+
feature :encrypted_fields
|
60
|
+
feature :transient_fields
|
61
|
+
|
62
|
+
field :title # Regular persistent field
|
63
|
+
encrypted_field :content # Encrypted storage
|
64
|
+
transient_field :api_key # Non-persistent (memory only)
|
65
|
+
field :tags # Regular field
|
66
|
+
field :metadata # Regular field
|
64
67
|
end
|
65
68
|
```
|
66
69
|
|
@@ -285,27 +288,28 @@ order.priority_urgent? # => false
|
|
285
288
|
|
286
289
|
```ruby
|
287
290
|
class Product < Familia::Horreum
|
288
|
-
|
289
|
-
|
290
|
-
field :
|
291
|
-
field :
|
291
|
+
feature :transient_fields
|
292
|
+
|
293
|
+
field :name
|
294
|
+
field :price
|
295
|
+
field :description
|
292
296
|
transient_field :temp_data
|
293
297
|
end
|
294
298
|
|
295
299
|
# Get all field names
|
296
300
|
Product.fields
|
297
|
-
# => [:name, :price, :description, :
|
301
|
+
# => [:name, :price, :description, :temp_data]
|
298
302
|
|
299
303
|
# Get field types registry
|
300
304
|
Product.field_types
|
301
305
|
# => { name: #<FieldType...>, price: #<FieldType...>, ... }
|
302
306
|
|
303
|
-
# Get fields by category
|
304
|
-
Product.fields.select { |f| Product.field_types[f].category == :
|
305
|
-
# => [:
|
307
|
+
# Get fields by category (read-only introspection)
|
308
|
+
Product.fields.select { |f| Product.field_types[f].category == :transient }
|
309
|
+
# => [:temp_data]
|
306
310
|
|
307
311
|
# Get persistent vs transient fields
|
308
|
-
Product.persistent_fields # => [:name, :price, :description
|
312
|
+
Product.persistent_fields # => [:name, :price, :description]
|
309
313
|
Product.transient_fields # => [:temp_data]
|
310
314
|
|
311
315
|
# Field method mapping (for backward compatibility)
|
@@ -313,15 +317,24 @@ Product.field_method_map
|
|
313
317
|
# => { name: :name, price: :price, secret_key: :secret_key, temp_data: :temp_data }
|
314
318
|
```
|
315
319
|
|
316
|
-
### Field
|
320
|
+
### Using Field Type Category for Introspection
|
321
|
+
|
322
|
+
The `category` method on FieldType provides read-only metadata for introspection:
|
317
323
|
|
318
324
|
```ruby
|
319
|
-
#
|
325
|
+
# Custom field type with category metadata
|
326
|
+
class SearchableFieldType < Familia::FieldType
|
327
|
+
def category
|
328
|
+
:searchable
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
# Features can process fields by inspecting their category
|
320
333
|
module SearchableFieldsFeature
|
321
334
|
def self.included(base)
|
322
335
|
base.extend ClassMethods
|
323
336
|
|
324
|
-
#
|
337
|
+
# Find all searchable fields by inspecting field type category
|
325
338
|
searchable_fields = base.fields.select do |field|
|
326
339
|
base.field_types[field].category == :searchable
|
327
340
|
end
|
@@ -348,11 +361,17 @@ module SearchableFieldsFeature
|
|
348
361
|
end
|
349
362
|
|
350
363
|
class Product < Familia::Horreum
|
351
|
-
feature :searchable_fields
|
364
|
+
feature :searchable_fields
|
352
365
|
|
353
|
-
field
|
354
|
-
|
355
|
-
|
366
|
+
# Use custom field type with searchable category
|
367
|
+
def self.searchable_field(name, **options)
|
368
|
+
field_type = SearchableFieldType.new(name, **options)
|
369
|
+
register_field_type(field_type)
|
370
|
+
end
|
371
|
+
|
372
|
+
searchable_field :name
|
373
|
+
searchable_field :description
|
374
|
+
field :internal_id
|
356
375
|
end
|
357
376
|
|
358
377
|
# Auto-generated search methods available
|
@@ -733,10 +752,13 @@ end
|
|
733
752
|
### 1. Choose Appropriate Field Types
|
734
753
|
|
735
754
|
```ruby
|
736
|
-
# Use
|
755
|
+
# Use dedicated field methods provided by features
|
737
756
|
class User < Familia::Horreum
|
738
|
-
|
739
|
-
|
757
|
+
feature :transient_fields
|
758
|
+
feature :encrypted_fields
|
759
|
+
|
760
|
+
field :name # Simple persistent field
|
761
|
+
field :metadata # For complex data
|
740
762
|
transient_field :temp_token # For runtime-only data
|
741
763
|
encrypted_field :api_key # For sensitive data
|
742
764
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# Migrating Guide: v2.0.0-pre18
|
2
|
+
|
3
|
+
This version completes the JSON serialization implementation by removing the string-as-is optimization and fixes encrypted field visibility in serialization.
|
4
|
+
|
5
|
+
## JSON Serialization for All Types
|
6
|
+
|
7
|
+
**What Changed:**
|
8
|
+
|
9
|
+
All field values (including strings) are now JSON-encoded during storage for consistent type preservation.
|
10
|
+
|
11
|
+
**Storage Format:**
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
# Before (v2.0.0-pre14):
|
15
|
+
HGET user:123 name
|
16
|
+
"John Doe" # Plain string
|
17
|
+
|
18
|
+
# After (v2.0.0-pre18):
|
19
|
+
HGET user:123 name
|
20
|
+
"\"John Doe\"" # JSON-encoded string
|
21
|
+
```
|
22
|
+
|
23
|
+
**Migration:**
|
24
|
+
|
25
|
+
No migration needed. The deserializer automatically handles:
|
26
|
+
- **New format**: `"\"value\""` → `"value"`
|
27
|
+
- **Legacy format**: `"value"` → `"value"`
|
28
|
+
|
29
|
+
**Why This Matters:**
|
30
|
+
|
31
|
+
Prevents data corruption for edge cases:
|
32
|
+
- Badge `"007"` stays `"007"` (not converted to integer `7`)
|
33
|
+
- String `"true"` stays `"true"` (not converted to boolean)
|
34
|
+
- String `"null"` stays `"null"` (not converted to `nil`)
|
35
|
+
|
36
|
+
## Encrypted Field Security Fix
|
37
|
+
|
38
|
+
**What Changed:**
|
39
|
+
|
40
|
+
Fields defined with `category: :encrypted` now correctly exclude encrypted data from `to_h()` output.
|
41
|
+
|
42
|
+
**Before:**
|
43
|
+
```ruby
|
44
|
+
field :secret, category: :encrypted
|
45
|
+
user.to_h # => {"id" => "123", "secret" => {...}} # ❌ Exposed!
|
46
|
+
```
|
47
|
+
|
48
|
+
**After:**
|
49
|
+
```ruby
|
50
|
+
field :secret, category: :encrypted
|
51
|
+
user.to_h # => {"id" => "123"} # ✅ Secure
|
52
|
+
```
|
53
|
+
|
54
|
+
Both `encrypted_field` and `field :name, category: :encrypted` now behave identically for security.
|
55
|
+
|
56
|
+
**Migration:**
|
57
|
+
|
58
|
+
No code changes needed. Review any code relying on encrypted fields appearing in `to_h()` output.
|
data/docs/overview.md
CHANGED
@@ -708,7 +708,7 @@ when 'production'
|
|
708
708
|
when 'development'
|
709
709
|
Familia.uri = 'redis://localhost:6379/0'
|
710
710
|
when 'test'
|
711
|
-
Familia.uri = 'redis://localhost:
|
711
|
+
Familia.uri = 'redis://localhost:2525/3'
|
712
712
|
end
|
713
713
|
```
|
714
714
|
|
@@ -868,7 +868,7 @@ Familia.redis.keys('*') # List all keys (use carefully in production)
|
|
868
868
|
require 'familia'
|
869
869
|
|
870
870
|
# Use separate test database
|
871
|
-
Familia.uri = 'redis://localhost:
|
871
|
+
Familia.uri = 'redis://localhost:2525/3'
|
872
872
|
|
873
873
|
# Setup encryption for tests
|
874
874
|
test_keys = {
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# Qodo Merge Compliance Configuration
|
2
|
+
|
3
|
+
This document describes the Qodo Merge (formerly PR-Agent) configuration for the Familia project.
|
4
|
+
|
5
|
+
## Overview
|
6
|
+
|
7
|
+
Qodo Merge provides automated PR analysis, code reviews, and compliance checks. Our configuration enables two key compliance features:
|
8
|
+
|
9
|
+
1. **Codebase Duplication Compliance** - Uses RAG (Retrieval-Augmented Generation) to check for duplicate code across related repositories
|
10
|
+
2. **Custom Compliance** - Project-specific rules tailored to Familia's development practices
|
11
|
+
|
12
|
+
## Configuration Files
|
13
|
+
|
14
|
+
### pr_agent.toml
|
15
|
+
|
16
|
+
The main Qodo Merge configuration file located in the repository root. It includes:
|
17
|
+
|
18
|
+
- **Response Language**: Set to English for consistency
|
19
|
+
- **RAG Context Enrichment**: Enabled with related repositories (`delano/familia`, `delano/tryouts`, `delano/otto`)
|
20
|
+
- **Custom Compliance Path**: References our custom compliance checklist
|
21
|
+
- **Ignore Rules**: Excludes generated files and build artifacts from analysis
|
22
|
+
|
23
|
+
### pr_compliance_checklist.yaml
|
24
|
+
|
25
|
+
Custom compliance rules specific to Familia development:
|
26
|
+
|
27
|
+
#### ErrorHandling
|
28
|
+
All external API calls and database operations must have proper error handling with try-catch blocks or appropriate error handling mechanisms.
|
29
|
+
|
30
|
+
#### TestCoverage
|
31
|
+
New features must include tests using the Tryouts framework. Test files should be in the `try/` directory following the `*_try.rb` or `*.try.rb` naming convention.
|
32
|
+
|
33
|
+
#### ChangelogFragment
|
34
|
+
User-facing changes must include a changelog fragment in the `changelog.d/` directory following RST format, or provide explicit justification for omission.
|
35
|
+
|
36
|
+
#### DocumentationUpdates
|
37
|
+
API changes must be reflected in documentation, including YARD comments for new public methods or updates to the `docs/` directory.
|
38
|
+
|
39
|
+
#### BackwardCompatibility
|
40
|
+
Changes must maintain backward compatibility or document breaking changes in migration guides with deprecation warnings.
|
41
|
+
|
42
|
+
#### ThreadSafety
|
43
|
+
Code handling shared state must be thread-safe with proper synchronization or clear documentation of thread-safety assumptions.
|
44
|
+
|
45
|
+
#### DatabaseKeyNaming
|
46
|
+
Database key generation must follow Familia conventions:
|
47
|
+
- Use the configured `delim` separator (default `:`)
|
48
|
+
- Avoid reserved keywords: `ttl`, `db`, `valkey`, `redis`
|
49
|
+
- Handle empty identifiers to prevent stack overflow
|
50
|
+
|
51
|
+
## Interactive Commands
|
52
|
+
|
53
|
+
Team members can trigger on-demand Qodo Merge analysis in PR comments:
|
54
|
+
|
55
|
+
- `/analyze --review` - Run code review
|
56
|
+
- `/analyze --test` - Generate test suggestions
|
57
|
+
- `/improve` - Get improvement suggestions
|
58
|
+
- `/ask` - Ask questions about the PR
|
59
|
+
|
60
|
+
## Compliance Status
|
61
|
+
|
62
|
+
In PR comments from `@qodo-merge-pro`, you'll see:
|
63
|
+
|
64
|
+
- 🟢 Green circle - Compliance check passed
|
65
|
+
- 🔴 Red circle - Compliance check failed with details
|
66
|
+
- ⚪ White circle - Compliance check not configured (should not appear with proper configuration)
|
67
|
+
|
68
|
+
## References
|
69
|
+
|
70
|
+
- [Qodo Merge Configuration Options](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/)
|
71
|
+
- [RAG Context Enrichment Guide](https://qodo-merge-docs.qodo.ai/core-abilities/rag_context_enrichment/)
|
72
|
+
- [Compliance Guide](https://qodo-merge-docs.qodo.ai/tools/compliance/)
|
73
|
+
- [Best Practices](https://docs.qodo.ai/qodo-documentation/qodo-merge/features/best-practices)
|
74
|
+
|
75
|
+
## Maintenance
|
76
|
+
|
77
|
+
### Updating Compliance Rules
|
78
|
+
|
79
|
+
To add or modify compliance rules:
|
80
|
+
|
81
|
+
1. Edit `pr_compliance_checklist.yaml`
|
82
|
+
2. Ensure YAML syntax is valid: `ruby -r yaml -e "YAML.load_file('pr_compliance_checklist.yaml')"`
|
83
|
+
3. Commit changes - they take effect immediately on new PRs
|
84
|
+
|
85
|
+
### Updating Ignore Rules
|
86
|
+
|
87
|
+
To exclude additional files from analysis:
|
88
|
+
|
89
|
+
1. Edit the `[ignore]` section in `pr_agent.toml`
|
90
|
+
2. Use glob patterns to match file paths
|
91
|
+
3. Test with new PRs to verify exclusions work as expected
|
92
|
+
|
93
|
+
## Future Improvements (Optional)
|
94
|
+
|
95
|
+
- **Centralized Configuration**: Create a `pr-agent-settings` repository with `metadata.yaml` to share configuration across all repos
|
96
|
+
- **Wiki Configuration**: Enable repo wiki and create `.pr_agent.toml` page (wiki config takes precedence over local files)
|
@@ -1167,7 +1167,7 @@ require 'familia'
|
|
1167
1167
|
|
1168
1168
|
# Use separate Valkey/Redis database for tests
|
1169
1169
|
Familia.configure do |config|
|
1170
|
-
config.redis_uri = ENV.fetch('REDIS_TEST_URI', 'redis://localhost:
|
1170
|
+
config.redis_uri = ENV.fetch('REDIS_TEST_URI', 'redis://localhost:2525/3')
|
1171
1171
|
end
|
1172
1172
|
|
1173
1173
|
module TestHelpers
|
data/examples/safe_dump.rb
CHANGED