familia 2.0.0.pre10 → 2.0.0.pre12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +75 -12
- data/CLAUDE.md +4 -54
- data/Gemfile.lock +1 -1
- data/changelog.d/README.md +45 -34
- data/docs/archive/FAMILIA_RELATIONSHIPS.md +1 -1
- data/docs/archive/FAMILIA_UPDATE.md +1 -1
- data/docs/archive/README.md +15 -19
- data/docs/guides/Home.md +1 -1
- data/docs/guides/Implementation-Guide.md +1 -1
- data/docs/guides/relationships-methods.md +1 -1
- data/docs/migrating/.gitignore +2 -0
- data/docs/migrating/v2.0.0-pre.md +84 -0
- data/docs/migrating/v2.0.0-pre11.md +255 -0
- data/docs/migrating/v2.0.0-pre12.md +306 -0
- data/docs/migrating/v2.0.0-pre5.md +110 -0
- data/docs/migrating/v2.0.0-pre6.md +154 -0
- data/docs/migrating/v2.0.0-pre7.md +222 -0
- data/docs/overview.md +6 -7
- data/{examples/redis_command_validation_example.rb → docs/reference/auditing_database_commands.rb} +29 -32
- data/examples/{bit_encoding_integration.rb → permissions.rb} +30 -27
- data/examples/{relationships_basic.rb → relationships.rb} +2 -3
- data/examples/safe_dump.rb +281 -0
- data/familia.gemspec +4 -4
- data/lib/familia/base.rb +52 -0
- data/lib/familia/{encryption_request_cache.rb → encryption/request_cache.rb} +1 -1
- data/lib/familia/errors.rb +2 -0
- data/lib/familia/features/autoloader.rb +57 -0
- data/lib/familia/features/external_identifier.rb +310 -0
- data/lib/familia/features/object_identifier.rb +307 -0
- data/lib/familia/features/safe_dump.rb +66 -72
- data/lib/familia/features.rb +93 -5
- data/lib/familia/horreum/subclass/definition.rb +47 -3
- data/lib/familia/secure_identifier.rb +51 -75
- data/lib/familia/verifiable_identifier.rb +162 -0
- data/lib/familia/version.rb +1 -1
- data/lib/familia.rb +1 -0
- data/setup.cfg +1 -8
- data/try/core/secure_identifier_try.rb +47 -18
- data/try/core/verifiable_identifier_try.rb +171 -0
- data/try/features/{external_identifiers/external_identifiers_try.rb → external_identifier/external_identifier_try.rb} +25 -28
- data/try/features/feature_improvements_try.rb +126 -0
- data/try/features/{object_identifiers/object_identifiers_integration_try.rb → object_identifier/object_identifier_integration_try.rb} +28 -30
- data/try/features/{object_identifiers/object_identifiers_try.rb → object_identifier/object_identifier_try.rb} +13 -13
- data/try/features/real_feature_integration_try.rb +7 -6
- data/try/features/safe_dump/safe_dump_try.rb +8 -9
- data/try/helpers/test_helpers.rb +17 -17
- metadata +30 -22
- data/changelog.d/fragments/.keep +0 -0
- data/changelog.d/template.md.j2 +0 -29
- data/lib/familia/features/external_identifiers/external_identifier_field_type.rb +0 -120
- data/lib/familia/features/external_identifiers.rb +0 -111
- data/lib/familia/features/object_identifiers/object_identifier_field_type.rb +0 -91
- data/lib/familia/features/object_identifiers.rb +0 -194
@@ -0,0 +1,154 @@
|
|
1
|
+
# Migrating Guide: Architecture Improvements (v2.0.0-pre6)
|
2
|
+
|
3
|
+
This guide covers the architecture enhancements and new persistence methods in v2.0.0-pre6.
|
4
|
+
|
5
|
+
## Architecture Improvements
|
6
|
+
|
7
|
+
### 1. Enhanced Persistence Operations
|
8
|
+
|
9
|
+
**New `save_if_not_exists` Method:**
|
10
|
+
```ruby
|
11
|
+
user = User.new(email: 'user@example.com')
|
12
|
+
|
13
|
+
# Only save if the user doesn't already exist
|
14
|
+
if user.save_if_not_exists
|
15
|
+
puts "User created successfully"
|
16
|
+
else
|
17
|
+
puts "User already exists"
|
18
|
+
end
|
19
|
+
```
|
20
|
+
|
21
|
+
**Atomic Persistence with Transactions:**
|
22
|
+
```ruby
|
23
|
+
user.transaction do |conn|
|
24
|
+
conn.set(user.key, user.serialize)
|
25
|
+
conn.sadd("all_users", user.identifier)
|
26
|
+
conn.expire(user.key, user.ttl) if user.ttl
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
### 2. Modular Class Structure
|
31
|
+
|
32
|
+
The Horreum class structure was reorganized for better maintainability:
|
33
|
+
|
34
|
+
**Core Modules:**
|
35
|
+
- `Familia::Horreum::Core` - Essential functionality
|
36
|
+
- `Familia::Horreum::ClassMethods` - Class-level methods
|
37
|
+
- `Familia::Horreum::Serialization` - Object serialization
|
38
|
+
- `Familia::Horreum::Commands` - Redis command wrappers
|
39
|
+
|
40
|
+
**Feature System Improvements:**
|
41
|
+
- Dependency management between features
|
42
|
+
- Cleaner feature activation
|
43
|
+
- Better error handling for missing dependencies
|
44
|
+
|
45
|
+
### 3. Enhanced Error Handling
|
46
|
+
|
47
|
+
**New Exception Types:**
|
48
|
+
```ruby
|
49
|
+
begin
|
50
|
+
user.save!
|
51
|
+
rescue Familia::PersistenceError => e
|
52
|
+
puts "Failed to save: #{e.message}"
|
53
|
+
rescue Familia::ValidationError => e
|
54
|
+
puts "Validation failed: #{e.message}"
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
**Improved Data Consistency:**
|
59
|
+
- Automatic retry for transient Redis connection issues
|
60
|
+
- Better handling of concurrent modifications
|
61
|
+
- Enhanced validation before persistence operations
|
62
|
+
|
63
|
+
## Migration Steps
|
64
|
+
|
65
|
+
### 1. Update Error Handling
|
66
|
+
|
67
|
+
**Before (v2.0.0-pre5):**
|
68
|
+
```ruby
|
69
|
+
begin
|
70
|
+
user.save
|
71
|
+
rescue => e
|
72
|
+
puts "Something went wrong: #{e}"
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
**After (v2.0.0-pre6):**
|
77
|
+
```ruby
|
78
|
+
begin
|
79
|
+
user.save
|
80
|
+
rescue Familia::PersistenceError => e
|
81
|
+
puts "Persistence failed: #{e.message}"
|
82
|
+
# Handle specific persistence issues
|
83
|
+
rescue Familia::ValidationError => e
|
84
|
+
puts "Invalid data: #{e.message}"
|
85
|
+
# Handle validation failures
|
86
|
+
end
|
87
|
+
```
|
88
|
+
|
89
|
+
### 2. Adopt Conditional Persistence
|
90
|
+
|
91
|
+
Replace existence checks with atomic operations:
|
92
|
+
|
93
|
+
**Before:**
|
94
|
+
```ruby
|
95
|
+
user = User.new(email: email)
|
96
|
+
unless User.exists?(email)
|
97
|
+
user.save
|
98
|
+
end
|
99
|
+
```
|
100
|
+
|
101
|
+
**After:**
|
102
|
+
```ruby
|
103
|
+
user = User.new(email: email)
|
104
|
+
user.save_if_not_exists
|
105
|
+
```
|
106
|
+
|
107
|
+
### 3. Leverage Transaction Support
|
108
|
+
|
109
|
+
For complex operations, use transactions:
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
# Before - Multiple separate operations
|
113
|
+
user.save
|
114
|
+
user.tags.add(tag)
|
115
|
+
user.scores.add(score, timestamp)
|
116
|
+
|
117
|
+
# After - Atomic transaction
|
118
|
+
user.transaction do |conn|
|
119
|
+
conn.set(user.key, user.serialize)
|
120
|
+
conn.sadd(user.tags.key, tag)
|
121
|
+
conn.zadd(user.scores.key, timestamp, score)
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
## Performance Improvements
|
126
|
+
|
127
|
+
### Connection Management
|
128
|
+
- Improved connection pooling with better resource utilization
|
129
|
+
- Reduced connection overhead through intelligent connection reuse
|
130
|
+
- Enhanced concurrent operation support
|
131
|
+
|
132
|
+
### Feature System
|
133
|
+
- Lazy feature loading reduces memory footprint
|
134
|
+
- Optimized method dispatch for feature methods
|
135
|
+
- Better dependency resolution
|
136
|
+
|
137
|
+
## Breaking Changes
|
138
|
+
|
139
|
+
### Method Signatures
|
140
|
+
- Some internal methods changed signatures for better consistency
|
141
|
+
- Error handling improved with specific exception types
|
142
|
+
- Transaction block interface standardized
|
143
|
+
|
144
|
+
### Feature Dependencies
|
145
|
+
- Features now explicitly declare dependencies
|
146
|
+
- Better error messages for missing feature requirements
|
147
|
+
- Automatic dependency resolution where possible
|
148
|
+
|
149
|
+
## Next Steps
|
150
|
+
|
151
|
+
After completing architecture migration:
|
152
|
+
1. Explore [Relationships Migration](v2.0.0-pre7.md) for the comprehensive relationship system
|
153
|
+
2. Review updated documentation for architectural patterns
|
154
|
+
3. Consider adopting new persistence patterns in your application
|
@@ -0,0 +1,222 @@
|
|
1
|
+
# Migrating Guide: Relationships System (v2.0.0-pre7)
|
2
|
+
|
3
|
+
This guide covers adopting the comprehensive relationships system introduced in v2.0.0-pre7.
|
4
|
+
|
5
|
+
## Relationships System Overview
|
6
|
+
|
7
|
+
The v2.0.0-pre7 release introduces three powerful relationship types:
|
8
|
+
|
9
|
+
- **`tracked_in`** - Multi-presence tracking with score encoding
|
10
|
+
- **`indexed_by`** - O(1) hash-based lookups
|
11
|
+
- **`member_of`** - Bidirectional membership with collision-free naming
|
12
|
+
|
13
|
+
## Migration Steps
|
14
|
+
|
15
|
+
### 1. Enable Relationships Feature
|
16
|
+
|
17
|
+
Add the relationships feature to your models:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
class Customer < Familia::Horreum
|
21
|
+
feature :relationships # Required for all relationship types
|
22
|
+
|
23
|
+
identifier_field :custid
|
24
|
+
field :custid, :name, :email
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
### 2. Choose Appropriate Relationship Types
|
29
|
+
|
30
|
+
**For Tracking Collections (sorted sets):**
|
31
|
+
```ruby
|
32
|
+
class Customer < Familia::Horreum
|
33
|
+
feature :relationships
|
34
|
+
|
35
|
+
# Global tracking with score-based sorting
|
36
|
+
tracked_in :all_customers, type: :sorted_set, score: :created_at
|
37
|
+
|
38
|
+
# Scoped tracking
|
39
|
+
tracked_in :active_users, type: :sorted_set, score: :last_seen
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
**For Fast Lookups (hash indexes):**
|
44
|
+
```ruby
|
45
|
+
class Customer < Familia::Horreum
|
46
|
+
feature :relationships
|
47
|
+
|
48
|
+
# Global email index for O(1) lookups
|
49
|
+
indexed_by :email, :email_lookup, context: :global
|
50
|
+
|
51
|
+
# Domain-specific indexes
|
52
|
+
indexed_by :account_id, :account_lookup, context: Domain
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
**For Bidirectional Membership:**
|
57
|
+
```ruby
|
58
|
+
class Domain < Familia::Horreum
|
59
|
+
feature :relationships
|
60
|
+
|
61
|
+
# Belongs to customer's domains collection
|
62
|
+
member_of Customer, :domains, type: :set
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
### 3. Implement Permission Systems
|
67
|
+
|
68
|
+
For access-controlled relationships:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
class Document < Familia::Horreum
|
72
|
+
feature :relationships
|
73
|
+
include Familia::Features::Relationships::PermissionManagement
|
74
|
+
|
75
|
+
# Permission-aware tracking
|
76
|
+
tracked_in Customer, :documents, score: :created_at
|
77
|
+
|
78
|
+
permission_tracking :user_permissions
|
79
|
+
|
80
|
+
def permission_bits
|
81
|
+
# Define permission levels (bit-encoded)
|
82
|
+
@permission_bits || 1 # Default: read-only
|
83
|
+
end
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
### 4. Update Queries
|
88
|
+
|
89
|
+
**Before (manual Redis operations):**
|
90
|
+
```ruby
|
91
|
+
# Manual sorted set operations
|
92
|
+
redis.zadd("all_customers", customer.created_at, customer.custid)
|
93
|
+
customers = redis.zrange("all_customers", 0, -1)
|
94
|
+
```
|
95
|
+
|
96
|
+
**After (relationship methods):**
|
97
|
+
```ruby
|
98
|
+
# Automatic method generation
|
99
|
+
Customer.add_to_all_customers(customer)
|
100
|
+
customers = Customer.all_customers.to_a
|
101
|
+
```
|
102
|
+
|
103
|
+
## Relationship Method Patterns
|
104
|
+
|
105
|
+
### `tracked_in` Methods
|
106
|
+
```ruby
|
107
|
+
# Class methods generated:
|
108
|
+
Customer.add_to_all_customers(customer)
|
109
|
+
Customer.remove_from_all_customers(customer)
|
110
|
+
Customer.all_customers # Access sorted set directly
|
111
|
+
```
|
112
|
+
|
113
|
+
### `indexed_by` Methods
|
114
|
+
```ruby
|
115
|
+
# Class methods generated:
|
116
|
+
Customer.add_to_email_lookup(customer)
|
117
|
+
Customer.remove_from_email_lookup(customer)
|
118
|
+
Customer.email_lookup.get(email) # O(1) lookup
|
119
|
+
```
|
120
|
+
|
121
|
+
### `member_of` Methods
|
122
|
+
```ruby
|
123
|
+
# Instance methods generated:
|
124
|
+
domain.add_to_customer_domains(customer)
|
125
|
+
domain.remove_from_customer_domains(customer)
|
126
|
+
domain.in_customer_domains?(customer)
|
127
|
+
```
|
128
|
+
|
129
|
+
## Permission System Migration
|
130
|
+
|
131
|
+
### Basic Permission Encoding
|
132
|
+
```ruby
|
133
|
+
# Permission levels (bit-encoded)
|
134
|
+
READ = 1 # 001
|
135
|
+
WRITE = 4 # 100
|
136
|
+
DELETE = 32 # 100000
|
137
|
+
ADMIN = 128 # 10000000
|
138
|
+
|
139
|
+
# Combine permissions
|
140
|
+
user_permissions = READ | WRITE # Can read and write
|
141
|
+
admin_permissions = ADMIN # All permissions via hierarchy
|
142
|
+
```
|
143
|
+
|
144
|
+
### Time-Based Permission Scores
|
145
|
+
```ruby
|
146
|
+
# Encode timestamp with permission bits
|
147
|
+
timestamp = Time.now.to_i
|
148
|
+
permissions = READ | WRITE
|
149
|
+
score = Familia::Features::Relationships::ScoreEncoding.encode_score(timestamp, permissions)
|
150
|
+
|
151
|
+
# Query by permission level
|
152
|
+
documents_with_write_access = customer.documents.accessible_items(
|
153
|
+
permissions: WRITE,
|
154
|
+
collection_key: customer.documents.key
|
155
|
+
)
|
156
|
+
```
|
157
|
+
|
158
|
+
## Performance Considerations
|
159
|
+
|
160
|
+
### Relationship Type Selection
|
161
|
+
|
162
|
+
**Use `indexed_by` for:**
|
163
|
+
- Unique field lookups (email, username, ID)
|
164
|
+
- Fields that need O(1) access
|
165
|
+
- Reference relationships
|
166
|
+
|
167
|
+
**Use `tracked_in` for:**
|
168
|
+
- Time-ordered collections
|
169
|
+
- Scored/ranked relationships
|
170
|
+
- Permission-based access control
|
171
|
+
|
172
|
+
**Use `member_of` for:**
|
173
|
+
- Simple membership tracking
|
174
|
+
- Bidirectional relationships
|
175
|
+
- Set-based collections
|
176
|
+
|
177
|
+
### Optimization Tips
|
178
|
+
|
179
|
+
**Batch Operations:**
|
180
|
+
```ruby
|
181
|
+
# Instead of multiple individual operations
|
182
|
+
customers.each { |c| Customer.add_to_all_customers(c) }
|
183
|
+
|
184
|
+
# Use batch operations where available
|
185
|
+
Customer.all_customers.add_batch(customers.map(&:identifier),
|
186
|
+
customers.map(&:created_at))
|
187
|
+
```
|
188
|
+
|
189
|
+
**Permission Queries:**
|
190
|
+
```ruby
|
191
|
+
# Efficient permission filtering
|
192
|
+
accessible_docs = document.accessible_items(
|
193
|
+
collection_key: customer.documents.key,
|
194
|
+
minimum_permissions: READ
|
195
|
+
)
|
196
|
+
```
|
197
|
+
|
198
|
+
## Breaking Changes
|
199
|
+
|
200
|
+
### Method Name Changes
|
201
|
+
- Relationship methods follow new naming patterns
|
202
|
+
- Previous manual Redis operations need updating
|
203
|
+
- Collection access methods standardized
|
204
|
+
|
205
|
+
### Permission System
|
206
|
+
- New bit-encoded permission system
|
207
|
+
- Time-based scoring for temporal access
|
208
|
+
- Permission hierarchy implementation required
|
209
|
+
|
210
|
+
## Next Steps
|
211
|
+
|
212
|
+
1. **Analyze Existing Relationships:** Review current Redis operations for optimization opportunities
|
213
|
+
2. **Choose Relationship Types:** Select appropriate types based on usage patterns
|
214
|
+
3. **Implement Permissions:** Add access control where needed
|
215
|
+
4. **Update Queries:** Replace manual operations with generated relationship methods
|
216
|
+
5. **Test Performance:** Benchmark relationship operations under load
|
217
|
+
|
218
|
+
## Resources
|
219
|
+
|
220
|
+
- [Relationships Methods Guide](../guides/relationships-methods.md) - Complete method reference
|
221
|
+
- [Relationships Guide](../guides/Relationships-Guide.md) - Implementation examples
|
222
|
+
- [Performance Guide](../guides/Implementation-Guide.md) - Optimization strategies
|
data/docs/overview.md
CHANGED
@@ -118,17 +118,16 @@ This is ideal for temporary data like authentication tokens or cache entries.
|
|
118
118
|
|
119
119
|
### Safe Dumping for APIs
|
120
120
|
|
121
|
-
Control which fields are exposed when serializing objects:
|
121
|
+
Control which fields are exposed when serializing objects using the clean DSL:
|
122
122
|
|
123
123
|
```ruby
|
124
124
|
class User < Familia::Horreum
|
125
125
|
feature :safe_dump
|
126
126
|
|
127
|
-
@safe_dump_fields
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
]
|
127
|
+
# Use clean DSL methods instead of @safe_dump_fields
|
128
|
+
safe_dump_field :id
|
129
|
+
safe_dump_field :email
|
130
|
+
safe_dump_field :full_name, ->(user) { "#{user.first_name} #{user.last_name}" }
|
132
131
|
|
133
132
|
field :id, :email, :first_name, :last_name, :password_hash
|
134
133
|
end
|
@@ -137,7 +136,7 @@ user.safe_dump
|
|
137
136
|
#=> {id: "123", email: "alice@example.com", full_name: "Alice Smith"}
|
138
137
|
```
|
139
138
|
|
140
|
-
|
139
|
+
The new DSL prevents accidental exposure of sensitive data and makes field definitions easier to organize in feature modules.
|
141
140
|
|
142
141
|
### Time-based Quantization
|
143
142
|
|
data/{examples/redis_command_validation_example.rb → docs/reference/auditing_database_commands.rb}
RENAMED
@@ -50,21 +50,21 @@ class TransferService
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
puts
|
54
|
-
puts
|
53
|
+
puts '🧪 Redis Command Validation Framework Demo'
|
54
|
+
puts '=' * 50
|
55
55
|
|
56
56
|
# Clean up any existing test data
|
57
|
-
cleanup_keys = Familia.dbclient.keys(
|
57
|
+
cleanup_keys = Familia.dbclient.keys('account:*')
|
58
58
|
Familia.dbclient.del(*cleanup_keys) if cleanup_keys.any?
|
59
59
|
|
60
60
|
# Example 1: Basic Command Recording
|
61
61
|
puts "\n1. Basic Command Recording"
|
62
|
-
puts
|
62
|
+
puts '-' * 30
|
63
63
|
|
64
64
|
CommandRecorder = Familia::Validation::CommandRecorder
|
65
65
|
CommandRecorder.start_recording
|
66
66
|
|
67
|
-
account = Account.new(account_id:
|
67
|
+
account = Account.new(account_id: 'acc001', balance: '1000', status: 'active')
|
68
68
|
account.save
|
69
69
|
|
70
70
|
commands = CommandRecorder.stop_recording
|
@@ -73,12 +73,12 @@ commands.commands.each { |cmd| puts " #{cmd}" }
|
|
73
73
|
|
74
74
|
# Example 2: Transaction Detection
|
75
75
|
puts "\n2. Transaction Detection"
|
76
|
-
puts
|
76
|
+
puts '-' * 30
|
77
77
|
|
78
78
|
CommandRecorder.start_recording
|
79
79
|
|
80
|
-
acc1 = Account.new(account_id:
|
81
|
-
acc2 = Account.new(account_id:
|
80
|
+
acc1 = Account.new(account_id: 'acc002', balance: '2000')
|
81
|
+
acc2 = Account.new(account_id: 'acc003', balance: '500')
|
82
82
|
acc1.save
|
83
83
|
acc2.save
|
84
84
|
|
@@ -96,7 +96,7 @@ end
|
|
96
96
|
|
97
97
|
# Example 3: Validation with Expectations DSL
|
98
98
|
puts "\n3. Command Validation with Expectations"
|
99
|
-
puts
|
99
|
+
puts '-' * 30
|
100
100
|
|
101
101
|
begin
|
102
102
|
validator = Familia::Validation::Validator.new
|
@@ -104,15 +104,15 @@ begin
|
|
104
104
|
# This should pass - we expect the exact Redis commands
|
105
105
|
result = validator.validate do |expect|
|
106
106
|
expect.transaction do |tx|
|
107
|
-
tx.hset(
|
108
|
-
.hset(
|
109
|
-
.hset(
|
110
|
-
.hset(
|
107
|
+
tx.hset('account:acc004:object', 'balance', '1500')
|
108
|
+
.hset('account:acc005:object', 'balance', '1000')
|
109
|
+
.hset('account:acc004:object', 'last_updated', Familia::Validation::ArgumentMatcher.new(:any_string))
|
110
|
+
.hset('account:acc005:object', 'last_updated', Familia::Validation::ArgumentMatcher.new(:any_string))
|
111
111
|
end
|
112
112
|
|
113
113
|
# Execute the operation
|
114
|
-
acc4 = Account.new(account_id:
|
115
|
-
acc5 = Account.new(account_id:
|
114
|
+
acc4 = Account.new(account_id: 'acc004', balance: '2000')
|
115
|
+
acc5 = Account.new(account_id: 'acc005', balance: '500')
|
116
116
|
acc4.save
|
117
117
|
acc5.save
|
118
118
|
|
@@ -121,51 +121,49 @@ begin
|
|
121
121
|
|
122
122
|
puts "Validation result: #{result.valid? ? 'PASS ✅' : 'FAIL ❌'}"
|
123
123
|
puts "Summary: #{result.summary}"
|
124
|
-
|
125
|
-
rescue => e
|
124
|
+
rescue StandardError => e
|
126
125
|
puts "Validation demo encountered error: #{e.message}"
|
127
|
-
puts
|
126
|
+
puts 'This is expected as the framework needs Redis middleware integration'
|
128
127
|
end
|
129
128
|
|
130
129
|
# Example 4: Performance Analysis
|
131
130
|
puts "\n4. Performance Analysis"
|
132
|
-
puts
|
131
|
+
puts '-' * 30
|
133
132
|
|
134
133
|
begin
|
135
134
|
commands = Familia::Validation.capture_commands do
|
136
135
|
# Create multiple accounts
|
137
136
|
accounts = []
|
138
137
|
(1..5).each do |i|
|
139
|
-
account = Account.new(account_id: "perf#{i}", balance:
|
138
|
+
account = Account.new(account_id: "perf#{i}", balance: '1000')
|
140
139
|
account.save
|
141
140
|
accounts << account
|
142
141
|
end
|
143
142
|
|
144
143
|
# Perform operations
|
145
|
-
accounts[0].balance =
|
144
|
+
accounts[0].balance = '1100'
|
146
145
|
accounts[0].save
|
147
146
|
end
|
148
147
|
|
149
148
|
analyzer = Familia::Validation::PerformanceAnalyzer.new(commands)
|
150
149
|
analysis = analyzer.analyze
|
151
150
|
|
152
|
-
puts
|
151
|
+
puts 'Performance Analysis:'
|
153
152
|
puts " Total Commands: #{analysis[:total_commands]}"
|
154
153
|
puts " Command Types: #{analysis[:command_type_breakdown].keys.join(', ')}"
|
155
154
|
puts " Efficiency Score: #{analysis[:efficiency_score]}/100"
|
156
|
-
|
157
|
-
rescue => e
|
155
|
+
rescue StandardError => e
|
158
156
|
puts "Performance analysis encountered error: #{e.message}"
|
159
157
|
end
|
160
158
|
|
161
159
|
# Example 5: Atomicity Validation
|
162
160
|
puts "\n5. Atomicity Validation"
|
163
|
-
puts
|
161
|
+
puts '-' * 30
|
164
162
|
|
165
163
|
begin
|
166
164
|
# Test atomic vs non-atomic operations
|
167
|
-
acc6 = Account.new(account_id:
|
168
|
-
acc7 = Account.new(account_id:
|
165
|
+
acc6 = Account.new(account_id: 'acc006', balance: '3000')
|
166
|
+
acc7 = Account.new(account_id: 'acc007', balance: '1000')
|
169
167
|
acc6.save
|
170
168
|
acc7.save
|
171
169
|
|
@@ -180,13 +178,12 @@ begin
|
|
180
178
|
result = atomicity_validator.validate
|
181
179
|
|
182
180
|
puts "Atomicity validation: #{result.valid? ? 'PASS ✅' : 'FAIL ❌'}"
|
183
|
-
|
184
|
-
rescue => e
|
181
|
+
rescue StandardError => e
|
185
182
|
puts "Atomicity validation encountered error: #{e.message}"
|
186
183
|
end
|
187
184
|
|
188
185
|
puts "\n6. Framework Architecture Overview"
|
189
|
-
puts
|
186
|
+
puts '-' * 30
|
190
187
|
puts "
|
191
188
|
The Redis Command Validation Framework provides:
|
192
189
|
|
@@ -224,8 +221,8 @@ Key Benefits:
|
|
224
221
|
"
|
225
222
|
|
226
223
|
# Cleanup
|
227
|
-
cleanup_keys = Familia.dbclient.keys(
|
224
|
+
cleanup_keys = Familia.dbclient.keys('account:*')
|
228
225
|
Familia.dbclient.del(*cleanup_keys) if cleanup_keys.any?
|
229
226
|
|
230
227
|
puts "\n🎉 Demo complete! The validation framework is ready for use."
|
231
|
-
puts
|
228
|
+
puts ' See try/validation/ for comprehensive test examples.'
|