ff-ruby-server-sdk 1.4.1 → 1.4.3

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: e2bcc6b6312ee2462bbf6a2a689ddee47c6000bc010db561eb72b5204a7c8d8f
4
- data.tar.gz: 7058cd57f6e72cb2c649b51071eaebed405ff3aac691f4aa186a096da70692b9
3
+ metadata.gz: 21ede6e2de94f3ed2aec871c40b8dbee7a9feec6adbdec14726e5237caedbb0b
4
+ data.tar.gz: e89c0b57ae84666c87dccf6b25a67f0d0ca77990220ee014c9abe1a1225993c9
5
5
  SHA512:
6
- metadata.gz: 85ff6d9cda7f5579a7eeedce0f7ea293ccf95ff426b413f53aa09c22a0caa4bc1890607c63d67a0b3c58295d537f830a85e81ae45a2a6afafdd4d0521daa60df
7
- data.tar.gz: '089aeb5abb536d43e118bade66a80fde7b70e1b74ce1a96fa32d53d7a4a61f08ec7b4c5d35a987e60f11fc4a8791b7233bad01c742bfc4ebc5545a738a13038d'
6
+ metadata.gz: 943c5b49c1bf887dd6ff24edce3e03cd2bff1badde8dd0802fdc8bda042e2e260b2cd7929c18189ec9dfb39f8b8189bec5b49e32ab021c722a17da71268bcccb
7
+ data.tar.gz: 5f32b626e8c49fd3074401db1ef6810acfb79b4cdba6f03e7f55e31a2a6e921b73ce273d71780f30dc90f18e74f691e4a203da6503bb0a473a60e49b0b56d37b
@@ -1,56 +1,23 @@
1
-
1
+ require 'singleton'
2
2
  require_relative "../../generated/lib/openapi_client"
3
3
  require_relative "../common/closeable"
4
4
  require_relative "inner_client"
5
5
 
6
6
  class CfClient < Closeable
7
-
8
- # Static:
9
- class << self
10
-
11
- @@instance = CfClient.new
12
-
13
- def instance
14
-
15
- @@instance
7
+ include Singleton
8
+
9
+ def init(api_key, config, connector = nil)
10
+ # Only initialize if @client is nil to avoid reinitialization
11
+ unless @client
12
+ @config = config || ConfigBuilder.new.build
13
+ @client = InnerClient.new(api_key, @config, connector)
14
+ @config.logger.debug "Client initialized with API key: #{api_key}"
16
15
  end
16
+ @client
17
17
  end
18
18
 
19
- # Static - End
20
-
21
- def initialize(api_key = nil, config = nil, connector = nil)
22
-
23
- if config == nil
24
-
25
- @config = ConfigBuilder.new.build
26
- else
27
-
28
- @config = config
29
- end
30
-
31
- @client = InnerClient.new(api_key, config, connector)
32
-
33
- @config.logger.debug "Client (1): " + @client.to_s
34
- end
35
-
36
- def init(api_key = nil, config = nil, connector = nil)
37
-
38
- if @client == nil
39
-
40
- @config = config
41
-
42
- @client = InnerClient.new(
43
-
44
- api_key = api_key,
45
- config = config,
46
- connector = connector
47
- )
48
-
49
- @config.logger.debug "Client (2): " + @client.to_s
50
- end
51
- end
52
19
 
53
- def wait_for_initialization(timeout_ms: nil)
20
+ def wait_for_initialization(timeout_ms: nil)
54
21
  if @client != nil
55
22
  @client.wait_for_initialization(timeout: timeout_ms)
56
23
  end
@@ -78,28 +78,25 @@ class MetricsProcessor < Closeable
78
78
 
79
79
  @executor = Concurrent::FixedThreadPool.new(10)
80
80
 
81
+ # Used for locking the evalution and target metrics maps before we clone them
82
+ @metric_maps_mutex = Mutex.new
81
83
  @evaluation_metrics = FrequencyMap.new
82
84
  @target_metrics = Concurrent::Map.new
83
85
 
84
86
  # Keep track of targets that have already been sent to avoid sending them again
85
87
  @seen_targets = Concurrent::Map.new
86
88
 
87
- @max_buffer_size = config.buffer_size - 1
88
-
89
- # Max 100k targets per interval
90
- @max_targets_buffer_size = 100000
91
-
92
- @evaluation_warning_issued = Concurrent::AtomicBoolean.new
93
- @target_warning_issued = Concurrent::AtomicBoolean.new
94
-
95
89
  @callback.on_metrics_ready
96
90
  end
97
91
 
98
92
  def start
99
- @config.logger.debug "Starting metrics processor with request interval: " + @config.frequency.to_s
100
- start_async
93
+ @config.logger.debug "Starting metrics processor with request interval: #{@config.frequency}"
94
+ if @running
95
+ @config.logger.warn "Metrics processor is already running."
96
+ else
97
+ start_async
98
+ end
101
99
  end
102
-
103
100
  def stop
104
101
  @config.logger.debug "Stopping metrics processor"
105
102
  stop_async
