familia 2.11.2 → 2.13.0
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/claude-code-review.yml +16 -11
- data/.github/workflows/claude.yml +9 -25
- data/.github/workflows/code-smells.yml +1 -1
- data/.github/workflows/release-gem.yml +1 -1
- data/.github/workflows/yardoc.yml +1 -1
- data/.gitignore +9 -2
- data/.talismanrc +13 -0
- data/AGENTS.md +28 -0
- data/CHANGELOG.rst +84 -92
- data/Gemfile +2 -2
- data/Gemfile.lock +16 -19
- data/README.md +14 -3
- data/changelog.d/README.md +46 -54
- data/changelog.d/fragments/20260901_221800_delano_find_by_id_legacy_string.rst +17 -0
- data/changelog.d/fragments/20260902_043148_delano_406_valid_debug_log.md +7 -0
- data/changelog.d/fragments/20260902_043513_delano_407_deserialization_log_redaction.md +7 -0
- data/changelog.d/fragments/20260902_120000_delano_405_envelope_provenance.rst +32 -0
- data/changelog.d/fragments/20260902_130000_delano_408_envelope_encoding_validation.rst +26 -0
- data/changelog.d/fragments/20260904_120000_delano_security_audit_anchors.rst +4 -0
- data/changelog.d/fragments/20260904_150000_delano_encryption_identifier_precondition.rst +6 -0
- data/changelog.d/fragments/20260904_160000_delano_rebuild_via_scan_failure.rst +4 -0
- data/changelog.d/fragments/20260905_000000_delano_external_identifier_format_validation.rst +4 -0
- data/changelog.d/fragments/20260905_000500_delano_concurrent_rebuild_temp_key.rst +78 -0
- data/changelog.d/fragments/20260905_111500_delano_identifier_secret_env.rst +16 -0
- data/changelog.d/fragments/20260905_213000_delano_related_field_lifecycle.rst +104 -0
- data/changelog.d/fragments/20260906_203000_delano_unique_index_rebuild_fallback.rst +10 -0
- data/docs/adr/0001-record-architecture-decisions.md +20 -0
- data/docs/adr/0002-watch-for-private-keys-lua-for-shared-keys.md +62 -0
- data/docs/adr/README.md +14 -0
- data/docs/guides/datatype-collections.md +157 -1
- data/docs/guides/encryption.md +42 -7
- data/docs/guides/feature-encrypted-fields.md +25 -0
- data/docs/guides/feature-external-identifiers.md +4 -0
- data/docs/guides/feature-housekeeping.md +50 -1
- data/docs/guides/feature-relationships-indexing.md +306 -3
- data/docs/guides/feature-relationships-participation.md +14 -0
- data/docs/guides/index.md +10 -7
- data/docs/guides/schema-validation.md +199 -0
- data/docs/investigation/memory-audit.md +39 -0
- data/docs/investigation/rebuild-memory-incident.md +136 -0
- data/docs/investigation/v2-passphrase-not-bound-to-ciphertext.md +163 -0
- data/docs/migrating/identifier-secret.md +36 -0
- data/docs/migrating/v2.10.md +14 -0
- data/docs/overview.md +120 -37
- data/docs/reference/api-technical.md +91 -20
- data/docs/reference/migrations-specification.md +703 -0
- data/docs/reference/transaction_safety.md +215 -0
- data/docs/security/2026-07-19-audit.md +123 -0
- data/docs/security/2026-07-26-audit.md +113 -0
- data/docs/security/2026-07-30-audit.md +61 -0
- data/docs/security/2026-08-06-audit.md +110 -0
- data/docs/security/2026-09-04-audit.md +106 -0
- data/docs/security/README.md +25 -0
- data/examples/encryption_upgrade_proof/README.md +14 -8
- data/examples/encryption_upgrade_proof/gemfiles/Gemfile.dev-no-libsodium +1 -0
- data/examples/encryption_upgrade_proof/gemfiles/Gemfile.dev-with-libsodium +1 -0
- data/examples/encryption_upgrade_proof/gemfiles/Gemfile.production-today +1 -0
- data/examples/encryption_upgrade_proof/phase1_gem_upgrade_no_libsodium.rb +4 -1
- data/examples/encryption_upgrade_proof/phase2_libsodium_enabled.rb +33 -14
- data/examples/encryption_upgrade_proof/phase3_rollback_hazard.rb +1 -1
- data/familia.gemspec +0 -2
- data/lib/familia/atomic_operations.rb +399 -36
- data/lib/familia/connection/middleware.rb +4 -2
- data/lib/familia/connection/operations.rb +18 -2
- data/lib/familia/connection/transaction_core.rb +1 -1
- data/lib/familia/connection.rb +49 -3
- data/lib/familia/data_type/class_methods.rb +33 -0
- data/lib/familia/data_type/collection_base.rb +55 -7
- data/lib/familia/data_type/types/hashkey.rb +150 -0
- data/lib/familia/data_type/types/listkey.rb +89 -18
- data/lib/familia/data_type/types/lock.rb +34 -6
- data/lib/familia/data_type/types/sorted_set.rb +87 -22
- data/lib/familia/data_type.rb +105 -8
- data/lib/familia/encryption/encrypted_data.rb +34 -4
- data/lib/familia/encryption/manager.rb +135 -73
- data/lib/familia/encryption/provider.rb +7 -0
- data/lib/familia/encryption/providers/aes_gcm_provider.rb +3 -2
- data/lib/familia/encryption/providers/blake2b_personalization.rb +101 -0
- data/lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb +24 -13
- data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +21 -12
- data/lib/familia/encryption/stored_envelope.rb +28 -0
- data/lib/familia/encryption.rb +1 -0
- data/lib/familia/errors.rb +71 -1
- data/lib/familia/features/encrypted_fields/concealed_string.rb +14 -15
- data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +66 -14
- data/lib/familia/features/encrypted_fields.rb +5 -3
- data/lib/familia/features/expiration.rb +5 -4
- data/lib/familia/features/external_identifier.rb +24 -10
- data/lib/familia/features/housekeeping/enforce_collection_caps.rb +94 -0
- data/lib/familia/features/housekeeping.rb +20 -9
- data/lib/familia/features/relationships/collection_operations.rb +87 -6
- data/lib/familia/features/relationships/indexing/multi_index_generators.rb +49 -8
- data/lib/familia/features/relationships/indexing/rebuild_strategies.rb +110 -98
- data/lib/familia/features/relationships/indexing/unique_index_generators.rb +243 -47
- data/lib/familia/features/relationships/indexing.rb +483 -15
- data/lib/familia/features/relationships/participation/target_methods.rb +194 -21
- data/lib/familia/features/relationships/participation.rb +17 -5
- data/lib/familia/features/relationships/participation_relationship.rb +1 -0
- data/lib/familia/features/relationships/score_encoding.rb +109 -28
- data/lib/familia/features/relationships.rb +22 -40
- data/lib/familia/features/transient_fields/single_use_redacted_string.rb +9 -3
- data/lib/familia/features/transient_fields.rb +1 -0
- data/lib/familia/field_type.rb +214 -11
- data/lib/familia/horreum/atomic_write.rb +19 -1
- data/lib/familia/horreum/database_commands.rb +21 -3
- data/lib/familia/horreum/definition.rb +76 -111
- data/lib/familia/horreum/management/repair.rb +24 -62
- data/lib/familia/horreum/management.rb +3 -2
- data/lib/familia/horreum/persistence.rb +910 -119
- data/lib/familia/horreum/related_fields.rb +213 -13
- data/lib/familia/horreum/serialization.rb +39 -12
- data/lib/familia/horreum.rb +123 -45
- data/lib/familia/multi_result.rb +115 -21
- data/lib/familia/settings.rb +47 -14
- data/lib/familia/thread_safety/instrumented_mutex.rb +5 -2
- data/lib/familia/verifiable_identifier.rb +60 -25
- data/lib/familia/version.rb +1 -1
- data/lib/middleware/database_logger.rb +54 -7
- data/try/bug_fixes/overview_permission_example_try.rb +62 -0
- data/try/bug_fixes/partial_write_index_maintenance_try.rb +492 -0
- data/try/bug_fixes/permission_query_try.rb +151 -0
- data/try/bug_fixes/relationships_rdoc_example_try.rb +83 -0
- data/try/bug_fixes/stale_unique_index_try.rb +124 -0
- data/try/edge_cases/fast_writer_transaction_guard_try.rb +2 -4
- data/try/edge_cases/legacy_data_detection/deserialization_edge_cases_try.rb +2 -1
- data/try/edge_cases/legacy_data_detection/deserialization_log_redaction_try.rb +144 -0
- data/try/edge_cases/legacy_data_detection/find_by_id_legacy_string_try.rb +76 -0
- data/try/features/atomic_write_coverage_try.rb +2 -4
- data/try/features/dirty_tracking_try.rb +2 -4
- data/try/features/dirty_write_new_object_try.rb +22 -1
- data/try/features/dirty_write_warnings_try.rb +2 -1
- data/try/features/encrypted_fields/aad_nil_fields_try.rb +4 -6
- data/try/features/encrypted_fields/aad_protection_try.rb +4 -6
- data/try/features/encrypted_fields/aad_roundtrip_try.rb +4 -6
- data/try/features/encrypted_fields/aad_transient_fix_try.rb +4 -6
- data/try/features/encrypted_fields/aad_transient_proof_try.rb +4 -6
- data/try/features/encrypted_fields/concealed_string_core_try.rb +8 -6
- data/try/features/encrypted_fields/context_isolation_try.rb +2 -4
- data/try/features/encrypted_fields/encrypted_data_try.rb +2 -4
- data/try/features/encrypted_fields/encrypted_fields_core_try.rb +42 -1
- data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +17 -0
- data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +2 -4
- data/try/features/encrypted_fields/encrypted_fields_security_try.rb +6 -0
- data/try/features/encrypted_fields/envelope_provenance_try.rb +151 -0
- data/try/features/encrypted_fields/envelope_version_branching_try.rb +4 -6
- data/try/features/encrypted_fields/envelope_version_try.rb +4 -6
- data/try/features/encrypted_fields/error_conditions_try.rb +2 -4
- data/try/features/encrypted_fields/fast_writer_try.rb +4 -6
- data/try/features/encrypted_fields/fresh_key_derivation_try.rb +2 -4
- data/try/features/encrypted_fields/fresh_key_try.rb +4 -2
- data/try/features/encrypted_fields/identifier_precondition_try.rb +80 -0
- data/try/features/encrypted_fields/key_material_try.rb +4 -6
- data/try/features/encrypted_fields/key_rotation_try.rb +6 -7
- data/try/features/encrypted_fields/memory_security_try.rb +5 -5
- data/try/features/encrypted_fields/nonce_uniqueness_try.rb +2 -4
- data/try/features/encrypted_fields/per_field_algorithm_try.rb +5 -2
- data/try/features/encrypted_fields/re_encrypt_fields_try.rb +11 -19
- data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +5 -5
- data/try/features/encrypted_fields/thread_safety_try.rb +2 -4
- data/try/features/encrypted_fields/universal_serialization_safety_try.rb +5 -5
- data/try/features/encryption/aes_gcm_salt_rotation_try.rb +24 -5
- data/try/features/encryption/algorithm_upgrade_try.rb +12 -10
- data/try/features/encryption/config_persistence_try.rb +42 -5
- data/try/features/encryption/core_try.rb +4 -1
- data/try/features/encryption/encoding_phase1_try.rb +4 -1
- data/try/features/encryption/encoding_phase2_try.rb +4 -1
- data/try/features/encryption/encrypted_data_valid_logging_try.rb +145 -0
- data/try/features/encryption/envelope_encoding_validation_try.rb +135 -0
- data/try/features/encryption/instance_variable_scope_try.rb +5 -4
- data/try/features/encryption/module_loading_try.rb +7 -5
- data/try/features/encryption/providers/xchacha20_poly1305_provider_try.rb +51 -3
- data/try/features/encryption/request_cache_try.rb +4 -7
- data/try/features/encryption/roundtrip_validation_try.rb +3 -0
- data/try/features/encryption/secure_memory_handling_try.rb +76 -5
- data/try/features/encryption/xchacha20_personalization_rotation_try.rb +230 -0
- data/try/features/expiration/long_ttl_try.rb +196 -0
- data/try/features/external_identifier/external_identifier_try.rb +24 -5
- data/try/features/housekeeping/enforce_collection_caps_try.rb +136 -0
- data/try/features/housekeeping/housekeeping_try.rb +2 -2
- data/try/features/instance_registry_try.rb +6 -14
- data/try/features/real_feature_integration_try.rb +8 -0
- data/try/features/relationships/class_level_multi_index_try.rb +30 -0
- data/try/features/relationships/indexing_commands_verification_try.rb +19 -0
- data/try/features/relationships/indexing_rebuild_try.rb +60 -0
- data/try/features/relationships/rebuild_via_scan_try.rb +102 -0
- data/try/features/relationships/relationships_edge_cases_try.rb +3 -5
- data/try/features/relationships/score_encoding_permissions_try.rb +245 -0
- data/try/features/relationships/unique_index_cas_try.rb +546 -0
- data/try/features/relationships/unique_index_fallback_try.rb +132 -0
- data/try/features/transient_fields/refresh_reset_try.rb +4 -1
- data/try/features/transient_fields/single_use_redacted_string_try.rb +34 -0
- data/try/integration/connection/isolated_dbclient_try.rb +34 -22
- data/try/integration/connection/middleware_reconnect_try.rb +3 -3
- data/try/integration/connection/pools_try.rb +22 -13
- data/try/integration/familia_extended_try.rb +1 -1
- data/try/integration/persistence_operations_try.rb +2 -4
- data/try/integration/save_methods_consistency_try.rb +52 -6
- data/try/integration/verifiable_identifier_try.rb +255 -0
- data/try/investigation/memory_leak_proof.rb +20 -13
- data/try/investigation/pipeline_routing/CONCLUSION.md +149 -0
- data/try/investigation/pipeline_routing/FINDINGS.md +168 -0
- data/try/performance/transaction_safety_benchmark_try.rb +51 -27
- data/try/support/debugging/debug_aad_process.rb +2 -2
- data/try/{features/transient_fields → support/debugging}/simple_refresh_test.rb +2 -2
- data/try/support/encryption_config_helper_try.rb +114 -0
- data/try/support/helpers/encryption_config.rb +169 -0
- data/try/support/helpers/test_helpers.rb +47 -0
- data/try/support/prototypes/pooling/docs/README_advanced_usage.md +636 -0
- data/try/support/prototypes/pooling/docs/README_stress_testing.md +200 -0
- data/try/thread_safety/encryption_manager_cache_race_try.rb +2 -4
- data/try/thread_safety/instrumented_mutex_exclusion_try.rb +88 -0
- data/try/unit/atomic_operations_try.rb +487 -3
- data/try/unit/core/suite_hygiene_try.rb +32 -0
- data/try/unit/core/tools_try.rb +4 -2
- data/try/unit/data_types/enumerable_consistency/large_scale_consistency_try.rb +14 -3
- data/try/unit/data_types/lock_try.rb +44 -3
- data/try/unit/data_types/max_length_try.rb +607 -0
- data/try/unit/horreum/automatic_index_validation_try.rb +89 -2
- data/try/unit/horreum/commands_try.rb +85 -0
- data/try/unit/horreum/destroy_index_cleanup_try.rb +714 -22
- data/try/unit/horreum/multi_field_update_try.rb +154 -1
- data/try/unit/horreum/related_field_inheritance_snapshot_try.rb +122 -0
- data/try/unit/horreum/related_field_lifecycle_try.rb +1109 -0
- data/try/unit/horreum/serialization_try.rb +2 -2
- data/try/unit/horreum/unique_index_edge_cases_try.rb +46 -7
- data/try/unit/horreum/unique_index_guard_validation_try.rb +2 -0
- data/try/unit/middleware/database_logger_methods_try.rb +39 -0
- data/try/unit/multi_result_try.rb +298 -0
- data/try/unit/thread_safety_monitor_try.rb +20 -12
- metadata +62 -38
- data/docs/qodo-merge-compliance.md +0 -96
- /data/docs/{1106-participates_in-bidirectional-solution.md → investigation/participates_in-bidirectional-solution.md} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 889cca334ccb762d4a5cb4fa64a400c3df8727a8219bf19129b6699bf4056069
|
|
4
|
+
data.tar.gz: c2e315e109a866d8b1943be21fb7cf215c3db767e801138fa4097229e98c5dcb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d7e65ba3aa75c03d7c0328a34f7c6ad13f9c840efc2aefbe0c06bba678a41ac27704928962b5d9a3be769bd7df186bf1bc56647ee80aa173a1000ff6404d599e
|
|
7
|
+
data.tar.gz: e34f5200cac7681ff999b31cf842d326e49882ffd823602d8d677bec95b6376edca29f967f9da494eb431f9a857bc81758519dd4fd5969714ed478bd085cdf54
|
|
@@ -48,7 +48,7 @@ jobs:
|
|
|
48
48
|
|
|
49
49
|
- name: Run Claude Code Review
|
|
50
50
|
id: claude-review
|
|
51
|
-
uses: anthropics/claude-code-action@
|
|
51
|
+
uses: anthropics/claude-code-action@833fb0f8c9f6686b33d963a8bae0a94f4936ab2a # v1.0.211
|
|
52
52
|
with:
|
|
53
53
|
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
54
54
|
|
|
@@ -56,13 +56,24 @@ jobs:
|
|
|
56
56
|
# runs) -> the CLAUDE_MODEL repo variable -> this built-in default.
|
|
57
57
|
# Pinning a current id avoids the action's frozen default, which 404s
|
|
58
58
|
# ("model: claude-sonnet-4-20250514"). Fall back to Sonnet on overload.
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
# v1 of the action dropped the model/fallback_model/allowed_tools
|
|
60
|
+
# inputs; they are CLI flags passed via claude_args now (see
|
|
61
|
+
# docs/migration-guide.md and docs/usage.md in the action repo).
|
|
62
|
+
claude_args: |
|
|
63
|
+
--model ${{ inputs.model || vars.CLAUDE_MODEL || 'claude-opus-4-6' }}
|
|
64
|
+
--fallback-model ${{ vars.CLAUDE_FALLBACK_MODEL || 'claude-sonnet-4-6' }}
|
|
65
|
+
--allowedTools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"
|
|
61
66
|
|
|
62
|
-
#
|
|
67
|
+
# A bare `prompt` puts the action in agent mode, which creates no tracking
|
|
68
|
+
# comment, so use_sticky_comment alone did nothing and every push got a
|
|
69
|
+
# fresh `gh pr comment`. track_progress forces tag mode: the action owns
|
|
70
|
+
# one tracking comment, use_sticky_comment finds and reuses it on later
|
|
71
|
+
# pushes, and Claude writes the review into it via the action's built-in
|
|
72
|
+
# comment tool. The prompt becomes <custom_instructions> in tag mode.
|
|
73
|
+
track_progress: true
|
|
63
74
|
use_sticky_comment: true
|
|
64
75
|
|
|
65
|
-
|
|
76
|
+
prompt: |
|
|
66
77
|
Please review this pull request and provide feedback on:
|
|
67
78
|
- Code quality and best practices
|
|
68
79
|
- Potential bugs or issues
|
|
@@ -71,9 +82,3 @@ jobs:
|
|
|
71
82
|
- Test coverage
|
|
72
83
|
|
|
73
84
|
Use the repository's AGENTS.md for guidance on style and conventions. Be constructive and helpful in your feedback.
|
|
74
|
-
|
|
75
|
-
Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
|
|
76
|
-
|
|
77
|
-
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
|
78
|
-
# or https://docs.anthropic.com/en/docs/claude-code/sdk#command-line for available options
|
|
79
|
-
allowed_tools: "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"
|
|
@@ -32,47 +32,31 @@ jobs:
|
|
|
32
32
|
|
|
33
33
|
- name: Run Claude Code
|
|
34
34
|
id: claude
|
|
35
|
-
uses: anthropics/claude-code-action@
|
|
35
|
+
uses: anthropics/claude-code-action@833fb0f8c9f6686b33d963a8bae0a94f4936ab2a # v1.0.211
|
|
36
36
|
with:
|
|
37
37
|
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
38
38
|
|
|
39
39
|
# Primary model: set the CLAUDE_MODEL repo variable to override without
|
|
40
40
|
# editing this file. Pinning a current id avoids the action's frozen
|
|
41
41
|
# default, which 404s ("model: claude-sonnet-4-20250514"). Fall back to
|
|
42
|
-
# Sonnet if the primary is unavailable or overloaded.
|
|
43
|
-
model
|
|
44
|
-
|
|
42
|
+
# Sonnet if the primary is unavailable or overloaded. v1 of the action
|
|
43
|
+
# dropped the model/fallback_model inputs; models are CLI flags passed
|
|
44
|
+
# via claude_args (see docs/migration-guide.md in the action repo).
|
|
45
|
+
# Other supported flags (--allowedTools, --max-turns, ...):
|
|
46
|
+
# https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
|
47
|
+
claude_args: |
|
|
48
|
+
--model ${{ vars.CLAUDE_MODEL || 'claude-opus-4-6' }}
|
|
49
|
+
--fallback-model ${{ vars.CLAUDE_FALLBACK_MODEL || 'claude-sonnet-4-6' }}
|
|
45
50
|
|
|
46
51
|
# This is an optional setting that allows Claude to read CI results on PRs
|
|
47
52
|
additional_permissions: |
|
|
48
53
|
actions: read
|
|
49
54
|
|
|
50
|
-
# Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4)
|
|
51
|
-
# model: "claude-opus-4-20250514"
|
|
52
|
-
|
|
53
55
|
# Optional: Customize the trigger phrase (default: @claude)
|
|
54
56
|
# trigger_phrase: "/claude"
|
|
55
57
|
|
|
56
58
|
# Optional: Trigger when specific user is assigned to an issue
|
|
57
59
|
# assignee_trigger: "claude-bot"
|
|
58
60
|
|
|
59
|
-
# Optional: Allow Claude to run specific commands
|
|
60
|
-
# allowed_tools: "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)"
|
|
61
|
-
|
|
62
|
-
# Optional: Add custom instructions for Claude to customize its behavior for your project
|
|
63
|
-
# custom_instructions: |
|
|
64
|
-
# Follow our coding standards
|
|
65
|
-
# Ensure all new code has tests
|
|
66
|
-
# Use TypeScript for new files
|
|
67
|
-
|
|
68
|
-
# Optional: Custom environment variables for Claude
|
|
69
|
-
# claude_env: |
|
|
70
|
-
# NODE_ENV: test
|
|
71
|
-
|
|
72
61
|
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
|
|
73
62
|
# prompt: 'Update the pull request description to include a summary of changes.'
|
|
74
|
-
|
|
75
|
-
# Optional: Add claude_args to customize behavior and configuration
|
|
76
|
-
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
|
77
|
-
# or https://docs.anthropic.com/en/docs/claude-code/sdk#command-line for available options
|
|
78
|
-
# claude_args: '--model claude-opus-4-1-20250805 --allowed-tools Bash(gh pr:*)'
|
|
@@ -158,4 +158,4 @@ jobs:
|
|
|
158
158
|
echo "Releasing familia ${gem_version} from tag ${RELEASE_TAG}"
|
|
159
159
|
|
|
160
160
|
- name: Build and push gem to RubyGems
|
|
161
|
-
uses: rubygems/release-gem@
|
|
161
|
+
uses: rubygems/release-gem@7f9650160c1a4e7989fdc9855807bdbd421d8b6b # v1.4.1
|
data/.gitignore
CHANGED
|
@@ -18,14 +18,21 @@
|
|
|
18
18
|
dump.rdb
|
|
19
19
|
appendonlydir
|
|
20
20
|
data
|
|
21
|
+
doc
|
|
21
22
|
log
|
|
22
23
|
tmp
|
|
23
24
|
vendor
|
|
24
25
|
*.gem
|
|
25
26
|
public/
|
|
26
27
|
|
|
27
|
-
# Ignore WIP or temp dev files with uppercase names
|
|
28
|
-
|
|
28
|
+
# Ignore WIP or temp dev files with uppercase names, at the repo root only.
|
|
29
|
+
# Anchored because core.ignoreCase is true on macOS/Windows checkouts: git
|
|
30
|
+
# casefolds the [A-Z] class, so an unanchored pattern silently swallowed every
|
|
31
|
+
# new lowercase .md anywhere in the tree (docs/*.md included).
|
|
32
|
+
/[A-Z]*.md
|
|
33
|
+
|
|
34
|
+
# Unredacted security notes stay local; publish redacted summaries only
|
|
35
|
+
*.private.md
|
|
29
36
|
|
|
30
37
|
# Exclusions
|
|
31
38
|
!README.md
|
data/.talismanrc
CHANGED
|
@@ -12,4 +12,17 @@ fileignoreconfig:
|
|
|
12
12
|
checksum: 10c94f802b2fa3a39fa33bf7dc34dac2ecaa2dd453ff97a19313f96a32fadeff
|
|
13
13
|
- filename: examples/encrypted_fields.rb
|
|
14
14
|
checksum: d1bd77f85d951d367e1c2bfd066a1d68d5f486346ee479121a3d5dcc2560bf52
|
|
15
|
+
# SHA-pinned actions read as "hex encoded text" to talisman; the pin is the point.
|
|
16
|
+
- filename: .github/workflows/claude.yml
|
|
17
|
+
checksum: 3a7acf45fb032644c40bad629ba6c0271689a1233ef6893aba3caf03f6327b50
|
|
18
|
+
- filename: .github/workflows/claude-code-review.yml
|
|
19
|
+
checksum: 698ebf39c1c49a72212cd8d9fd0117aaf15079dcb9f1e22c94dc7a871dd7952e
|
|
20
|
+
- filename: docs/adr/0002-watch-for-private-keys-lua-for-shared-keys.md
|
|
21
|
+
checksum: 0ace51636017e6d0a5b489dc14fc6b684cabd64c6bb706a710f869d31ea5f4f0
|
|
22
|
+
- filename: .github/workflows/ruby-lint.yml
|
|
23
|
+
checksum: b8009bc29189d214229c88f1cf7960c651404e659be74436a79efb130177ff58
|
|
24
|
+
- filename: .github/workflows/ci.yml
|
|
25
|
+
checksum: 0b356104ddf0b192d29b25669c61b17c863eca5de0e36822ea4d7b353d065016
|
|
26
|
+
- filename: .github/workflows/release-gem.yml
|
|
27
|
+
checksum: 1ad4786c939da966b79275105f60005c7a3214f424d5701d8118a7175b087112
|
|
15
28
|
version: ""
|
data/AGENTS.md
CHANGED
|
@@ -11,6 +11,8 @@ Guidance for AI coding agents working in this repository.
|
|
|
11
11
|
|
|
12
12
|
### Testing (Tryouts v3)
|
|
13
13
|
|
|
14
|
+
Use `valkey-server try/valkey.conf` to start the test redis.
|
|
15
|
+
|
|
14
16
|
Each file has optional setup, testcases, and optional teardown. A testcase is a
|
|
15
17
|
`##` description line, Ruby code, then one or more expectation comments
|
|
16
18
|
(`#=>`, `#==>`, `#=:>`, `#=!>`, ...). The last expression is the result.
|
|
@@ -21,6 +23,13 @@ Run with `--agent` for token-efficient output (`--agent-focus summary|first-fail
|
|
|
21
23
|
See `bundle exec try --help` for the full CLI, framework integration (`--rspec`,
|
|
22
24
|
`--minitest`), and debugging flags.
|
|
23
25
|
|
|
26
|
+
The whole suite runs in one process, so anything a file sets globally outlives
|
|
27
|
+
it. For encryption keys use the scoped helpers rather than assigning
|
|
28
|
+
`Familia.config.encryption_keys` directly: `set_test_encryption_keys(keys,
|
|
29
|
+
current_version:)` in setup with `clear_test_encryption_keys` in teardown, or
|
|
30
|
+
`with_test_encryption_keys(keys, current_version:) { ... }` for a single
|
|
31
|
+
testcase. See @try/support/helpers/encryption_config.rb.
|
|
32
|
+
|
|
24
33
|
### Changelog
|
|
25
34
|
|
|
26
35
|
Add a changelog fragment (RST) with each user-facing change. See @changelog.d/README.md
|
|
@@ -196,3 +205,22 @@ last-write timestamps (ZADD score), not a registry.
|
|
|
196
205
|
DataType instances are frozen (immutable). Configure module-level settings once
|
|
197
206
|
at startup, before threads spawn. `Familia.start_monitoring!` tracks contention.
|
|
198
207
|
Tests and contention patterns live in `try/thread_safety/`.
|
|
208
|
+
|
|
209
|
+
## Project claims and source authority
|
|
210
|
+
|
|
211
|
+
### Attribution
|
|
212
|
+
|
|
213
|
+
Do not infer project terminology or guarantees from repetition. Before attributing a claim to the project, locate an authoritative primary source and provide its exact wording. Treat delivery notes, commit messages, agent output, and documents created or modified during the current task as leads, not evidence. If the wording is absent, call it an interpretation or proposal. Never place paraphrases in quotation marks.
|
|
214
|
+
|
|
215
|
+
### Authoritative sources
|
|
216
|
+
|
|
217
|
+
Authoritative sources must be identified explicitly; repository presence alone does not confer authority. Accepted specifications and ADRs may establish project claims only within their stated scope. Delivery notes, commit messages, issue discussions, summaries, and agent-authored text are non-authoritative unless an authoritative source incorporates them explicitly.
|
|
218
|
+
|
|
219
|
+
### Normative claims
|
|
220
|
+
|
|
221
|
+
For normative claims concerning security, privacy, compatibility, persistence, or data loss:
|
|
222
|
+
|
|
223
|
+
1. Cite the authoritative source and its exact wording.
|
|
224
|
+
2. Distinguish quotations, paraphrases, interpretations, and proposals.
|
|
225
|
+
3. Do not use material created or modified during the current task to validate that task’s claims.
|
|
226
|
+
4. If no authoritative wording exists, report the claim as unsupported.
|
data/CHANGELOG.rst
CHANGED
|
@@ -7,6 +7,77 @@ The format is based on `Keep a Changelog <https://keepachangelog.com/en/1.1.0/>`
|
|
|
7
7
|
|
|
8
8
|
<!--scriv-insert-here-->
|
|
9
9
|
|
|
10
|
+
.. _changelog-2.12.0:
|
|
11
|
+
|
|
12
|
+
2.12.0 — 2026-08-03
|
|
13
|
+
===================
|
|
14
|
+
|
|
15
|
+
Added
|
|
16
|
+
-----
|
|
17
|
+
|
|
18
|
+
- Added ``Familia::HashKey#claim_field`` and ``#release_field`` for single-field compare-and-set and compare-and-delete. They raise ``Familia::OperationModeError`` in pipelines and transactions.
|
|
19
|
+
- Added generated ``claim_unique_<index>!`` and ``release_unique_<index>!`` methods for class-level unique indexes. #353
|
|
20
|
+
- Added ``Familia::MultiResult#aborted?`` and ``#inspect`` for transaction outcome handling and logging.
|
|
21
|
+
- Added ``max_length:`` to ``ListKey``, ``SortedSet``, ``participates_in``, and ``class_participates_in``. ``ListKey`` retains the N elements nearest the end written to, while ``SortedSet`` retains its N highest-scoring members. Existing oversized collections are trimmed on the next capped write; call ``enforce_max_length!`` or run ``Familia::Features::Housekeeping::EnforceCollectionCaps`` to enforce a new cap immediately. ``DataType#max_length`` exposes the configured cap. #351
|
|
22
|
+
- Added ``encryption_personalization_history`` to support XChaCha20-Poly1305 personalization rotation. See ``docs/guides/encryption.md``. #333
|
|
23
|
+
- Added ``limit:``, ``offset:``, and ``each_<collection>_with_permission`` for memory-bounded permission-filtered collection queries. #309
|
|
24
|
+
- Added the ``dirty_write_warnings:`` collection option to override a parent class's diagnostic mode. #282
|
|
25
|
+
|
|
26
|
+
Changed
|
|
27
|
+
-------
|
|
28
|
+
|
|
29
|
+
- Class-level unique-index updates inside transactions now require a prior claim and raise ``Familia::OperationModeError`` otherwise. #353
|
|
30
|
+
- Class-level index removal and destruction no longer delete entries owned by other records. #353
|
|
31
|
+
- ``Familia::MultiResult#results`` now returns an empty ``Array`` on transaction aborts, ``#to_h`` includes ``:aborted``, and result objects are read-only.
|
|
32
|
+
- ``SortedSet#increment`` now applies the dirty-write guard. #351
|
|
33
|
+
- XChaCha20 decryption and request caching now support personalization rotation candidates. #333
|
|
34
|
+
- ``multi_field_fast_write`` rejects class-indexed fields, and ``field!`` rejects class-indexed fields in transactions or pipelines and unsaved records. #308
|
|
35
|
+
- Registered instance-scoped index memberships refresh on ``save``. ``atomic_write`` callers must update those indexes explicitly. #282
|
|
36
|
+
- Saving a record with an instance-scoped unique-index collision now raises ``Familia::RecordExistsError`` without replacing the existing entry. #282
|
|
37
|
+
- Direct instance- and class-scoped index mutations now require a persisted record. #282
|
|
38
|
+
- Instance-scoped index mutations now reject scopes without an identifier or a Symbol/String ``identifier_field``. #282
|
|
39
|
+
|
|
40
|
+
Removed
|
|
41
|
+
-------
|
|
42
|
+
|
|
43
|
+
- Removed unused ``csv`` and ``stringio`` runtime dependencies from the gemspec. #354
|
|
44
|
+
|
|
45
|
+
Fixed
|
|
46
|
+
-----
|
|
47
|
+
|
|
48
|
+
- Fixed ``decrby`` and ``decr`` (and aliases) to decrement hash fields correctly and validate integer amounts.
|
|
49
|
+
- Fixed ``encryption_info`` to report correct provider details and key sizes.
|
|
50
|
+
- Fixed unique-index save races and ownership-checked removals, preventing collisions from replacing or deleting another record's entry. #353
|
|
51
|
+
- Fixed claim leaks when unpersisted records call ``update_in_<scope>_<index_name>``. #370
|
|
52
|
+
- Fixed ``Familia::MultiResult`` handling of WATCH-aborted transactions. #355
|
|
53
|
+
- Fixed XChaCha20 key derivation to preserve caller-provided context values. #356
|
|
54
|
+
- Fixed ``SortedSet#increment`` in transactions and pipelines to return the queued result. #351
|
|
55
|
+
- ``:maxlength`` now warns at definition time; rename it to ``max_length:`` to opt in to collection capping. #351
|
|
56
|
+
- Fixed ``Lock#acquire`` with a TTL to acquire and set the expiration atomically. #347
|
|
57
|
+
- Fixed ``DatabaseLogger.sample_rate`` validation and ``SingleUseRedactedString`` loading through ``require 'familia'``. #347
|
|
58
|
+
- Fixed memory use in ``<collection>_with_permission`` queries by processing results in bounded batches. #309
|
|
59
|
+
- Fixed invalid permission-symbol lookups to fail rather than silently misconfigure permission queries.
|
|
60
|
+
- Fixed partial and fast writes to maintain class-level unique indexes atomically. #308
|
|
61
|
+
- Fixed instance-scoped index cleanup after indexed values change, scope classes share an index name, or identifiers are reused. #282, #365
|
|
62
|
+
|
|
63
|
+
Security
|
|
64
|
+
--------
|
|
65
|
+
|
|
66
|
+
- ``multi_field_update`` and ``multi_field_fast_write`` now reject plaintext writes to encrypted fields and writes to transient fields.
|
|
67
|
+
- Pinned GitHub Workflows holding ``CLAUDE_CODE_OAUTH_TOKEN`` to immutable release commit SHAs.
|
|
68
|
+
- Encryption now fails closed when ``encryption_hkdf_salt`` is blank, including with a warm request cache. Configure a non-blank salt as described in ``docs/guides/encryption.md``. #380
|
|
69
|
+
|
|
70
|
+
Documentation
|
|
71
|
+
-------------
|
|
72
|
+
|
|
73
|
+
- Corrected permission-management, relationship, and connection-provider examples.
|
|
74
|
+
- Documented ``<collection>_with_permission`` flags, permission categories, exclusive tiers, and encryption personalization rotation.
|
|
75
|
+
|
|
76
|
+
AI Assistance
|
|
77
|
+
-------------
|
|
78
|
+
|
|
79
|
+
- Core fixes, tryout coverage (120+ test cases), and documentation updates implemented with AI assistance.
|
|
80
|
+
|
|
10
81
|
.. _changelog-2.11.2:
|
|
11
82
|
|
|
12
83
|
2.11.2 — 2026-07-05
|
|
@@ -16,25 +87,14 @@ The format is based on `Keep a Changelog <https://keepachangelog.com/en/1.1.0/>`
|
|
|
16
87
|
Changed
|
|
17
88
|
-------
|
|
18
89
|
|
|
19
|
-
- ``
|
|
20
|
-
become nil. ``save``/``commit_fields`` do a full overwrite (the stored hash
|
|
21
|
-
matches the in-memory object, so a field nil in memory is deleted);
|
|
22
|
-
``save_fields``/``multi_field_update``/``multi_field_fast_write`` delete a named
|
|
23
|
-
field passed as nil. ``to_h`` still returns every declared field, nils included.
|
|
90
|
+
- Nil-valued fields are now omitted from storage. Setting a field to ``nil`` removes it on every write path, while ``to_h`` continues to include declared fields with nil values.
|
|
24
91
|
|
|
25
|
-
-
|
|
26
|
-
another writer claimed via ``HSETNX``. To claim and update without disturbing
|
|
27
|
-
it, use the targeted writers or ``refresh!`` first.
|
|
92
|
+
- Refresh stale instances before a full ``save`` or ``commit_fields`` when another writer may have claimed a field; use targeted writers to update only named fields.
|
|
28
93
|
|
|
29
94
|
Fixed
|
|
30
95
|
-----
|
|
31
96
|
|
|
32
|
-
-
|
|
33
|
-
hash has no native NULL, this left declared fields perpetually present, breaking
|
|
34
|
-
``HSETNX``/``HEXISTS`` atomic-claim patterns and wasting memory. Nil fields are
|
|
35
|
-
now omitted, and clearing a field to nil removes it from storage (``HDEL``), so
|
|
36
|
-
absence again means "no value". No migration required: stale ``"null"`` values
|
|
37
|
-
are cleaned up on the next save and already decode back to ``nil`` on read.
|
|
97
|
+
- Fixed nil-valued fields being stored as the JSON string ``"null"``. No migration is required; existing values are cleaned up on the next save.
|
|
38
98
|
|
|
39
99
|
AI Assistance
|
|
40
100
|
-------------
|
|
@@ -49,96 +109,28 @@ AI Assistance
|
|
|
49
109
|
Added
|
|
50
110
|
-----
|
|
51
111
|
|
|
52
|
-
- ``encrypted_field`` now honors
|
|
53
|
-
field's write algorithm to a specific registered provider (``'aes-256-gcm'`` or
|
|
54
|
-
``'xchacha20poly1305'``) independent of the registry's default-provider
|
|
55
|
-
priority. The option was previously documented but silently ignored, so writes
|
|
56
|
-
always used the default provider. Decryption stays envelope-driven, so a pin can
|
|
57
|
-
be added, changed, or removed without breaking ciphertext already at rest, and
|
|
58
|
-
``re_encrypt_fields!`` re-encrypts under the pin rather than the default. This is
|
|
59
|
-
the supported lever for a reader-before-writer format migration: deploy
|
|
60
|
-
``rbnacl`` fleet-wide so every node can *read* XChaCha20-Poly1305 while keeping
|
|
61
|
-
*writes* pinned to AES-256-GCM until all readers are confirmed capable, then drop
|
|
62
|
-
the pin. Issue #334
|
|
112
|
+
- ``encrypted_field`` now honors its per-field ``algorithm:`` option for new writes, including ``re_encrypt_fields!``. Existing ciphertext remains decryptable when the pin changes or is removed. See ``docs/guides/feature-encrypted-fields.md`` for rollout guidance. #334
|
|
63
113
|
|
|
64
114
|
Changed
|
|
65
115
|
-------
|
|
66
116
|
|
|
67
|
-
-
|
|
68
|
-
from a *known* algorithm whose provider is not available on the current node.
|
|
69
|
-
Because ``Registry.register`` only stores providers whose runtime dependency is
|
|
70
|
-
present, pinning ``encrypted_field ..., algorithm: 'xchacha20poly1305'`` on a
|
|
71
|
-
node without ``rbnacl``/libsodium previously raised the misleading
|
|
72
|
-
``"Unsupported algorithm: xchacha20poly1305"`` -- pointing an operator at a typo
|
|
73
|
-
when the real fix is a missing dependency. It now names the provider, explains
|
|
74
|
-
the dependency is missing, and (because ``get`` runs on both the encrypt and
|
|
75
|
-
decrypt paths) states that installing the dependency is what enables reading
|
|
76
|
-
*and* writing the algorithm, framing an algorithm pin as a write-time
|
|
77
|
-
workaround that cannot decrypt existing ciphertext. Each provider declares its
|
|
78
|
-
own dependency via a new ``Provider.dependency_hint`` class method (nil for
|
|
79
|
-
always-available providers like OpenSSL AES-256-GCM), so the generic error path
|
|
80
|
-
names the correct library as providers are added rather than hardcoding any one
|
|
81
|
-
of them. The set of registerable providers is centralized in
|
|
82
|
-
``Registry.known_providers``, the single source of truth shared by ``setup!``
|
|
83
|
-
and ``get``. Error-message and internal-refactor only; the resolution of every
|
|
84
|
-
available algorithm is unchanged. Issue #334
|
|
117
|
+
- Encryption errors now distinguish unsupported algorithms from known algorithms whose provider dependency is unavailable. #334
|
|
85
118
|
|
|
86
119
|
Fixed
|
|
87
120
|
-----
|
|
88
121
|
|
|
89
|
-
- ``Familia::DataType#exists?``
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
but ``EXISTS`` returns an Integer count and ``0`` is truthy in Ruby, so the
|
|
93
|
-
guard never short-circuited on a missing key -- existence was decided
|
|
94
|
-
entirely by the size check. ``exists?`` now uses a boolean-coerced ``EXISTS``
|
|
95
|
-
count directly. Issue #331
|
|
96
|
-
|
|
97
|
-
- Relatedly, ``StringKey#size``/``#length``/``#empty?`` (and ``Lock``'s) no
|
|
98
|
-
longer reflect the never-nil ``#to_s`` fallback. ``#char_count`` derived from
|
|
99
|
-
``#to_s.size``, and ``#to_s`` intentionally returns ``Familia::Base``'s
|
|
100
|
-
documented "never nil" inspect-string when the value is absent -- so
|
|
101
|
-
``#size`` was non-zero (and ``#empty?`` false) for a missing key.
|
|
102
|
-
``#char_count`` now reads ``#value`` directly; ``#to_s`` is left unchanged.
|
|
103
|
-
Issue #331
|
|
104
|
-
|
|
105
|
-
- ``encrypted_fields_status`` now reports each field's real algorithm for a live
|
|
106
|
-
encrypted value (e.g. ``{ encrypted: true, algorithm: "aes-256-gcm", cleared:
|
|
107
|
-
false }``), honoring any per-field pin. Previously it returned ``{ encrypted:
|
|
108
|
-
false, value: "[CONCEALED]" }`` for every encrypted field, because
|
|
109
|
-
``ConcealedString`` had no ``concealed?`` predicate for the status check to
|
|
110
|
-
match -- so the algorithm shown in the method's docstring and the guides was
|
|
111
|
-
never actually produced. ``ConcealedString`` gains ``#concealed?`` and
|
|
112
|
-
``#algorithm`` readers (the latter reads the stored envelope). Issue #334
|
|
122
|
+
- Fixed ``Familia::DataType#exists?`` and missing ``StringKey`` and ``Lock`` size and emptiness checks. #331
|
|
123
|
+
|
|
124
|
+
- Fixed ``encrypted_fields_status`` to report the stored algorithm for encrypted fields, including per-field algorithm pins. #334
|
|
113
125
|
|
|
114
126
|
Documentation
|
|
115
127
|
-------------
|
|
116
128
|
|
|
117
|
-
- Added
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
as deliberately-passing checks, two operational hazards: the XChaCha
|
|
123
|
-
``encryption_personalization`` cannot be rotated (no history/fallback like
|
|
124
|
-
``encryption_hkdf_salt_history``), and once any XChaCha envelope exists,
|
|
125
|
-
every node that may read it needs libsodium installed. PR #330
|
|
126
|
-
|
|
127
|
-
- The encrypted-fields guide previously showed a ``provider: :aes_gcm`` field
|
|
128
|
-
option that was never implemented; those examples now use the real
|
|
129
|
-
``algorithm: 'aes-256-gcm'`` form, and the ``Familia::Encryption`` facade
|
|
130
|
-
docstring documents the shipped behavior instead of a hypothetical
|
|
131
|
-
implementation sketch. The ``encrypted_fields_status`` output examples across
|
|
132
|
-
the guides and the overview were corrected to match what the method now
|
|
133
|
-
returns. Issue #334
|
|
134
|
-
|
|
135
|
-
- Added a memory-audit investigation (``docs/investigation/memory-audit.md``)
|
|
136
|
-
diagnosing #309's ``<collection>_with_permission`` O(N) query as a transient,
|
|
137
|
-
GC-reclaimable spike rather than a per-process leak, and auditing the rest of
|
|
138
|
-
``lib/`` for per-process growth (concluding Familia has no unconditional leak).
|
|
139
|
-
Ships two executable proofs in ``try/investigation/`` — a pure-Ruby
|
|
140
|
-
``process_memory_leak_proof.rb`` and a live-Redis ``memory_leak_proof.rb``.
|
|
141
|
-
Diagnosis only; no runtime behaviour is changed by the investigation. Issue #309
|
|
129
|
+
- Added ``examples/encryption_upgrade_proof/`` to demonstrate encrypted-field algorithm upgrades. PR #330
|
|
130
|
+
|
|
131
|
+
- Corrected encrypted-field option and status examples to match supported behavior. #334
|
|
132
|
+
|
|
133
|
+
- Documented memory characteristics of ``<collection>_with_permission`` queries in ``docs/investigation/memory-audit.md``. #309
|
|
142
134
|
|
|
143
135
|
AI Assistance
|
|
144
136
|
-------------
|
data/Gemfile
CHANGED
|
@@ -5,7 +5,7 @@ source 'https://rubygems.org'
|
|
|
5
5
|
gemspec
|
|
6
6
|
|
|
7
7
|
group :test do
|
|
8
|
-
gem 'concurrent-ruby', '~> 1.3.
|
|
8
|
+
gem 'concurrent-ruby', '~> 1.3.8', require: false
|
|
9
9
|
gem 'ruby-prof'
|
|
10
10
|
gem 'stackprof'
|
|
11
11
|
gem 'timecop', require: false
|
|
@@ -26,7 +26,7 @@ group :development, :test do
|
|
|
26
26
|
gem 'rake', '~> 13.0', require: false
|
|
27
27
|
gem 'redcarpet', require: false
|
|
28
28
|
gem 'reek', require: false
|
|
29
|
-
gem 'rubocop', '~> 1.
|
|
29
|
+
gem 'rubocop', '~> 1.90.0', require: false
|
|
30
30
|
gem 'rubocop-performance', require: false
|
|
31
31
|
gem 'rubocop-thread_safety', require: false
|
|
32
32
|
gem 'ruby-lsp', require: false
|
data/Gemfile.lock
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
familia (2.
|
|
4
|
+
familia (2.13.0)
|
|
5
5
|
concurrent-ruby (~> 1.3)
|
|
6
6
|
connection_pool (>= 2.4, < 4.0)
|
|
7
|
-
csv (~> 3.3)
|
|
8
7
|
json_schemer (~> 2.0)
|
|
9
8
|
logger (~> 1.7)
|
|
10
9
|
oj (~> 3.16)
|
|
11
10
|
redis (>= 5.0, < 6.0)
|
|
12
|
-
stringio (>= 3.1.1, < 3.3.0)
|
|
13
11
|
uri-valkey (~> 1.4)
|
|
14
12
|
|
|
15
13
|
GEM
|
|
@@ -19,9 +17,8 @@ GEM
|
|
|
19
17
|
base64 (0.3.0)
|
|
20
18
|
benchmark (0.5.0)
|
|
21
19
|
bigdecimal (4.1.2)
|
|
22
|
-
concurrent-ruby (1.3.
|
|
20
|
+
concurrent-ruby (1.3.8)
|
|
23
21
|
connection_pool (3.0.2)
|
|
24
|
-
csv (3.3.5)
|
|
25
22
|
date (3.5.1)
|
|
26
23
|
debug (1.11.1)
|
|
27
24
|
irb (~> 1.10)
|
|
@@ -66,22 +63,22 @@ GEM
|
|
|
66
63
|
prism (>= 1.3.0)
|
|
67
64
|
rdoc (>= 4.0.0)
|
|
68
65
|
reline (>= 0.4.2)
|
|
69
|
-
json (2.
|
|
66
|
+
json (2.21.2)
|
|
70
67
|
json_schemer (2.5.0)
|
|
71
68
|
bigdecimal
|
|
72
69
|
hana (~> 1.3)
|
|
73
70
|
regexp_parser (~> 2.0)
|
|
74
71
|
simpleidn (~> 0.2)
|
|
75
|
-
language_server-protocol (3.17.0.
|
|
72
|
+
language_server-protocol (3.17.0.6)
|
|
76
73
|
lint_roller (1.1.0)
|
|
77
74
|
logger (1.7.0)
|
|
78
75
|
minitest (5.27.0)
|
|
79
|
-
oj (3.17.
|
|
76
|
+
oj (3.17.6)
|
|
80
77
|
bigdecimal (>= 3.0)
|
|
81
78
|
ostruct (>= 0.2)
|
|
82
79
|
ostruct (0.6.3)
|
|
83
80
|
parallel (1.28.0)
|
|
84
|
-
parser (3.3.
|
|
81
|
+
parser (3.3.12.0)
|
|
85
82
|
ast (~> 2.4.1)
|
|
86
83
|
racc
|
|
87
84
|
pastel (0.8.0)
|
|
@@ -98,7 +95,7 @@ GEM
|
|
|
98
95
|
rake (13.4.2)
|
|
99
96
|
rbnacl (7.1.2)
|
|
100
97
|
ffi (~> 1)
|
|
101
|
-
rbs (4.
|
|
98
|
+
rbs (4.1.3)
|
|
102
99
|
logger
|
|
103
100
|
prism (>= 1.6.0)
|
|
104
101
|
tsort
|
|
@@ -134,8 +131,8 @@ GEM
|
|
|
134
131
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
135
132
|
rspec-support (~> 3.13.0)
|
|
136
133
|
rspec-support (3.13.7)
|
|
137
|
-
rubocop (1.
|
|
138
|
-
json (
|
|
134
|
+
rubocop (1.90.0)
|
|
135
|
+
json (>= 2.3)
|
|
139
136
|
language_server-protocol (~> 3.17.0.2)
|
|
140
137
|
lint_roller (~> 1.1.0)
|
|
141
138
|
parallel (>= 1.10)
|
|
@@ -145,18 +142,18 @@ GEM
|
|
|
145
142
|
rubocop-ast (>= 1.49.0, < 2.0)
|
|
146
143
|
ruby-progressbar (~> 1.7)
|
|
147
144
|
unicode-display_width (>= 2.4.0, < 4.0)
|
|
148
|
-
rubocop-ast (1.
|
|
145
|
+
rubocop-ast (1.50.0)
|
|
149
146
|
parser (>= 3.3.7.2)
|
|
150
147
|
prism (~> 1.7)
|
|
151
|
-
rubocop-performance (1.
|
|
148
|
+
rubocop-performance (1.27.0)
|
|
152
149
|
lint_roller (~> 1.1)
|
|
153
|
-
rubocop (>= 1.
|
|
150
|
+
rubocop (>= 1.89.0, < 2.0)
|
|
154
151
|
rubocop-ast (>= 1.47.1, < 2.0)
|
|
155
152
|
rubocop-thread_safety (0.7.3)
|
|
156
153
|
lint_roller (~> 1.1)
|
|
157
154
|
rubocop (~> 1.72, >= 1.72.1)
|
|
158
155
|
rubocop-ast (>= 1.44.0, < 2.0)
|
|
159
|
-
ruby-lsp (0.26.
|
|
156
|
+
ruby-lsp (0.26.11)
|
|
160
157
|
language_server-protocol (~> 3.17.0)
|
|
161
158
|
prism (>= 1.2, < 2.0)
|
|
162
159
|
rbs (>= 3, < 5)
|
|
@@ -185,7 +182,7 @@ GEM
|
|
|
185
182
|
unicode-emoji (~> 4.1)
|
|
186
183
|
unicode-emoji (4.2.0)
|
|
187
184
|
uri-valkey (1.4.0)
|
|
188
|
-
yard (0.9.
|
|
185
|
+
yard (0.9.45)
|
|
189
186
|
zeitwerk (2.8.2)
|
|
190
187
|
|
|
191
188
|
PLATFORMS
|
|
@@ -194,7 +191,7 @@ PLATFORMS
|
|
|
194
191
|
|
|
195
192
|
DEPENDENCIES
|
|
196
193
|
benchmark (~> 0.4)
|
|
197
|
-
concurrent-ruby (~> 1.3.
|
|
194
|
+
concurrent-ruby (~> 1.3.8)
|
|
198
195
|
debug
|
|
199
196
|
dry-configurable (>= 1.3, < 1.5)
|
|
200
197
|
familia!
|
|
@@ -204,7 +201,7 @@ DEPENDENCIES
|
|
|
204
201
|
rbnacl (~> 7.1, >= 7.1.1)
|
|
205
202
|
redcarpet
|
|
206
203
|
reek
|
|
207
|
-
rubocop (~> 1.
|
|
204
|
+
rubocop (~> 1.90.0)
|
|
208
205
|
rubocop-performance
|
|
209
206
|
rubocop-thread_safety
|
|
210
207
|
ruby-lsp
|
data/README.md
CHANGED
|
@@ -377,13 +377,24 @@ end
|
|
|
377
377
|
```ruby
|
|
378
378
|
require 'connection_pool'
|
|
379
379
|
|
|
380
|
+
POOLS = {}
|
|
381
|
+
POOLS_MUTEX = Mutex.new
|
|
382
|
+
|
|
380
383
|
Familia.connection_provider = lambda do |uri|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
+
POOLS_MUTEX.synchronize do
|
|
385
|
+
POOLS[uri] ||= ConnectionPool::Wrapper.new(size: 10, timeout: 5) do
|
|
386
|
+
Redis.new(url: uri)
|
|
387
|
+
end
|
|
388
|
+
end
|
|
384
389
|
end
|
|
385
390
|
```
|
|
386
391
|
|
|
392
|
+
Build each pool once, outside the lambda, and return a `ConnectionPool::Wrapper`
|
|
393
|
+
— it checks a connection out for the duration of each command and checks it back
|
|
394
|
+
in afterwards. Returning `pool.with { |conn| conn }` instead hands back a
|
|
395
|
+
connection the pool already considers free, so concurrent callers share it. See
|
|
396
|
+
[the provider contract](docs/reference/api-technical.md#provider-contract).
|
|
397
|
+
|
|
387
398
|
### Encryption Setup
|
|
388
399
|
|
|
389
400
|
```ruby
|