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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CLAUDE.md +12 -5
  3. data/Gemfile +4 -3
  4. data/Gemfile.lock +24 -11
  5. data/bin/irb +1 -1
  6. data/docs/connection_pooling.md +98 -223
  7. data/familia.gemspec +1 -1
  8. data/lib/familia/connection.rb +3 -3
  9. data/lib/familia/core_ext.rb +2 -2
  10. data/lib/familia/features/expiration.rb +0 -1
  11. data/lib/familia/features/relatable_objects.rb +127 -0
  12. data/lib/familia/features.rb +7 -3
  13. data/lib/familia/horreum/class_methods.rb +18 -4
  14. data/lib/familia/secure_identifier.rb +129 -0
  15. data/lib/familia/utils.rb +7 -96
  16. data/lib/familia/version.rb +1 -1
  17. data/lib/familia.rb +3 -1
  18. data/try/configuration/scenarios_try.rb +43 -31
  19. data/try/core/connection_try.rb +1 -1
  20. data/try/core/errors_try.rb +10 -10
  21. data/try/core/extensions_try.rb +56 -23
  22. data/try/core/familia_extended_try.rb +3 -3
  23. data/try/core/familia_try.rb +2 -6
  24. data/try/core/middleware_try.rb +34 -40
  25. data/try/{pooling/connection_pool_test_try.rb → core/pools_try.rb} +2 -2
  26. data/try/core/secure_identifier_try.rb +104 -0
  27. data/try/core/tools_try.rb +52 -36
  28. data/try/core/utils_try.rb +0 -98
  29. data/try/datatypes/boolean_try.rb +6 -7
  30. data/try/datatypes/datatype_base_try.rb +2 -2
  31. data/try/datatypes/hash_try.rb +0 -1
  32. data/try/datatypes/list_try.rb +0 -1
  33. data/try/datatypes/set_try.rb +0 -2
  34. data/try/datatypes/sorted_set_try.rb +1 -2
  35. data/try/datatypes/string_try.rb +1 -2
  36. data/try/edge_cases/empty_identifiers_try.rb +42 -35
  37. data/try/edge_cases/hash_symbolization_try.rb +5 -5
  38. data/try/edge_cases/json_serialization_try.rb +12 -13
  39. data/try/edge_cases/race_conditions_try.rb +46 -49
  40. data/try/edge_cases/reserved_keywords_try.rb +103 -49
  41. data/try/edge_cases/string_coercion_try.rb +2 -2
  42. data/try/edge_cases/ttl_side_effects_try.rb +44 -25
  43. data/try/features/expiration_try.rb +2 -2
  44. data/try/features/quantization_try.rb +2 -2
  45. data/try/features/relatable_objects_try.rb +221 -0
  46. data/try/features/safe_dump_advanced_try.rb +13 -14
  47. data/try/features/safe_dump_try.rb +8 -8
  48. data/try/helpers/test_helpers.rb +10 -12
  49. data/try/horreum/base_try.rb +9 -9
  50. data/try/horreum/class_methods_try.rb +34 -28
  51. data/try/horreum/commands_try.rb +69 -33
  52. data/try/horreum/initialization_try.rb +4 -4
  53. data/try/horreum/relations_try.rb +13 -14
  54. data/try/horreum/serialization_try.rb +3 -3
  55. data/try/horreum/settings_try.rb +25 -31
  56. data/try/integration/cross_component_try.rb +45 -35
  57. data/try/models/customer_safe_dump_try.rb +4 -4
  58. data/try/models/customer_try.rb +22 -25
  59. data/try/models/datatype_base_try.rb +2 -4
  60. data/try/models/familia_object_try.rb +3 -4
  61. data/try/performance/benchmarks_try.rb +47 -38
  62. data/try/prototypes/atomic_saves_v4.rb +3 -3
  63. metadata +18 -15
  64. data/try/core/refinements_try.rb +0 -39
  65. /data/try/{pooling → prototypes/pooling}/README.md +0 -0
  66. /data/try/{pooling/configurable_stress_test_try.rb → prototypes/pooling/configurable_stress_test.rb} +0 -0
  67. /data/try/{pooling → prototypes/pooling}/lib/atomic_saves_v3_connection_pool_helpers.rb +0 -0
  68. /data/try/{pooling → prototypes/pooling}/lib/connection_pool_metrics.rb +0 -0
  69. /data/try/{pooling → prototypes/pooling}/lib/connection_pool_stress_test.rb +0 -0
  70. /data/try/{pooling → prototypes/pooling}/lib/connection_pool_threading_models.rb +0 -0
  71. /data/try/{pooling → prototypes/pooling}/lib/visualize_stress_results.rb +0 -0
  72. /data/try/{pooling/pool_siege_try.rb → prototypes/pooling/pool_siege.rb} +0 -0
  73. /data/try/{pooling/run_stress_tests_try.rb → prototypes/pooling/run_stress_tests.rb} +0 -0