@@ -139,28 +136,13 @@ class MetricsProcessor < Closeable
139
136
  return
140
137
  end
141
138
 
142
-
143
- if @evaluation_metrics.size > @max_buffer_size
144
- unless @evaluation_warning_issued.true?
145
- SdkCodes.warn_metrics_evaluations_max_size_exceeded(@config.logger)
146
- @evaluation_warning_issued.make_true
147
- end
148
- return
149
- end
150
-
151
139
  event = MetricsEvent.new(feature_config, GLOBAL_TARGET, variation, @config.logger)
152
- @evaluation_metrics.increment event
140
+ @metric_maps_mutex.synchronize do
141
+ @evaluation_metrics.increment event
142
+ end
153
143
  end
154
144
 
155
145
  def register_target_metric(target)
156
- if @target_metrics.size > @max_targets_buffer_size
157
- unless @target_warning_issued.true?
158
- SdkCodes.warn_metrics_targets_max_size_exceeded(@config.logger)
159
- @target_warning_issued.make_true
160
- end
161
- return
162
- end
163
-
164
146
  if target.is_private
165
147
  return
166
148
  end
@@ -171,34 +153,39 @@ class MetricsProcessor < Closeable
171
153
  return
172
154
  end
173
155
 
174
- @target_metrics.put(target.identifier, target)
156
+ @metric_maps_mutex.synchronize do
157
+ @target_metrics.put(target.identifier, target)
158
+ end
175
159
  end
176
160
 
177
161
  def run_one_iteration
178
162
  send_data_and_reset_cache(@evaluation_metrics, @target_metrics)
179
-
180
- @config.logger.debug "metrics: frequency map size #{@evaluation_metrics.size}. targets map size #{@target_metrics.size} global target size #{@seen_targets.size}"
181
163
  end
182
164
 
183
165
  def send_data_and_reset_cache(evaluation_metrics_map, target_metrics_map)
184
- # Clone and clear evaluation metrics map
185
- evaluation_metrics_map_clone = Concurrent::Map.new
166
+ # A single lock is used to synchronise access to both the evaluation and target metrics maps.
167
+ # While separate locks could be applied to each map individually, we want an interval's eval/target
168
+ # metrics to be processed in an atomic unit.
169
+ evaluation_metrics_map_clone, target_metrics_map_clone = @metric_maps_mutex.synchronize do
170
+
171
+ clone_evaluations = Concurrent::Map.new
172
+ clone_targets = Concurrent::Map.new
173
+ # Clone and clear evaluation metrics map
174
+ evaluation_metrics_map.each_pair do |key, value|
175
+ clone_evaluations[key] = value
176
+ end
186
177
 
187
- evaluation_metrics_map.each_pair do |key, value|
188
- evaluation_metrics_map_clone[key] = value
189
- end
178
+ evaluation_metrics_map.clear
190
179
 
191
- evaluation_metrics_map.clear
192
- target_metrics_map_clone = Concurrent::Map.new
180
+ target_metrics_map.each_pair do |key, value|
181
+ clone_targets[key] = value
182
+ end
193
183
 
194
- target_metrics_map.each_pair do |key, value|
195
- target_metrics_map_clone[key] = value
196
- end
184
+ target_metrics_map.clear
197
185
 
198
- target_metrics_map.clear
186
+ [clone_evaluations, clone_targets]
199
187
 
200
- @evaluation_warning_issued.make_false
201
- @target_warning_issued.make_false
188
+ end
202
189
 
203
190
  metrics = prepare_summary_metrics_body(evaluation_metrics_map_clone, target_metrics_map_clone)
204
191
 
@@ -286,6 +273,7 @@ class MetricsProcessor < Closeable
286
273
  def start_async
287
274
  @config.logger.debug "Async starting: " + self.to_s
288
275
  @ready = true
276
+ @running = true
289
277
  @thread = Thread.new do
290
278
  @config.logger.debug "Async started: " + self.to_s
291
279
  while @ready do
@@ -303,8 +291,14 @@ class MetricsProcessor < Closeable
303
291
  def stop_async
304
292
  @ready = false
305
293
  @initialized = false
294
+ if @thread && @thread.alive?
295
+ @thread.join
296
+ @config.logger.debug "Metrics processor thread has been stopped."
297
+ end
298
+ @running = false
306
299
  end
307
300
 
301
+
308
302
  def get_version
309
303
  Ff::Ruby::Server::Sdk::VERSION
310
304
  end
@@ -5,7 +5,7 @@ module Ff
5
5
  module Server
6
6
  module Sdk
7
7
 
8
- VERSION = "1.4.1"
8
+ VERSION = "1.4.3"
9
9
  end
10
10
  end
11
11
  end
data/scripts/sdk_specs.sh CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/bin/bash
2
2
 
3
3
  export ff_ruby_sdk="ff-ruby-server-sdk"
4
- export ff_ruby_sdk_version="1.4.1"
4
+ export ff_ruby_sdk_version="1.4.3"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ff-ruby-server-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - 'Miloš Vasić, cyr.: Милош Васић'
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-12 00:00:00.000000000 Z
11
+ date: 2024-11-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake