async-utilization 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ddd4fc21308eeba6b47fbd44df20d4694ee4bd5b78488a44395d0ab5e2da500
4
- data.tar.gz: 8699da59ebaa0497ca112cf4f1ca65805935d11061b9ed6e1475a56f05a58795
3
+ metadata.gz: bae4a631b828e8a236bcee48919460731116a2a521031f16ae8f11ed03234407
4
+ data.tar.gz: 3ca70a5a98f4ba4515d3f30271561e0764912cf1f7983d602307bf6ba869b296
5
5
  SHA512:
6
- metadata.gz: '079cbc3d3a93cda55ebcce48f93c23e5460db7ae8019336b442d0a24ffd783ec6e614cd2d36fc7c937f388cf729ce7d4d6944c5aefae754c4165560a4f353a98'
7
- data.tar.gz: '049b0ea1ae9d8bc15c12aa69c3d595e32424d1d200003425067f70111f804079fda1f23ef21cc3ed0a0a0d698b36e3b00cbe0cb9ce3803dde197c8e03c8599b1'
6
+ metadata.gz: 0ae6db6c1108dcc43ef14a38b6fb88de1c882deeeac95df60c843bac006a4de88c6d6344128f0cd9e53344572391ab6833b4a2f36ebbea741fceb1b22e26ecef
7
+ data.tar.gz: 664e8d90bee5423e467aa01a502d043838d2a139fbd53bda712c27422839abe501e1a250cb760492f95b79f0e9245dde2cf09d33fcfba85a11435bc97be23f16
checksums.yaml.gz.sig CHANGED
Binary file
@@ -3,8 +3,6 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2026, by Samuel Williams.
5
5
 
6
- require "thread/local"
7
-
8
6
  module Async
9
7
  module Utilization
10
8
  # Registry for emitting utilization metrics.
@@ -12,8 +10,9 @@ module Async
12
10
  # The registry tracks values directly and notifies a registered observer
13
11
  # when values change. The observer (like Observer) can write to its backend.
14
12
  #
15
- # Each thread gets its own instance of the registry, providing
16
- # thread-local behavior through the thread-local gem.
13
+ # Registries should be explicitly created and passed to components that need them.
14
+ # In service contexts, registries are typically created via the evaluator and
15
+ # shared across components within the same service instance.
17
16
  #
18
17
  # When an observer is added, it is immediately notified of all current values
19
18
  # so it can sync its state. When values change, the observer is notified.
@@ -36,7 +35,6 @@ module Async
36
35
  # observer = Async::Utilization::Observer.open(schema, "/path/to/shm", 4096, 0)
37
36
  # registry.observer = observer
38
37
  class Registry
39
- extend Thread::Local
40
38
 
41
39
  # Initialize a new registry.
42
40
  def initialize
@@ -7,6 +7,6 @@
7
7
  module Async
8
8
  # @namespace
9
9
  module Utilization
10
- VERSION = "0.1.0"
10
+ VERSION = "0.2.0"
11
11
  end
12
12
  end
@@ -15,42 +15,9 @@ module Async
15
15
  #
16
16
  # This module provides a convenient interface for tracking utilization metrics
17
17
  # that can be synchronized to shared memory for inter-process communication.
18
- # Each thread gets its own instance of the underlying {Registry}, providing
19
- # thread-local behavior.
18
+ # Registries should be explicitly created and passed to components that need them.
20
19
  #
21
20
  # See the {file:guides/getting-started/readme.md Getting Started} guide for usage examples.
22
21
  module Utilization
23
- # Set the observer for utilization metrics.
24
- #
25
- # When an observer is set, it is notified of all current metric values
26
- # so it can sync its state. The observer must implement `set(field, value)`.
27
- #
28
- # Delegates to the thread-local {Registry} instance.
29
- #
30
- # @parameter observer [#set] The observer to set.
31
- def self.observer=(observer)
32
- Registry.instance.observer = observer
33
- end
34
-
35
- # Get a cached metric reference for a field.
36
- #
37
- # Returns a {Metric} instance that caches all details needed for fast writes
38
- # to shared memory, avoiding hash lookups on the fast path.
39
- #
40
- # This is the recommended way to access metrics for optimal performance.
41
- #
42
- # Delegates to the thread-local {Registry} instance.
43
- #
44
- # @parameter field [Symbol] The field name to get a metric for.
45
- # @returns [Metric] A metric instance for the given field.
46
- # @example Get a metric and increment it:
47
- # current_requests = Async::Utilization.metric(:current_requests)
48
- # current_requests.increment
49
- # current_requests.increment do
50
- # # Handle request - auto-decrements when block completes
51
- # end
52
- def self.metric(field)
53
- Registry.instance.metric(field)
54
- end
55
22
  end
56
23
  end
@@ -29,28 +29,24 @@ describe Async::Utilization::Metric do
29
29
  Async::Utilization::Observer.open(schema, shm_path, segment_size, offset)
30
30
  end
31
31
 
32
+ let(:registry) {Async::Utilization::Registry.new}
33
+
32
34
  before do
33
35
  File.open(shm_path, "w+b") do |file|
34
36
  file.truncate(file_size)
35
37
  end
36
-
37
- # Reset the registry to ensure clean state between tests
38
- registry = Async::Utilization::Registry.instance
39
- registry.instance_variable_set(:@values, Hash.new(0))
40
- registry.instance_variable_set(:@metrics, {})
41
- registry.instance_variable_set(:@observer, nil)
42
38
  end
43
39
 
44
40
  it "can create a metric from a field name" do