@@ -1,55 +1,64 @@
1
+ # Performance benchmarks separate from stress tests
2
+
1
3
  require_relative '../helpers/test_helpers'
2
4
  require 'benchmark'
3
5
 
4
- # Performance benchmarks separate from stress tests
5
- group "Performance Benchmarks"
6
-
7
- setup do
8
- @user_class = Class.new(Familia::Horreum) do
9
- identifier :email
10
- field :name
11
- field :data
12
- end
6
+ ## serialization performance comparison
7
+ user_class = Class.new(Familia::Horreum) do
8
+ identifier_field :email
9
+ field :name
10
+ field :data
13
11
  end
14
12
 
15
- try "serialization performance comparison" do
16
- large_data = { items: (1..1000).to_a, metadata: "x" * 1000 }
13
+ large_data = { items: (1..1000).to_a, metadata: "x" * 1000 }
17
14
 
18
- json_time = Benchmark.realtime do
19
- 100.times { JSON.dump(large_data) }
20
- end
21
-
22
- familia_time = Benchmark.realtime do
23
- 100.times { Familia.distinguisher(large_data) }
24
- end
15
+ json_time = Benchmark.realtime do
16
+ 100.times { JSON.dump(large_data) }
17
+ end
25
18
 
26
- json_time > 0 && familia_time > 0
19
+ familia_time = Benchmark.realtime do
20
+ 100.times { Familia.distinguisher(large_data) }
27
21
  end
28
22
 
29
- try "bulk operations vs individual saves" do
30
- users = 100.times.map { |i|
31
- @user_class.new(email: "user#{i}@example.com", name: "User #{i}")
32
- }
23
+ json_time > 0 && familia_time > 0
24
+ #=!> StandardError
33
25
 
34
- individual_time = Benchmark.realtime do
35
- users.each(&:save)
36
- end
26
+ ## bulk operations vs individual saves
27
+ user_class = Class.new(Familia::Horreum) do
28
+ identifier_field :email
29
+ field :name
30
+ field :data
31
+ end
37
32
 
38
- # Cleanup for next test
39
- users.each(&:delete!)
33
+ users = 100.times.map { |i|
34
+ user_class.new(email: "user#{i}@example.com", name: "User #{i}")
35
+ }
40
36
 
41
- individual_time > 0
37
+ individual_time = Benchmark.realtime do
38
+ users.each(&:save)
42
39
  end
43
40
 
44
- try "Redis type access performance" do
45
- user = @user_class.new(email: "perf@example.com")
46
- user.save
41
+ # Cleanup for next test
42
+ users.each(&:delete!)
47
43
 
48
- access_time = Benchmark.realtime do
49
- 1000.times { user.set(:tags) }
50
- end
44
+ individual_time > 0
45
+ #=!> StandardError
51
46
 
52
- access_time > 0
53
- ensure
54
- user&.delete!
47
+ ## Redis type access performance
48
+ user_class = Class.new(Familia::Horreum) do
49
+ identifier_field :email
50
+ field :name
51
+ field :data
55
52
  end
