familia 2.0.0.pre4 → 2.0.0.pre6
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/.gitignore +3 -0
- data/.rubocop_todo.yml +17 -17
- data/CLAUDE.md +11 -8
- data/Gemfile +5 -1
- data/Gemfile.lock +19 -3
- data/README.md +36 -157
- data/docs/overview.md +359 -0
- data/docs/wiki/API-Reference.md +347 -0
- data/docs/wiki/Connection-Pooling-Guide.md +437 -0
- data/docs/wiki/Encrypted-Fields-Overview.md +101 -0
- data/docs/wiki/Expiration-Feature-Guide.md +596 -0
- data/docs/wiki/Feature-System-Guide.md +600 -0
- data/docs/wiki/Features-System-Developer-Guide.md +892 -0
- data/docs/wiki/Field-System-Guide.md +784 -0
- data/docs/wiki/Home.md +106 -0
- data/docs/wiki/Implementation-Guide.md +276 -0
- data/docs/wiki/Quantization-Feature-Guide.md +721 -0
- data/docs/wiki/RelatableObjects-Guide.md +563 -0
- data/docs/wiki/Security-Model.md +183 -0
- data/docs/wiki/Transient-Fields-Guide.md +280 -0
- data/lib/familia/base.rb +18 -27
- data/lib/familia/connection.rb +6 -5
- data/lib/familia/{datatype → data_type}/commands.rb +2 -5
- data/lib/familia/{datatype → data_type}/serialization.rb +8 -10
- data/lib/familia/data_type/types/counter.rb +38 -0
- data/lib/familia/{datatype → data_type}/types/hashkey.rb +20 -2
- data/lib/familia/{datatype → data_type}/types/list.rb +17 -18
- data/lib/familia/data_type/types/lock.rb +43 -0
- data/lib/familia/{datatype → data_type}/types/sorted_set.rb +17 -17
- data/lib/familia/{datatype → data_type}/types/string.rb +11 -3
- data/lib/familia/{datatype → data_type}/types/unsorted_set.rb +17 -18
- data/lib/familia/{datatype.rb → data_type.rb} +12 -14
- data/lib/familia/encryption/encrypted_data.rb +137 -0
- data/lib/familia/encryption/manager.rb +119 -0
- data/lib/familia/encryption/provider.rb +49 -0
- data/lib/familia/encryption/providers/aes_gcm_provider.rb +123 -0
- data/lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb +184 -0
- data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +138 -0
- data/lib/familia/encryption/registry.rb +50 -0
- data/lib/familia/encryption.rb +178 -0
- data/lib/familia/encryption_request_cache.rb +68 -0
- data/lib/familia/errors.rb +17 -3
- data/lib/familia/features/encrypted_fields/concealed_string.rb +295 -0
- data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +221 -0
- data/lib/familia/features/encrypted_fields.rb +28 -0
- data/lib/familia/features/expiration.rb +107 -77
- data/lib/familia/features/quantization.rb +5 -9
- data/lib/familia/features/relatable_objects.rb +2 -4
- data/lib/familia/features/safe_dump.rb +14 -17
- data/lib/familia/features/transient_fields/redacted_string.rb +159 -0
- data/lib/familia/features/transient_fields/single_use_redacted_string.rb +62 -0
- data/lib/familia/features/transient_fields/transient_field_type.rb +139 -0
- data/lib/familia/features/transient_fields.rb +47 -0
- data/lib/familia/features.rb +40 -24
- data/lib/familia/field_type.rb +273 -0
- data/lib/familia/horreum/{connection.rb → core/connection.rb} +6 -15
- data/lib/familia/horreum/{commands.rb → core/database_commands.rb} +20 -21
- data/lib/familia/horreum/core/serialization.rb +535 -0
- data/lib/familia/horreum/{utils.rb → core/utils.rb} +9 -12
- data/lib/familia/horreum/core.rb +21 -0
- data/lib/familia/horreum/{settings.rb → shared/settings.rb} +10 -4
- data/lib/familia/horreum/subclass/definition.rb +469 -0
- data/lib/familia/horreum/{class_methods.rb → subclass/management.rb} +27 -250
- data/lib/familia/horreum/{related_fields_management.rb → subclass/related_fields_management.rb} +15 -10
- data/lib/familia/horreum.rb +30 -22
- data/lib/familia/logging.rb +14 -14
- data/lib/familia/settings.rb +39 -3
- data/lib/familia/utils.rb +45 -0
- data/lib/familia/version.rb +1 -1
- data/lib/familia.rb +3 -2
- data/try/core/base_enhancements_try.rb +115 -0
- data/try/core/connection_try.rb +0 -1
- data/try/core/create_method_try.rb +240 -0
- data/try/core/database_consistency_try.rb +299 -0
- data/try/core/errors_try.rb +25 -5
- data/try/core/familia_extended_try.rb +3 -4
- data/try/core/familia_try.rb +1 -2
- data/try/core/persistence_operations_try.rb +297 -0
- data/try/core/pools_try.rb +2 -2
- data/try/core/secure_identifier_try.rb +0 -1
- data/try/core/settings_try.rb +0 -1
- data/try/core/utils_try.rb +0 -1
- data/try/{datatypes → data_types}/boolean_try.rb +1 -2
- data/try/data_types/counter_try.rb +93 -0
- data/try/{datatypes → data_types}/datatype_base_try.rb +2 -3
- data/try/{datatypes → data_types}/hash_try.rb +1 -2
- data/try/{datatypes → data_types}/list_try.rb +1 -2
- data/try/data_types/lock_try.rb +133 -0
- data/try/{datatypes → data_types}/set_try.rb +1 -2
- data/try/{datatypes → data_types}/sorted_set_try.rb +1 -2
- data/try/{datatypes → data_types}/string_try.rb +1 -2
- data/try/debugging/README.md +32 -0
- data/try/debugging/cache_behavior_tracer.rb +91 -0
- data/try/debugging/debug_aad_process.rb +82 -0
- data/try/debugging/debug_concealed_internal.rb +59 -0
- data/try/debugging/debug_concealed_reveal.rb +61 -0
- data/try/debugging/debug_context_aad.rb +68 -0
- data/try/debugging/debug_context_simple.rb +80 -0
- data/try/debugging/debug_cross_context.rb +62 -0
- data/try/debugging/debug_database_load.rb +64 -0
- data/try/debugging/debug_encrypted_json_check.rb +53 -0
- data/try/debugging/debug_encrypted_json_step_by_step.rb +62 -0
- data/try/debugging/debug_exists_lifecycle.rb +54 -0
- data/try/debugging/debug_field_decrypt.rb +74 -0
- data/try/debugging/debug_fresh_cross_context.rb +73 -0
- data/try/debugging/debug_load_path.rb +66 -0
- data/try/debugging/debug_method_definition.rb +46 -0
- data/try/debugging/debug_method_resolution.rb +41 -0
- data/try/debugging/debug_minimal.rb +24 -0
- data/try/debugging/debug_provider.rb +68 -0
- data/try/debugging/debug_secure_behavior.rb +73 -0
- data/try/debugging/debug_string_class.rb +46 -0
- data/try/debugging/debug_test.rb +46 -0
- data/try/debugging/debug_test_design.rb +80 -0
- data/try/debugging/encryption_method_tracer.rb +138 -0
- data/try/debugging/provider_diagnostics.rb +110 -0
- data/try/edge_cases/hash_symbolization_try.rb +0 -1
- data/try/edge_cases/json_serialization_try.rb +0 -1
- data/try/edge_cases/reserved_keywords_try.rb +42 -11
- data/try/encryption/config_persistence_try.rb +192 -0
- data/try/encryption/encryption_core_try.rb +328 -0
- data/try/encryption/instance_variable_scope_try.rb +31 -0
- data/try/encryption/module_loading_try.rb +28 -0
- data/try/encryption/providers/aes_gcm_provider_try.rb +178 -0
- data/try/encryption/providers/xchacha20_poly1305_provider_try.rb +169 -0
- data/try/encryption/roundtrip_validation_try.rb +28 -0
- data/try/encryption/secure_memory_handling_try.rb +125 -0
- data/try/features/encrypted_fields_core_try.rb +125 -0
- data/try/features/encrypted_fields_integration_try.rb +216 -0
- data/try/features/encrypted_fields_no_cache_security_try.rb +219 -0
- data/try/features/encrypted_fields_security_try.rb +377 -0
- data/try/features/encryption_fields/aad_protection_try.rb +138 -0
- data/try/features/encryption_fields/concealed_string_core_try.rb +250 -0
- data/try/features/encryption_fields/context_isolation_try.rb +141 -0
- data/try/features/encryption_fields/error_conditions_try.rb +116 -0
- data/try/features/encryption_fields/fresh_key_derivation_try.rb +128 -0
- data/try/features/encryption_fields/fresh_key_try.rb +168 -0
- data/try/features/encryption_fields/key_rotation_try.rb +123 -0
- data/try/features/encryption_fields/memory_security_try.rb +37 -0
- data/try/features/encryption_fields/missing_current_key_version_try.rb +23 -0
- data/try/features/encryption_fields/nonce_uniqueness_try.rb +56 -0
- data/try/features/encryption_fields/secure_by_default_behavior_try.rb +310 -0
- data/try/features/encryption_fields/thread_safety_try.rb +199 -0
- data/try/features/encryption_fields/universal_serialization_safety_try.rb +174 -0
- data/try/features/expiration_try.rb +0 -1
- data/try/features/feature_dependencies_try.rb +159 -0
- data/try/features/quantization_try.rb +0 -1
- data/try/features/real_feature_integration_try.rb +148 -0
- data/try/features/relatable_objects_try.rb +0 -1
- data/try/features/safe_dump_advanced_try.rb +0 -1
- data/try/features/safe_dump_try.rb +0 -1
- data/try/features/transient_fields/redacted_string_try.rb +248 -0
- data/try/features/transient_fields/refresh_reset_try.rb +164 -0
- data/try/features/transient_fields/simple_refresh_test.rb +50 -0
- data/try/features/transient_fields/single_use_redacted_string_try.rb +310 -0
- data/try/features/transient_fields_core_try.rb +181 -0
- data/try/features/transient_fields_integration_try.rb +260 -0
- data/try/helpers/test_helpers.rb +67 -0
- data/try/horreum/base_try.rb +157 -3
- data/try/horreum/enhanced_conflict_handling_try.rb +176 -0
- data/try/horreum/field_categories_try.rb +118 -0
- data/try/horreum/field_definition_try.rb +96 -0
- data/try/horreum/initialization_try.rb +1 -2
- data/try/horreum/relations_try.rb +1 -2
- data/try/horreum/serialization_persistent_fields_try.rb +165 -0
- data/try/horreum/serialization_try.rb +41 -7
- data/try/memory/memory_basic_test.rb +73 -0
- data/try/memory/memory_detailed_test.rb +121 -0
- data/try/memory/memory_docker_ruby_dump.sh +80 -0
- data/try/memory/memory_search_for_string.rb +83 -0
- data/try/memory/test_actual_redactedstring_protection.rb +38 -0
- data/try/models/customer_safe_dump_try.rb +1 -2
- data/try/models/customer_try.rb +1 -2
- data/try/models/datatype_base_try.rb +1 -2
- data/try/models/familia_object_try.rb +0 -1
- metadata +131 -23
- data/lib/familia/horreum/serialization.rb +0 -445
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93cb8ea627c19daff3566c7373aa45ff04adb6d37a3346c3b3049712c18838ea
|
4
|
+
data.tar.gz: 9d359e2067062a4c6afe91a76985362989a569611400f10f7155e505dd55e39b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e020a48703858e929eeb11188029893656ef84ce98113e4c448d41e354edb4fe77df420aa4bab33b7775f0719ad5a693fc672c8159cd0e963be7750daa12d5b9
|
7
|
+
data.tar.gz: c3e66800df77ccd33ccd5a6027d031173642446210309e60bf83243f59585a0416ea99002063f0080828eb24d1aa1fa50f3013e7dbf408b2299f2fea617b2fa3
|
data/.gitignore
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -26,14 +26,14 @@ Layout/EmptyLines:
|
|
26
26
|
# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only
|
27
27
|
Layout/EmptyLinesAroundClassBody:
|
28
28
|
Exclude:
|
29
|
-
- "lib/familia/
|
30
|
-
- "lib/familia/
|
29
|
+
- "lib/familia/data_type/types/list.rb"
|
30
|
+
- "lib/familia/data_type/types/unsorted_set.rb"
|
31
31
|
|
32
32
|
# Offense count: 1
|
33
33
|
# This cop supports safe autocorrection (--autocorrect).
|
34
34
|
Layout/SpaceAfterComma:
|
35
35
|
Exclude:
|
36
|
-
- "lib/familia/
|
36
|
+
- "lib/familia/data_type/types/hashkey.rb"
|
37
37
|
|
38
38
|
# Offense count: 4
|
39
39
|
# This cop supports safe autocorrection (--autocorrect).
|
@@ -61,9 +61,9 @@ Metrics/PerceivedComplexity:
|
|
61
61
|
# SupportedStyles: anonymous, explicit
|
62
62
|
Naming/BlockForwarding:
|
63
63
|
Exclude:
|
64
|
-
- "lib/familia/
|
65
|
-
- "lib/familia/
|
66
|
-
- "lib/familia/
|
64
|
+
- "lib/familia/data_type/types/list.rb"
|
65
|
+
- "lib/familia/data_type/types/sorted_set.rb"
|
66
|
+
- "lib/familia/data_type/types/unsorted_set.rb"
|
67
67
|
- "lib/familia/refinements.rb"
|
68
68
|
|
69
69
|
# Offense count: 8
|
@@ -73,8 +73,8 @@ Naming/MethodParameterName:
|
|
73
73
|
Exclude:
|
74
74
|
- "lib/familia/core_ext.rb"
|
75
75
|
- "lib/familia/horreum/class_methods.rb"
|
76
|
-
- "lib/familia/
|
77
|
-
- "lib/familia/
|
76
|
+
- "lib/familia/data_type/types/sorted_set.rb"
|
77
|
+
- "lib/familia/data_type/types/unsorted_set.rb"
|
78
78
|
|
79
79
|
# Offense count: 1
|
80
80
|
# Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
|
@@ -104,9 +104,9 @@ Naming/PredicatePrefix:
|
|
104
104
|
Style/ArgumentsForwarding:
|
105
105
|
Exclude:
|
106
106
|
- "lib/familia/horreum/class_methods.rb"
|
107
|
-
- "lib/familia/
|
108
|
-
- "lib/familia/
|
109
|
-
- "lib/familia/
|
107
|
+
- "lib/familia/data_type/types/list.rb"
|
108
|
+
- "lib/familia/data_type/types/sorted_set.rb"
|
109
|
+
- "lib/familia/data_type/types/unsorted_set.rb"
|
110
110
|
- "lib/familia/refinements.rb"
|
111
111
|
|
112
112
|
# Offense count: 11
|
@@ -118,11 +118,11 @@ Style/Documentation:
|
|
118
118
|
- "lib/familia/errors.rb"
|
119
119
|
- "lib/familia/horreum/class_methods.rb"
|
120
120
|
- "lib/familia/horreum/related_fields_management.rb"
|
121
|
-
- "lib/familia/
|
122
|
-
- "lib/familia/
|
123
|
-
- "lib/familia/
|
124
|
-
- "lib/familia/
|
125
|
-
- "lib/familia/
|
121
|
+
- "lib/familia/data_type/types/hashkey.rb"
|
122
|
+
- "lib/familia/data_type/types/list.rb"
|
123
|
+
- "lib/familia/data_type/types/sorted_set.rb"
|
124
|
+
- "lib/familia/data_type/types/string.rb"
|
125
|
+
- "lib/familia/data_type/types/unsorted_set.rb"
|
126
126
|
- "lib/familia/version.rb"
|
127
127
|
|
128
128
|
# Offense count: 1
|
@@ -150,7 +150,7 @@ Style/FrozenStringLiteralComment:
|
|
150
150
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
151
151
|
Style/HashTransformValues:
|
152
152
|
Exclude:
|
153
|
-
- "lib/familia/
|
153
|
+
- "lib/familia/data_type/types/hashkey.rb"
|
154
154
|
|
155
155
|
# Offense count: 1
|
156
156
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
data/CLAUDE.md
CHANGED
@@ -6,11 +6,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
6
6
|
|
7
7
|
### Testing
|
8
8
|
|
9
|
-
|
10
|
-
1)
|
11
|
-
2)
|
12
|
-
3)
|
13
|
-
4)
|
9
|
+
Tryouts framework rules:
|
10
|
+
1) **Structure**: 3 sections - setup (optional), testcases, teardown (optional)
|
11
|
+
2) **Test cases**: Use `##` for descriptions, Ruby code, then `#=>` expectations
|
12
|
+
3) **Variables**: Instance variables (`@var`) persist across all sections
|
13
|
+
4) **Expectations**: `#=>` (value), `#==>` (boolean), `#=:>` (type), `#=!>` (exception)
|
14
|
+
5) **Comments**: Use single `#` prefix, DO NOT label sections
|
15
|
+
6) **Philosophy**: Plain realistic code, avoid mocks/test DSL
|
16
|
+
7) **Result**: Last expression in each test case is the result
|
14
17
|
|
15
18
|
- **Run tests**: `bundle exec try` (uses tryouts testing framework)
|
16
19
|
- **Run specific test file, verbose**: `bundle exec try -v try/specific_test_try.rb`
|
@@ -51,9 +54,9 @@ This project uses `tryouts` instead of RSpec/Minitest. Test files are located in
|
|
51
54
|
- Supports multiple identifier strategies: symbols, procs, arrays
|
52
55
|
|
53
56
|
2. **`Familia::DataType`** - Base class for Valkey data type wrappers
|
54
|
-
- Located in `lib/familia/
|
57
|
+
- Located in `lib/familia/data_type.rb`
|
55
58
|
- Provides String, List, Set, SortedSet, HashKey implementations
|
56
|
-
- Each type has its own class in `lib/familia/
|
59
|
+
- Each type has its own class in `lib/familia/data_type/types/`
|
57
60
|
|
58
61
|
3. **`Familia::Base`** - Common module for both Horreum and DataType
|
59
62
|
- Located in `lib/familia/base.rb`
|
@@ -89,7 +92,7 @@ end
|
|
89
92
|
|
90
93
|
- `lib/familia.rb` - Main entry point and module definition
|
91
94
|
- `lib/familia/horreum/` - Horreum class implementation (class_methods, commands, serialization, etc.)
|
92
|
-
- `lib/familia/
|
95
|
+
- `lib/familia/data_type/` - Valkey/Redis type implementations and commands
|
93
96
|
- `lib/familia/features/` - Modular feature implementations
|
94
97
|
- `try/` - Test files using tryouts framework
|
95
98
|
- `try/test_helpers.rb` - Shared test utilities and sample classes
|
data/Gemfile
CHANGED
@@ -9,7 +9,7 @@ group :test do
|
|
9
9
|
gem 'tryouts', path: '../tryouts'
|
10
10
|
gem 'uri-valkey', path: '..//uri-valkey/gems', glob: 'uri-valkey.gemspec'
|
11
11
|
else
|
12
|
-
gem 'tryouts', '~> 3.
|
12
|
+
gem 'tryouts', '~> 3.3.2', require: false
|
13
13
|
end
|
14
14
|
gem 'concurrent-ruby', '~> 1.3.5', require: false
|
15
15
|
gem 'ruby-prof'
|
@@ -27,3 +27,7 @@ group :development, :test do
|
|
27
27
|
gem 'yard', '~> 0.9', require: false
|
28
28
|
gem 'irb', '~> 1.15.2', require: false
|
29
29
|
end
|
30
|
+
|
31
|
+
group :optional do
|
32
|
+
gem 'rbnacl', '~> 7.1', '>= 7.1.1'
|
33
|
+
end
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
familia (2.0.0.
|
4
|
+
familia (2.0.0.pre6)
|
5
5
|
benchmark
|
6
6
|
connection_pool
|
7
7
|
csv
|
@@ -24,6 +24,8 @@ GEM
|
|
24
24
|
date (3.4.1)
|
25
25
|
diff-lcs (1.6.2)
|
26
26
|
erb (5.0.2)
|
27
|
+
ffi (1.17.2)
|
28
|
+
ffi (1.17.2-arm64-darwin)
|
27
29
|
io-console (0.8.1)
|
28
30
|
irb (1.15.2)
|
29
31
|
pp (>= 0.6.0)
|
@@ -41,6 +43,8 @@ GEM
|
|
41
43
|
parser (3.3.8.0)
|
42
44
|
ast (~> 2.4.1)
|
43
45
|
racc
|
46
|
+
pastel (0.8.0)
|
47
|
+
tty-color (~> 0.5)
|
44
48
|
pp (0.6.2)
|
45
49
|
prettyprint
|
46
50
|
prettyprint (0.2.0)
|
@@ -56,6 +60,8 @@ GEM
|
|
56
60
|
stringio
|
57
61
|
racc (1.8.1)
|
58
62
|
rainbow (3.1.1)
|
63
|
+
rbnacl (7.1.2)
|
64
|
+
ffi (~> 1)
|
59
65
|
rdoc (6.14.2)
|
60
66
|
erb
|
61
67
|
psych (>= 4.0.0)
|
@@ -107,9 +113,18 @@ GEM
|
|
107
113
|
ruby-progressbar (1.13.0)
|
108
114
|
stackprof (0.2.27)
|
109
115
|
stringio (3.1.7)
|
110
|
-
tryouts (3.
|
116
|
+
tryouts (3.3.2)
|
117
|
+
concurrent-ruby (~> 1.0)
|
118
|
+
irb
|
111
119
|
minitest (~> 5.0)
|
120
|
+
pastel (~> 0.8)
|
121
|
+
prism (~> 1.0)
|
112
122
|
rspec (~> 3.0)
|
123
|
+
tty-cursor (~> 0.7)
|
124
|
+
tty-screen (~> 0.8)
|
125
|
+
tty-color (0.6.0)
|
126
|
+
tty-cursor (0.7.1)
|
127
|
+
tty-screen (0.8.2)
|
113
128
|
unicode-display_width (3.1.4)
|
114
129
|
unicode-emoji (~> 4.0, >= 4.0.4)
|
115
130
|
unicode-emoji (4.0.4)
|
@@ -127,12 +142,13 @@ DEPENDENCIES
|
|
127
142
|
irb (~> 1.15.2)
|
128
143
|
kramdown
|
129
144
|
pry-byebug (~> 3.10.1)
|
145
|
+
rbnacl (~> 7.1, >= 7.1.1)
|
130
146
|
rubocop
|
131
147
|
rubocop-performance
|
132
148
|
rubocop-thread_safety
|
133
149
|
ruby-prof
|
134
150
|
stackprof
|
135
|
-
tryouts (~> 3.
|
151
|
+
tryouts (~> 3.3.2)
|
136
152
|
yard (~> 0.9)
|
137
153
|
|
138
154
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -1,191 +1,70 @@
|
|
1
|
-
# Familia - 2.0
|
1
|
+
# Familia - 2.0
|
2
2
|
|
3
3
|
**Organize and store Ruby objects in Valkey/Redis. A powerful Ruby ORM (of sorts) for Valkey/Redis.**
|
4
4
|
|
5
5
|
Familia provides a flexible and feature-rich way to interact with Valkey using Ruby objects. It's designed to make working with Valkey as natural as working with Ruby classes, while offering advanced features for complex data management.
|
6
6
|
|
7
|
-
##
|
7
|
+
## Quick Start
|
8
8
|
|
9
|
+
### 1. Installation
|
9
10
|
|
10
|
-
|
11
|
+
```bash
|
12
|
+
# Add to Gemfile
|
13
|
+
gem 'familia', '>= 2.0.0'
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
* Or for development: `git clone git@github.com:delano/familia.git`
|
15
|
-
|
16
|
-
|
17
|
-
## Core Concepts and Features
|
18
|
-
|
19
|
-
### 1. Defining Horreum Classes
|
20
|
-
|
21
|
-
Familia uses the concept of "Horreum" classes to represent Valkey-compatible objects:
|
22
|
-
|
23
|
-
```ruby
|
24
|
-
class Flower < Familia::Horreum
|
25
|
-
identifier_field :token
|
26
|
-
field :name
|
27
|
-
list :owners
|
28
|
-
set :tags
|
29
|
-
zset :metrics
|
30
|
-
hashkey :props
|
31
|
-
string :counter
|
32
|
-
end
|
33
|
-
```
|
34
|
-
|
35
|
-
### 2. Flexible Identifiers
|
36
|
-
|
37
|
-
You can define identifiers in various ways:
|
38
|
-
|
39
|
-
```ruby
|
40
|
-
class User < Familia::Horreum
|
41
|
-
identifier_field :email
|
42
|
-
# or
|
43
|
-
identifier_field -> (user) { "user:#{user.email}" }
|
44
|
-
# or
|
45
|
-
identifier_field [:type, :email]
|
46
|
-
|
47
|
-
field :email
|
48
|
-
field :type
|
49
|
-
end
|
50
|
-
```
|
51
|
-
|
52
|
-
### 3. Data Types
|
53
|
-
|
54
|
-
Familia supports various Valkey-compatible data types:
|
55
|
-
|
56
|
-
```ruby
|
57
|
-
class Product < Familia::Horreum
|
58
|
-
string :name
|
59
|
-
list :categories
|
60
|
-
set :tags
|
61
|
-
zset :ratings
|
62
|
-
hashkey :attributes
|
63
|
-
end
|
64
|
-
```
|
65
|
-
|
66
|
-
### 4. Class-level Valkey-compatible Types
|
67
|
-
|
68
|
-
You can also define Valkey-compatible types at the class level:
|
69
|
-
|
70
|
-
```ruby
|
71
|
-
class Customer < Familia::Horreum
|
72
|
-
class_sorted_set :values, key: 'project:customers'
|
73
|
-
class_hashkey :projects
|
74
|
-
class_list :customers, suffix: []
|
75
|
-
class_string :message
|
76
|
-
end
|
77
|
-
```
|
78
|
-
|
79
|
-
### 5. Automatic Expiration
|
80
|
-
|
81
|
-
Use the expiration feature to set default TTL for objects:
|
82
|
-
|
83
|
-
```ruby
|
84
|
-
class Session < Familia::Horreum
|
85
|
-
feature :expiration
|
86
|
-
default_expiration 180.minutes
|
87
|
-
end
|
15
|
+
# Or install directly
|
16
|
+
gem install familia
|
88
17
|
```
|
89
18
|
|
90
|
-
###
|
91
|
-
|
92
|
-
Control which fields are exposed when serializing objects:
|
19
|
+
### 2. Configure Connection
|
93
20
|
|
94
21
|
```ruby
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
@safe_dump_fields = [
|
99
|
-
:id,
|
100
|
-
:username,
|
101
|
-
{full_name: ->(user) { "#{user.first_name} #{user.last_name}" }}
|
102
|
-
]
|
103
|
-
end
|
104
|
-
```
|
22
|
+
# config/initializers/familia.rb (Rails)
|
23
|
+
# or at the top of your script
|
105
24
|
|
106
|
-
|
25
|
+
require 'familia'
|
107
26
|
|
108
|
-
|
27
|
+
# Basic configuration
|
28
|
+
Familia.uri = 'redis://localhost:6379/0'
|
109
29
|
|
110
|
-
|
111
|
-
|
112
|
-
feature :quantization
|
113
|
-
string :counter, default_expiration: 1.day, quantize: [10.minutes, '%H:%M']
|
114
|
-
end
|
30
|
+
# Or with authentication
|
31
|
+
Familia.uri = 'redis://user:password@localhost:6379/0'
|
115
32
|
```
|
116
33
|
|
117
|
-
###
|
118
|
-
|
119
|
-
Add custom methods to your Horreum classes:
|
34
|
+
### 3. Create Your First Model
|
120
35
|
|
121
36
|
```ruby
|
122
37
|
class User < Familia::Horreum
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
def active?
|
128
|
-
status == 'active'
|
129
|
-
end
|
38
|
+
identifier_field :email
|
39
|
+
field :email
|
40
|
+
field :name
|
41
|
+
field :created_at
|
130
42
|
end
|
131
43
|
```
|
132
44
|
|
133
|
-
###
|
134
|
-
|
135
|
-
You can add custom methods to your Horreum classes:
|
45
|
+
### 4. Basic Operations
|
136
46
|
|
137
47
|
```ruby
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
142
|
-
end
|
143
|
-
```
|
144
|
-
### 10. Open-ended Serialization
|
48
|
+
# Create
|
49
|
+
user = User.new(email: 'alice@example.com', name: 'Alice')
|
50
|
+
user.save
|
145
51
|
|
146
|
-
|
147
|
-
|
148
|
-
def serialize_value
|
149
|
-
custom_serialization_method
|
150
|
-
end
|
151
|
-
|
152
|
-
def self.deserialize_value(data)
|
153
|
-
custom_deserialization_method(data)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
```
|
52
|
+
# Find
|
53
|
+
user = User.load('alice@example.com')
|
157
54
|
|
158
|
-
|
55
|
+
# Update
|
56
|
+
user.name = 'Alice Smith'
|
57
|
+
user.save
|
159
58
|
|
160
|
-
|
161
|
-
|
162
|
-
conn.set("user:#{user.id}:status", "active")
|
163
|
-
conn.zadd("active_users", Time.now.to_i, user.id)
|
164
|
-
end
|
59
|
+
# Check existence
|
60
|
+
User.exists?('alice@example.com') #=> true
|
165
61
|
```
|
166
62
|
|
167
|
-
|
168
|
-
|
169
|
-
Familia supports custom connection providers for advanced scenarios like connection pooling:
|
170
|
-
|
171
|
-
```ruby
|
172
|
-
# Using connection_pool gem for thread-safe pooling
|
173
|
-
require 'connection_pool'
|
174
|
-
|
175
|
-
# Create pools for each logical database
|
176
|
-
pools = {
|
177
|
-
"redis://localhost:6379/0" => ConnectionPool.new(size: 10) { Redis.new(db: 0) },
|
178
|
-
"redis://localhost:6379/1" => ConnectionPool.new(size: 5) { Redis.new(db: 1) }
|
179
|
-
}
|
180
|
-
|
181
|
-
# Configure Familia to use the pools
|
182
|
-
Familia.connection_provider = lambda do |uri|
|
183
|
-
pool = pools[uri] || pools["redis://localhost:6379/0"]
|
184
|
-
pool.with { |conn| conn }
|
185
|
-
end
|
186
|
-
```
|
63
|
+
## Prerequisites
|
187
64
|
|
188
|
-
|
65
|
+
- **Ruby**: 3.4+ (3.4+ recommended)
|
66
|
+
- **Valkey/Redis**: 6.0+
|
67
|
+
- **Gems**: `redis` (automatically installed)
|
189
68
|
|
190
69
|
|
191
70
|
## Usage Examples
|