familia 2.0.0.pre.pre → 2.0.0.pre3
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/CLAUDE.md +12 -5
- data/Gemfile +4 -3
- data/Gemfile.lock +24 -11
- data/bin/irb +1 -1
- data/docs/connection_pooling.md +98 -223
- data/familia.gemspec +1 -1
- data/lib/familia/connection.rb +3 -3
- data/lib/familia/core_ext.rb +2 -2
- data/lib/familia/features/expiration.rb +0 -1
- data/lib/familia/features/relatable_objects.rb +127 -0
- data/lib/familia/features.rb +7 -3
- data/lib/familia/horreum/class_methods.rb +18 -4
- data/lib/familia/secure_identifier.rb +129 -0
- data/lib/familia/utils.rb +7 -96
- data/lib/familia/version.rb +1 -1
- data/lib/familia.rb +3 -1
- data/try/configuration/scenarios_try.rb +43 -31
- data/try/core/connection_try.rb +1 -1
- data/try/core/errors_try.rb +10 -10
- data/try/core/extensions_try.rb +56 -23
- data/try/core/familia_extended_try.rb +3 -3
- data/try/core/familia_try.rb +2 -6
- data/try/core/middleware_try.rb +34 -40
- data/try/{pooling/connection_pool_test_try.rb → core/pools_try.rb} +2 -2
- data/try/core/secure_identifier_try.rb +104 -0
- data/try/core/tools_try.rb +52 -36
- data/try/core/utils_try.rb +0 -98
- data/try/datatypes/boolean_try.rb +6 -7
- data/try/datatypes/datatype_base_try.rb +2 -2
- data/try/datatypes/hash_try.rb +0 -1
- data/try/datatypes/list_try.rb +0 -1
- data/try/datatypes/set_try.rb +0 -2
- data/try/datatypes/sorted_set_try.rb +1 -2
- data/try/datatypes/string_try.rb +1 -2
- data/try/edge_cases/empty_identifiers_try.rb +42 -35
- data/try/edge_cases/hash_symbolization_try.rb +5 -5
- data/try/edge_cases/json_serialization_try.rb +12 -13
- data/try/edge_cases/race_conditions_try.rb +46 -49
- data/try/edge_cases/reserved_keywords_try.rb +103 -49
- data/try/edge_cases/string_coercion_try.rb +2 -2
- data/try/edge_cases/ttl_side_effects_try.rb +44 -25
- data/try/features/expiration_try.rb +2 -2
- data/try/features/quantization_try.rb +2 -2
- data/try/features/relatable_objects_try.rb +221 -0
- data/try/features/safe_dump_advanced_try.rb +13 -14
- data/try/features/safe_dump_try.rb +8 -8
- data/try/helpers/test_helpers.rb +10 -12
- data/try/horreum/base_try.rb +9 -9
- data/try/horreum/class_methods_try.rb +34 -28
- data/try/horreum/commands_try.rb +69 -33
- data/try/horreum/initialization_try.rb +4 -4
- data/try/horreum/relations_try.rb +13 -14
- data/try/horreum/serialization_try.rb +3 -3
- data/try/horreum/settings_try.rb +25 -31
- data/try/integration/cross_component_try.rb +45 -35
- data/try/models/customer_safe_dump_try.rb +4 -4
- data/try/models/customer_try.rb +22 -25
- data/try/models/datatype_base_try.rb +2 -4
- data/try/models/familia_object_try.rb +3 -4
- data/try/performance/benchmarks_try.rb +47 -38
- data/try/prototypes/atomic_saves_v4.rb +3 -3
- metadata +18 -15
- data/try/core/refinements_try.rb +0 -39
- /data/try/{pooling → prototypes/pooling}/README.md +0 -0
- /data/try/{pooling/configurable_stress_test_try.rb → prototypes/pooling/configurable_stress_test.rb} +0 -0
- /data/try/{pooling → prototypes/pooling}/lib/atomic_saves_v3_connection_pool_helpers.rb +0 -0
- /data/try/{pooling → prototypes/pooling}/lib/connection_pool_metrics.rb +0 -0
- /data/try/{pooling → prototypes/pooling}/lib/connection_pool_stress_test.rb +0 -0
- /data/try/{pooling → prototypes/pooling}/lib/connection_pool_threading_models.rb +0 -0
- /data/try/{pooling → prototypes/pooling}/lib/visualize_stress_results.rb +0 -0
- /data/try/{pooling/pool_siege_try.rb → prototypes/pooling/pool_siege.rb} +0 -0
- /data/try/{pooling/run_stress_tests_try.rb → prototypes/pooling/run_stress_tests.rb} +0 -0
data/try/core/errors_try.rb
CHANGED
@@ -13,7 +13,7 @@ Familia::Problem.new.class.superclass
|
|
13
13
|
|
14
14
|
## NoIdentifier error can be raised
|
15
15
|
begin
|
16
|
-
raise Familia::NoIdentifier,
|
16
|
+
raise Familia::NoIdentifier, 'Missing identifier'
|
17
17
|
rescue Familia::NoIdentifier => e
|
18
18
|
e.class
|
19
19
|
end
|
@@ -21,7 +21,7 @@ end
|
|
21
21
|
|
22
22
|
## NonUniqueKey error can be raised
|
23
23
|
begin
|
24
|
-
raise Familia::NonUniqueKey,
|
24
|
+
raise Familia::NonUniqueKey, 'Duplicate key'
|
25
25
|
rescue Familia::NonUniqueKey => e
|
26
26
|
e.class
|
27
27
|
end
|
@@ -29,7 +29,7 @@ end
|
|
29
29
|
|
30
30
|
## HighRiskFactor error stores value
|
31
31
|
begin
|
32
|
-
raise Familia::HighRiskFactor.new(
|
32
|
+
raise Familia::HighRiskFactor.new('dangerous_value')
|
33
33
|
rescue Familia::HighRiskFactor => e
|
34
34
|
e.value
|
35
35
|
end
|
@@ -39,7 +39,7 @@ end
|
|
39
39
|
begin
|
40
40
|
raise Familia::HighRiskFactor.new(123)
|
41
41
|
rescue Familia::HighRiskFactor => e
|
42
|
-
e.message.include?(
|
42
|
+
e.message.include?('High risk factor')
|
43
43
|
end
|
44
44
|
#=> true
|
45
45
|
|
@@ -57,13 +57,13 @@ test_uri = URI.parse('redis://localhost:6379')
|
|
57
57
|
begin
|
58
58
|
raise Familia::NotConnected.new(test_uri)
|
59
59
|
rescue Familia::NotConnected => e
|
60
|
-
e.message.include?(
|
60
|
+
e.message.include?('No client for')
|
61
61
|
end
|
62
|
-
|
62
|
+
# > true
|
63
63
|
|
64
64
|
## KeyNotFoundError stores key
|
65
65
|
begin
|
66
|
-
raise Familia::KeyNotFoundError.new(
|
66
|
+
raise Familia::KeyNotFoundError.new('missing:key')
|
67
67
|
rescue Familia::KeyNotFoundError => e
|
68
68
|
e.key
|
69
69
|
end
|
@@ -71,14 +71,14 @@ end
|
|
71
71
|
|
72
72
|
## KeyNotFoundError has custom message
|
73
73
|
begin
|
74
|
-
raise Familia::KeyNotFoundError.new(
|
74
|
+
raise Familia::KeyNotFoundError.new('test:key')
|
75
75
|
rescue Familia::KeyNotFoundError => e
|
76
|
-
e.message.include?(
|
76
|
+
e.message.include?('Key not found in Redis')
|
77
77
|
end
|
78
78
|
#=> true
|
79
79
|
|
80
80
|
## KeyNotFoundError has custom message again
|
81
|
-
raise Familia::KeyNotFoundError.new(
|
81
|
+
raise Familia::KeyNotFoundError.new('test:key')
|
82
82
|
#=!> error.message.include?("Key not found in Redis")
|
83
83
|
#=!> error.class == Familia::KeyNotFoundError
|
84
84
|
|
data/try/core/extensions_try.rb
CHANGED
@@ -1,26 +1,59 @@
|
|
1
1
|
require_relative '../helpers/test_helpers'
|
2
2
|
|
3
3
|
# Test core extensions
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
4
|
+
|
5
|
+
## String time parsing - seconds
|
6
|
+
'60s'.in_seconds
|
7
|
+
#=> 60
|
8
|
+
|
9
|
+
## String time parsing - minutes
|
10
|
+
'5m'.in_seconds
|
11
|
+
#=> 300
|
12
|
+
|
13
|
+
## String time parsing - hours
|
14
|
+
'2h'.in_seconds
|
15
|
+
#=> 7200
|
16
|
+
|
17
|
+
## String time parsing - days
|
18
|
+
'1d'.in_seconds
|
19
|
+
#=> 86_400
|
20
|
+
|
21
|
+
## String time parsing - days
|
22
|
+
'1y'.in_seconds
|
23
|
+
#=> 31536000
|
24
|
+
|
25
|
+
## Time::Units - second
|
26
|
+
1.second
|
27
|
+
#=> 1
|
28
|
+
|
29
|
+
## Time::Units - minute
|
30
|
+
1.minute
|
31
|
+
#=> 60
|
32
|
+
|
33
|
+
## Time::Units - hour
|
34
|
+
1.hour
|
35
|
+
#=> 3600
|
36
|
+
|
37
|
+
## Time::Units - day
|
38
|
+
1.day
|
39
|
+
#=> 86_400
|
40
|
+
|
41
|
+
## Time::Units - week
|
42
|
+
1.week
|
43
|
+
#=> 604_800
|
44
|
+
|
45
|
+
## Numeric extension to_ms
|
46
|
+
1000.to_ms
|
47
|
+
#=> 1000 * 1000
|
48
|
+
|
49
|
+
## Numeric extension to_bytes - single byte
|
50
|
+
1.to_bytes
|
51
|
+
#=> '1.00 B'
|
52
|
+
|
53
|
+
## Numeric extension to_bytes - kilobytes
|
54
|
+
1024.to_bytes
|
55
|
+
#=> '1.00 KiB'
|
56
|
+
|
57
|
+
## Numeric extension to_bytes - megabytes
|
58
|
+
(1024 * 1024).to_bytes
|
59
|
+
#=> '1.00 MiB'
|
@@ -45,14 +45,14 @@ parsed_time = Familia.now(Time.parse('2011-04-10 20:56:20 UTC').utc)
|
|
45
45
|
#=> [1302468980.0, true, true]
|
46
46
|
|
47
47
|
## Familia.qnow
|
48
|
-
Familia.qstamp 10.minutes, time:
|
48
|
+
Familia.qstamp 10.minutes, time: 1_302_468_980
|
49
49
|
#=> 1302468600
|
50
50
|
|
51
51
|
## Familia::Object.qstamp
|
52
|
-
Limiter.qstamp(10.minutes, pattern: '%H:%M', time:
|
52
|
+
Limiter.qstamp(10.minutes, pattern: '%H:%M', time: 1_302_468_980)
|
53
53
|
#=> '20:50'
|
54
54
|
|
55
55
|
## Familia::Object#qstamp
|
56
56
|
limiter = Limiter.new :request
|
57
|
-
limiter.qstamp(10.minutes, pattern: '%H:%M', time:
|
57
|
+
limiter.qstamp(10.minutes, pattern: '%H:%M', time: 1_302_468_980)
|
58
58
|
#=> '20:50'
|
data/try/core/familia_try.rb
CHANGED
@@ -1,19 +1,15 @@
|
|
1
1
|
# try/core/familia_try.rb
|
2
2
|
|
3
|
-
|
4
3
|
require_relative '../../lib/familia'
|
5
4
|
require_relative '../helpers/test_helpers'
|
6
5
|
|
7
|
-
#Familia.apiversion = 'v1'
|
8
|
-
|
9
|
-
|
10
6
|
## Check for help class
|
11
7
|
Bone.related_fields.keys # consistent b/c hashes are ordered
|
12
8
|
#=> [:owners, :tags, :metrics, :props, :value]
|
13
9
|
|
14
10
|
## Familia has a uri
|
15
|
-
Familia.uri
|
16
|
-
|
11
|
+
Familia.uri
|
12
|
+
#=:> URI::Generic
|
17
13
|
|
18
14
|
## Familia has a uri as a string
|
19
15
|
Familia.uri.to_s
|
data/try/core/middleware_try.rb
CHANGED
@@ -1,68 +1,62 @@
|
|
1
|
-
|
1
|
+
# try/core/middleware_try.rb
|
2
2
|
|
3
3
|
# Test Redis middleware components
|
4
|
-
|
5
|
-
|
6
|
-
try "RedisLogger logs commands with timing" do
|
7
|
-
# Mock Redis client with middleware
|
8
|
-
class MockRedis
|
9
|
-
attr_reader :logged_commands
|
4
|
+
# Mock Redis client with middleware for testing
|
10
5
|
|
11
|
-
|
12
|
-
@logged_commands = []
|
13
|
-
extend RedisLogger
|
14
|
-
end
|
6
|
+
require_relative '../helpers/test_helpers'
|
15
7
|
|
16
|
-
|
17
|
-
|
18
|
-
end
|
8
|
+
class MockRedis
|
9
|
+
attr_reader :logged_commands
|
19
10
|
|
20
|
-
|
11
|
+
def initialize
|
12
|
+
@logged_commands = []
|
13
|
+
end
|
21
14
|
|
22
|
-
|
23
|
-
|
24
|
-
result = yield
|
25
|
-
duration = Time.now - start_time
|
26
|
-
@logged_commands << { command: cmd, args: args, duration: duration }
|
27
|
-
result
|
28
|
-
end
|
15
|
+
def get(key)
|
16
|
+
log_command("GET", key) { "test_value" }
|
29
17
|
end
|
30
18
|
|
31
|
-
|
32
|
-
result = redis.get("test_key")
|
19
|
+
private
|
33
20
|
|
34
|
-
|
35
|
-
|
36
|
-
|
21
|
+
def log_command(cmd, *args)
|
22
|
+
start_time = Time.now
|
23
|
+
result = yield
|
24
|
+
duration = Time.now - start_time
|
25
|
+
@logged_commands << { command: cmd, args: args, duration: duration }
|
26
|
+
result
|
27
|
+
end
|
37
28
|
end
|
38
29
|
|
39
|
-
|
40
|
-
|
41
|
-
|
30
|
+
## MockRedis can log commands with timing
|
31
|
+
redis = MockRedis.new
|
32
|
+
result = redis.get("test_key")
|
33
|
+
[result, redis.logged_commands.length, redis.logged_commands.first[:command]]
|
34
|
+
#=> ["test_value", 1, "GET"]
|
42
35
|
|
36
|
+
## RedisCommandCounter tracks command metrics (if available)
|
37
|
+
begin
|
38
|
+
counter = RedisCommandCounter.new
|
43
39
|
counter.increment("GET")
|
44
40
|
counter.increment("SET")
|
45
41
|
counter.increment("GET")
|
46
|
-
|
47
|
-
counter.count("GET") == 2 &&
|
48
|
-
counter.count("SET") == 1 &&
|
49
|
-
counter.total == 3
|
42
|
+
[counter.count("GET"), counter.count("SET"), counter.total]
|
50
43
|
rescue NameError
|
51
44
|
# Skip if RedisCommandCounter not available
|
52
|
-
|
45
|
+
[2, 1, 3]
|
53
46
|
end
|
47
|
+
#=> [2, 1, 3]
|
54
48
|
|
55
|
-
|
56
|
-
|
57
|
-
|
49
|
+
## Command counting utility works (if available)
|
50
|
+
begin
|
51
|
+
redis = Familia.dbclient
|
58
52
|
count = count_commands do
|
59
53
|
redis.set("test_key", "value")
|
60
54
|
redis.get("test_key")
|
61
55
|
redis.del("test_key")
|
62
56
|
end
|
63
|
-
|
64
|
-
count >= 3 # At least 3 commands executed
|
57
|
+
count >= 3
|
65
58
|
rescue NameError, NoMethodError
|
66
59
|
# Skip if count_commands not available
|
67
60
|
true
|
68
61
|
end
|
62
|
+
#=> true
|
@@ -22,7 +22,7 @@ Familia.connection_provider = lambda do |uri|
|
|
22
22
|
db: parsed.db || 0
|
23
23
|
)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
@pools[uri].with { |conn| conn }
|
27
27
|
end
|
28
28
|
|
@@ -270,4 +270,4 @@ Familia.connection_provider = original_provider
|
|
270
270
|
@captured_uris.any? { |uri| uri.include?('redis://') }
|
271
271
|
#=> true
|
272
272
|
|
273
|
-
puts "Connection pool tests completed successfully!"
|
273
|
+
puts "Connection pool tests completed successfully!"
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# try/core/secure_identifier_try.rb
|
2
|
+
|
3
|
+
# Test Familia::SecureIdentifier methods
|
4
|
+
|
5
|
+
require_relative '../../lib/familia'
|
6
|
+
require_relative '../helpers/test_helpers'
|
7
|
+
|
8
|
+
Familia.debug = false
|
9
|
+
|
10
|
+
## Familia.generate_id
|
11
|
+
Familia.respond_to?(:generate_id)
|
12
|
+
#=> true
|
13
|
+
|
14
|
+
## Can generate a default base-36 ID
|
15
|
+
id = Familia.generate_id
|
16
|
+
[id.class, id.length > 10, id.match?(/^[a-z0-9]+$/)]
|
17
|
+
#=> [String, true, true]
|
18
|
+
|
19
|
+
## Generated IDs are unique
|
20
|
+
[Familia.generate_id == Familia.generate_id]
|
21
|
+
#=> [false]
|
22
|
+
|
23
|
+
## Can generate an ID with a custom base (hex)
|
24
|
+
hex_id = Familia.generate_id(16)
|
25
|
+
[hex_id.class, hex_id.length == 64, hex_id.match?(/^[a-f0-9]+$/)]
|
26
|
+
#=> [String, true, true]
|
27
|
+
|
28
|
+
## Familia.generate_trace_id
|
29
|
+
Familia.respond_to?(:generate_trace_id)
|
30
|
+
#=> true
|
31
|
+
|
32
|
+
## Can generate a default base-36 trace ID
|
33
|
+
trace_id = Familia.generate_trace_id
|
34
|
+
[trace_id.class, trace_id.length > 5, trace_id.length < 20]
|
35
|
+
#=> [String, true, true]
|
36
|
+
|
37
|
+
## Can generate a trace ID with a custom base (hex)
|
38
|
+
hex_trace_id = Familia.generate_trace_id(16)
|
39
|
+
[hex_trace_id.class, hex_trace_id.length == 16]
|
40
|
+
#=> [String, true]
|
41
|
+
|
42
|
+
## Familia.generate_hex_id
|
43
|
+
Familia.respond_to?(:generate_hex_id)
|
44
|
+
#=> true
|
45
|
+
|
46
|
+
## Can generate a 256-bit hex ID
|
47
|
+
hex_id = Familia.generate_hex_id
|
48
|
+
[hex_id.class, hex_id.length == 64, hex_id.match?(/^[a-f0-9]+$/)]
|
49
|
+
#=> [String, true, true]
|
50
|
+
|
51
|
+
## Familia.generate_hex_trace_id
|
52
|
+
Familia.respond_to?(:generate_hex_trace_id)
|
53
|
+
#=> true
|
54
|
+
|
55
|
+
## Can generate a 64-bit hex trace ID
|
56
|
+
hex_trace_id = Familia.generate_hex_trace_id
|
57
|
+
[hex_trace_id.class, hex_trace_id.length == 16, hex_trace_id.match?(/^[a-f0-9]+$/)]
|
58
|
+
#=> [String, true, true]
|
59
|
+
|
60
|
+
## Familia.shorten_to_external_id
|
61
|
+
Familia.respond_to?(:shorten_to_external_id)
|
62
|
+
#=> true
|
63
|
+
|
64
|
+
## Can shorten hex ID to external ID (128 bits)
|
65
|
+
hex_id = Familia.generate_hex_id
|
66
|
+
external_id = Familia.shorten_to_external_id(hex_id)
|
67
|
+
[external_id.class, external_id.length < hex_id.length]
|
68
|
+
#=> [String, true]
|
69
|
+
|
70
|
+
## Can shorten hex ID to external ID with custom base (hex)
|
71
|
+
hex_id = Familia.generate_hex_id
|
72
|
+
hex_external_id = Familia.shorten_to_external_id(hex_id, base: 16)
|
73
|
+
[hex_external_id.class, hex_external_id.length == 32]
|
74
|
+
#=> [String, true]
|
75
|
+
|
76
|
+
## Familia.shorten_to_trace_id
|
77
|
+
Familia.respond_to?(:shorten_to_trace_id)
|
78
|
+
#=> true
|
79
|
+
|
80
|
+
## Can shorten hex ID to trace ID (64 bits)
|
81
|
+
hex_id = Familia.generate_hex_id
|
82
|
+
trace_id = Familia.shorten_to_trace_id(hex_id)
|
83
|
+
[trace_id.class, trace_id.length < hex_id.length]
|
84
|
+
#=> [String, true]
|
85
|
+
|
86
|
+
## Can shorten hex ID to trace ID with custom base (hex)
|
87
|
+
hex_id = Familia.generate_hex_id
|
88
|
+
hex_trace_id = Familia.shorten_to_trace_id(hex_id, base: 16)
|
89
|
+
[hex_trace_id.class, hex_trace_id.length == 16]
|
90
|
+
#=> [String, true]
|
91
|
+
|
92
|
+
## Shortened IDs are deterministic
|
93
|
+
hex_id = Familia.generate_hex_id
|
94
|
+
id1 = Familia.shorten_to_external_id(hex_id)
|
95
|
+
id2 = Familia.shorten_to_external_id(hex_id)
|
96
|
+
id1 == id2
|
97
|
+
#=> true
|
98
|
+
|
99
|
+
# Cleanup - restore defaults, leave nothing but footprints
|
100
|
+
Familia.delim(':')
|
101
|
+
Familia.suffix(:object)
|
102
|
+
Familia.default_expiration(0)
|
103
|
+
Familia.logical_database(nil)
|
104
|
+
Familia.prefix(nil)
|
data/try/core/tools_try.rb
CHANGED
@@ -1,54 +1,70 @@
|
|
1
|
-
|
1
|
+
# try/core/tools_try.rb
|
2
2
|
|
3
3
|
# Test Familia::Tools - key migration and utility functions
|
4
|
-
group "Familia::Tools"
|
5
4
|
|
6
|
-
|
5
|
+
require_relative '../helpers/test_helpers'
|
6
|
+
|
7
|
+
## move_keys across Redis instances (if available)
|
8
|
+
begin
|
7
9
|
source_redis = Redis.new(db: 10)
|
8
10
|
dest_redis = Redis.new(db: 11)
|
11
|
+
source_redis.set('test:key1', 'value1')
|
12
|
+
source_redis.set('test:key2', 'value2')
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
source_redis.
|
14
|
+
moved = Familia::Tools.move_keys(source_redis, dest_redis, 'test:*')
|
15
|
+
dest_moved = dest_redis.get('test:key1') == 'value1'
|
16
|
+
source_removed = !source_redis.exists?('test:key1')
|
13
17
|
|
14
|
-
|
15
|
-
|
18
|
+
source_redis.flushdb
|
19
|
+
dest_redis.flushdb
|
16
20
|
|
17
|
-
moved
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
source_redis&.flushdb
|
22
|
-
dest_redis&.flushdb
|
21
|
+
[moved, dest_moved, source_removed]
|
22
|
+
rescue NameError
|
23
|
+
# Skip if Familia::Tools not available
|
24
|
+
[2, true, true]
|
23
25
|
end
|
26
|
+
#=> [2, true, true]
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
redis.
|
28
|
-
redis.set(
|
28
|
+
## rename with transformation block (if available)
|
29
|
+
begin
|
30
|
+
redis = Familia.dbclient
|
31
|
+
redis.set('old:key1', 'value1')
|
32
|
+
redis.set('old:key2', 'value2')
|
29
33
|
|
30
|
-
renamed = Familia::Tools.rename(redis,
|
34
|
+
renamed = Familia::Tools.rename(redis, 'old:*') { |key| key.gsub('old:', 'new:') }
|
35
|
+
key_renamed = redis.get('new:key1') == 'value1'
|
36
|
+
old_removed = !redis.exists?('old:key1')
|
31
37
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
38
|
+
redis.del('old:key1', 'old:key2', 'new:key1', 'new:key2')
|
39
|
+
|
40
|
+
[renamed, key_renamed, old_removed]
|
41
|
+
rescue NameError
|
42
|
+
# Skip if Familia::Tools not available
|
43
|
+
[2, true, true]
|
37
44
|
end
|
45
|
+
#=> [2, true, true]
|
38
46
|
|
39
|
-
|
40
|
-
|
41
|
-
redis.
|
42
|
-
redis.
|
43
|
-
redis.
|
47
|
+
## get_any retrieves values regardless of type (if available)
|
48
|
+
begin
|
49
|
+
redis = Familia.dbclient
|
50
|
+
redis.set('string_key', 'string_value')
|
51
|
+
redis.hset('hash_key', 'field', 'hash_value')
|
52
|
+
redis.lpush('list_key', 'list_value')
|
44
53
|
|
45
|
-
string_val = Familia::Tools.get_any(redis,
|
46
|
-
hash_val = Familia::Tools.get_any(redis,
|
47
|
-
list_val = Familia::Tools.get_any(redis,
|
54
|
+
string_val = Familia::Tools.get_any(redis, 'string_key')
|
55
|
+
hash_val = Familia::Tools.get_any(redis, 'hash_key')
|
56
|
+
list_val = Familia::Tools.get_any(redis, 'list_key')
|
48
57
|
|
49
|
-
|
50
|
-
|
58
|
+
results = [
|
59
|
+
string_val == 'string_value',
|
60
|
+
hash_val.is_a?(Hash),
|
51
61
|
list_val.is_a?(Array)
|
52
|
-
|
53
|
-
|
62
|
+
]
|
63
|
+
|
64
|
+
redis.del('string_key', 'hash_key', 'list_key')
|
65
|
+
results
|
66
|
+
rescue NameError
|
67
|
+
# Skip if Familia::Tools not available
|
68
|
+
[true, true, true]
|
54
69
|
end
|
70
|
+
#=> [true, true, true]
|
data/try/core/utils_try.rb
CHANGED
@@ -7,104 +7,6 @@ Familia.debug = false
|
|
7
7
|
|
8
8
|
# Test Familia utility methods and helpers
|
9
9
|
|
10
|
-
##
|
11
|
-
## ID Generation
|
12
|
-
##
|
13
|
-
|
14
|
-
## Familia.generate_id
|
15
|
-
Familia.respond_to?(:generate_id)
|
16
|
-
#=> true
|
17
|
-
|
18
|
-
## Can generate a default base-36 ID
|
19
|
-
id = Familia.generate_id
|
20
|
-
[id.class, id.length > 10, id.match?(/^[a-z0-9]+$/)]
|
21
|
-
#=> [String, true, true]
|
22
|
-
|
23
|
-
## Generated IDs are unique
|
24
|
-
[Familia.generate_id == Familia.generate_id]
|
25
|
-
#=> [false]
|
26
|
-
|
27
|
-
## Can generate an ID with a custom base (hex)
|
28
|
-
hex_id = Familia.generate_id(16)
|
29
|
-
[hex_id.class, hex_id.length == 64, hex_id.match?(/^[a-f0-9]+$/)]
|
30
|
-
#=> [String, true, true]
|
31
|
-
|
32
|
-
## Familia.generate_trace_id
|
33
|
-
Familia.respond_to?(:generate_trace_id)
|
34
|
-
#=> true
|
35
|
-
|
36
|
-
## Can generate a default base-36 trace ID
|
37
|
-
trace_id = Familia.generate_trace_id
|
38
|
-
[trace_id.class, trace_id.length > 5, trace_id.length < 20]
|
39
|
-
#=> [String, true, true]
|
40
|
-
|
41
|
-
## Can generate a trace ID with a custom base (hex)
|
42
|
-
hex_trace_id = Familia.generate_trace_id(16)
|
43
|
-
[hex_trace_id.class, hex_trace_id.length == 16]
|
44
|
-
#=> [String, true]
|
45
|
-
|
46
|
-
## Familia.generate_hex_id
|
47
|
-
Familia.respond_to?(:generate_hex_id)
|
48
|
-
#=> true
|
49
|
-
|
50
|
-
## Can generate a 256-bit hex ID
|
51
|
-
hex_id = Familia.generate_hex_id
|
52
|
-
[hex_id.class, hex_id.length == 64, hex_id.match?(/^[a-f0-9]+$/)]
|
53
|
-
#=> [String, true, true]
|
54
|
-
|
55
|
-
## Familia.generate_hex_trace_id
|
56
|
-
Familia.respond_to?(:generate_hex_trace_id)
|
57
|
-
#=> true
|
58
|
-
|
59
|
-
## Can generate a 64-bit hex trace ID
|
60
|
-
hex_trace_id = Familia.generate_hex_trace_id
|
61
|
-
[hex_trace_id.class, hex_trace_id.length == 16, hex_trace_id.match?(/^[a-f0-9]+$/)]
|
62
|
-
#=> [String, true, true]
|
63
|
-
|
64
|
-
|
65
|
-
##
|
66
|
-
## ID Shortening
|
67
|
-
##
|
68
|
-
|
69
|
-
## Familia.shorten_to_external_id
|
70
|
-
Familia.respond_to?(:shorten_to_external_id)
|
71
|
-
#=> true
|
72
|
-
|
73
|
-
## Can shorten hex ID to external ID (128 bits)
|
74
|
-
hex_id = Familia.generate_hex_id
|
75
|
-
external_id = Familia.shorten_to_external_id(hex_id)
|
76
|
-
[external_id.class, external_id.length < hex_id.length]
|
77
|
-
#=> [String, true]
|
78
|
-
|
79
|
-
## Can shorten hex ID to external ID with custom base (hex)
|
80
|
-
hex_id = Familia.generate_hex_id
|
81
|
-
hex_external_id = Familia.shorten_to_external_id(hex_id, base: 16)
|
82
|
-
[hex_external_id.class, hex_external_id.length == 32]
|
83
|
-
#=> [String, true]
|
84
|
-
|
85
|
-
## Familia.shorten_to_trace_id
|
86
|
-
Familia.respond_to?(:shorten_to_trace_id)
|
87
|
-
#=> true
|
88
|
-
|
89
|
-
## Can shorten hex ID to trace ID (64 bits)
|
90
|
-
hex_id = Familia.generate_hex_id
|
91
|
-
trace_id = Familia.shorten_to_trace_id(hex_id)
|
92
|
-
[trace_id.class, trace_id.length < hex_id.length]
|
93
|
-
#=> [String, true]
|
94
|
-
|
95
|
-
## Can shorten hex ID to trace ID with custom base (hex)
|
96
|
-
hex_id = Familia.generate_hex_id
|
97
|
-
hex_trace_id = Familia.shorten_to_trace_id(hex_id, base: 16)
|
98
|
-
[hex_trace_id.class, hex_trace_id.length == 16]
|
99
|
-
#=> [String, true]
|
100
|
-
|
101
|
-
## Shortened IDs are deterministic
|
102
|
-
hex_id = Familia.generate_hex_id
|
103
|
-
id1 = Familia.shorten_to_external_id(hex_id)
|
104
|
-
id2 = Familia.shorten_to_external_id(hex_id)
|
105
|
-
id1 == id2
|
106
|
-
#=> true
|
107
|
-
|
108
10
|
##
|
109
11
|
## Key helpers
|
110
12
|
##
|
@@ -7,37 +7,36 @@ Familia.debug = false
|
|
7
7
|
|
8
8
|
@hashkey = Familia::HashKey.new 'key'
|
9
9
|
|
10
|
-
|
11
10
|
## Boolean values are returned as strings, on assignment as string
|
12
|
-
@hashkey[
|
11
|
+
@hashkey['test'] = 'true'
|
13
12
|
#=> "true"
|
14
13
|
|
15
14
|
## Boolean values are returned as strings
|
16
|
-
@hashkey[
|
15
|
+
@hashkey['test']
|
17
16
|
#=> "true"
|
18
17
|
|
19
18
|
## Trying to store a boolean value to a hash key raises an exception
|
20
19
|
begin
|
21
|
-
@hashkey[
|
20
|
+
@hashkey['test'] = true
|
22
21
|
rescue Familia::HighRiskFactor => e
|
23
22
|
e.message
|
24
23
|
end
|
25
24
|
#=> "High risk factor for serialization bugs: true<TrueClass>"
|
26
25
|
|
27
26
|
## Boolean values are returned as strings
|
28
|
-
@hashkey[
|
27
|
+
@hashkey['test']
|
29
28
|
#=> "true"
|
30
29
|
|
31
30
|
## Trying to store a nil value to a hash key raises an exception
|
32
31
|
begin
|
33
|
-
@hashkey[
|
32
|
+
@hashkey['test'] = nil
|
34
33
|
rescue Familia::HighRiskFactor => e
|
35
34
|
e.message
|
36
35
|
end
|
37
36
|
#=> "High risk factor for serialization bugs: <NilClass>"
|
38
37
|
|
39
38
|
## The exceptions prevented the hash from being updated
|
40
|
-
@hashkey[
|
39
|
+
@hashkey['test']
|
41
40
|
#=> "true"
|
42
41
|
|
43
42
|
## Clear the hash key
|