53
+
54
+ user = user_class.new(email: "perf@example.com")
55
+ user.save
56
+
57
+ access_time = Benchmark.realtime do
58
+ 1000.times { user.set(:tags) }
59
+ end
60
+
61
+ result = access_time > 0
62
+ user.delete!
63
+ result
64
+ #=!> StandardError
@@ -1,7 +1,7 @@
1
1
  # try/prototypes/atomic_saves_v4.rb
2
2
 
3
3
  class BankAccount < Familia::Horreum
4
- class_sorted_set :relatable_object_ids
4
+ class_sorted_set :relatable_objids
5
5
 
6
6
  identifier_field :account_number
7
7
  field :account_number
@@ -89,7 +89,7 @@ class BankAccount < Familia::Horreum
89
89
  # does a class level method like `add` get its db connection from then?
90
90
  #
91
91
  # This is PURPOSE2, a major reason for implementing transactions. We want
92
- # to prevent our relatable_object_ids index from being updated if the
92
+ # to prevent our relatable_objids index from being updated if the
93
93
  # account save fails.
94
94
  add accnt
95
95
 
@@ -99,7 +99,7 @@ class BankAccount < Familia::Horreum
99
99
  end
100
100
 
101
101
  def add(accnt)
102
- relatable_object_ids.add Time.now.to_f, accnt.identifier
102
+ relatable_objids.add Time.now.to_f, accnt.identifier
103
103
  end
104
104
  end
105
105
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: familia
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre.pre
4
+ version: 2.0.0.pre3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum
@@ -100,19 +100,19 @@ dependencies:
100
100
  - !ruby/object:Gem::Version
101
101
  version: 3.1.1
102
102
  - !ruby/object:Gem::Dependency
103
- name: uri-redis
103
+ name: uri-valkey
104
104
  requirement: !ruby/object:Gem::Requirement
105
105
  requirements:
106
106
  - - "~>"
107
107
  - !ruby/object:Gem::Version
108
- version: '1.3'
108
+ version: '1.4'
109
109
  type: :runtime
110
110
  prerelease: false
111
111
  version_requirements: !ruby/object:Gem::Requirement
112
112
  requirements:
113
113
  - - "~>"
114
114
  - !ruby/object:Gem::Version
115
- version: '1.3'
115
+ version: '1.4'
116
116
  description: 'Familia: An ORM for Valkey-compatible databases in Ruby.. Organize and
117
117
  store ruby objects in Valkey/Redis'
118
118
  email: gems@solutious.com
@@ -151,6 +151,7 @@ files:
151
151
  - lib/familia/features.rb
152
152
  - lib/familia/features/expiration.rb
153
153
  - lib/familia/features/quantization.rb
154
+ - lib/familia/features/relatable_objects.rb
154
155
  - lib/familia/features/safe_dump.rb
155
156
  - lib/familia/horreum.rb
156
157
  - lib/familia/horreum/class_methods.rb
@@ -163,6 +164,7 @@ files:
163
164
  - lib/familia/logging.rb
164
165
  - lib/familia/multi_result.rb
165
166
  - lib/familia/refinements.rb
167
+ - lib/familia/secure_identifier.rb
166
168
  - lib/familia/settings.rb
167
169
  - lib/familia/utils.rb
168
170
  - lib/familia/version.rb
@@ -174,7 +176,8 @@ files:
174
176
  - try/core/familia_extended_try.rb
175
177
  - try/core/familia_try.rb
176
178
  - try/core/middleware_try.rb
177
- - try/core/refinements_try.rb
179
+ - try/core/pools_try.rb
180
+ - try/core/secure_identifier_try.rb
178
181
  - try/core/settings_try.rb
179
182
  - try/core/tools_try.rb
180
183
  - try/core/utils_try.rb