45
- metric = Async::Utilization.metric(:total_requests)
41
+ metric = registry.metric(:total_requests)
46
42
 
47
43
  expect(metric).to be_a(Async::Utilization::Metric)
48
44
  expect(metric.name).to be == :total_requests
49
45
  end
50
46
 
51
47
  it "can increment a metric" do
52
- Async::Utilization.observer = observer
53
- metric = Async::Utilization.metric(:total_requests)
48
+ registry.observer = observer
49
+ metric = registry.metric(:total_requests)
54
50
 
55
51
  value = metric.increment
56
52
  expect(value).to be == 1
@@ -62,8 +58,8 @@ describe Async::Utilization::Metric do
62
58
  end
63
59
 
64
60
  it "can decrement a metric" do
65
- Async::Utilization.observer = observer
66
- metric = Async::Utilization.metric(:total_requests)
61
+ registry.observer = observer
62
+ metric = registry.metric(:total_requests)
67
63
 
68
64
  metric.increment
69
65
  metric.increment
@@ -74,8 +70,8 @@ describe Async::Utilization::Metric do
74
70
  end
75
71
 
76
72
  it "can set a metric value" do
77
- Async::Utilization.observer = observer
78
- metric = Async::Utilization.metric(:total_requests)
73
+ registry.observer = observer
74
+ metric = registry.metric(:total_requests)
79
75
 
80
76
  metric.set(42)
81
77
  expect(metric.value).to be == 42
@@ -85,8 +81,8 @@ describe Async::Utilization::Metric do
85
81
  end
86
82
 
87
83
  it "can increment with auto-decrement block" do
88
- Async::Utilization.observer = observer
89
- metric = Async::Utilization.metric(:active_requests)
84
+ registry.observer = observer
85
+ metric = registry.metric(:active_requests)
90
86
 
91
87
  metric.increment do
92
88
  expect(metric.value).to be == 1
@@ -96,8 +92,8 @@ describe Async::Utilization::Metric do
96
92
  end
97
93
 
98
94
  it "decrements even if block raises an error" do
99
- Async::Utilization.observer = observer
100
- metric = Async::Utilization.metric(:active_requests)
95
+ registry.observer = observer
96
+ metric = registry.metric(:active_requests)
101
97
 
102
98
  begin
103
99
  metric.increment do
@@ -111,8 +107,8 @@ describe Async::Utilization::Metric do
111
107
  end
112
108
 
113
109
  it "writes directly to shared memory when observer is set" do
114
- Async::Utilization.observer = observer
115
- metric = Async::Utilization.metric(:total_requests)
110
+ registry.observer = observer
111
+ metric = registry.metric(:total_requests)
116
112
 
117
113
  metric.set(42)
118
114
 
@@ -122,8 +118,8 @@ describe Async::Utilization::Metric do
122
118
  end
123
119
 
124
120
  it "invalidates cache when observer changes" do
125
- Async::Utilization.observer = observer
126
- metric = Async::Utilization.metric(:total_requests)
121
+ registry.observer = observer
122
+ metric = registry.metric(:total_requests)
127
123
 
128
124
  # Set a value - cache should be built
129
125
  metric.set(10)
@@ -139,7 +135,7 @@ describe Async::Utilization::Metric do
139
135
  new_observer = Async::Utilization::Observer.open(new_schema, new_shm_path, segment_size, 0)
140
136
 
141
137
  # Change observer - cache should be invalidated
142
- Async::Utilization.observer = new_observer
138
+ registry.observer = new_observer
143
139
 
144
140
  # Set a new value - cache should be rebuilt
145
141
  metric.set(20)
@@ -151,7 +147,7 @@ describe Async::Utilization::Metric do
151
147
  end
152
148
 
153
149
  it "works without an observer" do
154
- metric = Async::Utilization.metric(:total_requests)
150
+ metric = registry.metric(:total_requests)
155
151
 
156
152
  # Should work fine without observer (uses fallback path)
157
153
  metric.increment
@@ -161,21 +157,21 @@ describe Async::Utilization::Metric do
161
157
  expect(metric.value).to be == 5
162
158
 
163
159
  # Set observer and verify it works with fast path
164
- Async::Utilization.observer = observer
160
+ registry.observer = observer
165
161
  metric.set(10)
166
162
  expect(metric.value).to be == 10
167
163
  end
168
164
 
169
165
  it "returns the same metric instance for the same field" do
170
- metric1 = Async::Utilization.metric(:total_requests)
171
- metric2 = Async::Utilization.metric(:total_requests)
166
+ metric1 = registry.metric(:total_requests)
167
+ metric2 = registry.metric(:total_requests)
172
168
 
173
169
  expect(metric1).to be == metric2
174
170
  end
175
171
 
176
172
  it "falls back to observer.set when write_direct fails" do
177
- Async::Utilization.observer = observer
178
- metric = Async::Utilization.metric(:total_requests)
173
+ registry.observer = observer
174
+ metric = registry.metric(:total_requests)
179
175
 
180
176
  # Force cache to be invalid by invalidating it
181
177
  metric.invalidate
@@ -190,8 +186,8 @@ describe Async::Utilization::Metric do
190
186
  end
191
187
 
192
188
  it "handles write errors gracefully" do
193
- Async::Utilization.observer = observer
194
- metric = Async::Utilization.metric(:total_requests)
189
+ registry.observer = observer
190
+ metric = registry.metric(:total_requests)
195
191
 
196
192
  # Set a value first to build the cache
197
193
  metric.set(10)
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-utilization
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
metadata.gz.sig CHANGED
Binary file