@@ -194,6 +197,7 @@ files:
194
197
  - try/edge_cases/ttl_side_effects_try.rb
195
198
  - try/features/expiration_try.rb
196
199
  - try/features/quantization_try.rb
200
+ - try/features/relatable_objects_try.rb
197
201
  - try/features/safe_dump_advanced_try.rb
198
202
  - try/features/safe_dump_try.rb
199
203
  - try/helpers/test_helpers.rb
@@ -210,22 +214,21 @@ files:
210
214
  - try/models/datatype_base_try.rb
211
215
  - try/models/familia_object_try.rb
212
216
  - try/performance/benchmarks_try.rb
213
- - try/pooling/README.md
214
- - try/pooling/configurable_stress_test_try.rb
215
- - try/pooling/connection_pool_test_try.rb
216
- - try/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb
217
- - try/pooling/lib/connection_pool_metrics.rb
218
- - try/pooling/lib/connection_pool_stress_test.rb
219
- - try/pooling/lib/connection_pool_threading_models.rb
220
- - try/pooling/lib/visualize_stress_results.rb
221
- - try/pooling/pool_siege_try.rb
222
- - try/pooling/run_stress_tests_try.rb
223
217
  - try/prototypes/atomic_saves_v1_context_proxy.rb
224
218
  - try/prototypes/atomic_saves_v2_connection_switching.rb
225
219
  - try/prototypes/atomic_saves_v3_connection_pool.rb
226
220
  - try/prototypes/atomic_saves_v4.rb
227
221
  - try/prototypes/lib/atomic_saves_v2_connection_switching_helpers.rb
228
222
  - try/prototypes/lib/atomic_saves_v3_connection_pool_helpers.rb
223
+ - try/prototypes/pooling/README.md
224
+ - try/prototypes/pooling/configurable_stress_test.rb
225
+ - try/prototypes/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb
226
+ - try/prototypes/pooling/lib/connection_pool_metrics.rb
227
+ - try/prototypes/pooling/lib/connection_pool_stress_test.rb
228
+ - try/prototypes/pooling/lib/connection_pool_threading_models.rb
229
+ - try/prototypes/pooling/lib/visualize_stress_results.rb
230
+ - try/prototypes/pooling/pool_siege.rb
231
+ - try/prototypes/pooling/run_stress_tests.rb
229
232
  homepage: https://github.com/delano/familia
230
233
  licenses:
231
234
  - MIT
@@ -1,39 +0,0 @@
1
- require_relative '../helpers/test_helpers'
2
-
3
- # Test Familia refinements
4
- group "Familia Refinements"
5
-
6
- using Familia::FlexibleHashAccess
7
-
8
- try "FlexibleHashAccess allows string/symbol key interchange" do
9
- hash = { name: "test", "email" => "test@example.com" }
10
-
11
- hash[:name] == "test" &&
12
- hash["name"] == "test" &&
13
- hash[:email] == "test@example.com" &&
14
- hash["email"] == "test@example.com"
15
- end
16
-
17
- try "LoggerTraceRefinement adds trace level when FAMILIA_TRACE enabled" do
18
- old_env = ENV['FAMILIA_TRACE']
19
- ENV['FAMILIA_TRACE'] = '1'
20
-
21
- logger = Logger.new(STDOUT)
22
- logger.respond_to?(:trace)
23
- ensure
24
- ENV['FAMILIA_TRACE'] = old_env
25
- end
26
-
27
- try "FAMILIA_TRACE environment control" do
28
- old_env = ENV['FAMILIA_TRACE']
29
-
30
- ENV['FAMILIA_TRACE'] = '1'
31
- trace_enabled = ENV['FAMILIA_TRACE']
32
-
33
- ENV['FAMILIA_TRACE'] = nil
34
- trace_disabled = ENV['FAMILIA_TRACE']
35
-
36
- trace_enabled == '1' && trace_disabled.nil?
37
- ensure
38
- ENV['FAMILIA_TRACE'] = old_env
39
- end
File without changes