unleash 6.4.0 → 6.5.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 +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +51 -1
- data/lib/unleash/backup_file_reader.rb +24 -0
- data/lib/unleash/backup_file_writer.rb +21 -0
- data/lib/unleash/client.rb +5 -0
- data/lib/unleash/configuration.rb +6 -6
- data/lib/unleash/environment_resolver.rb +27 -0
- data/lib/unleash/impact_metrics.rb +43 -0
- data/lib/unleash/metrics_reporter.rb +26 -4
- data/lib/unleash/spec_version.rb +1 -1
- data/lib/unleash/streaming_client_executor.rb +29 -0
- data/lib/unleash/streaming_event_processor.rb +3 -1
- data/lib/unleash/toggle_fetcher.rb +8 -40
- data/lib/unleash/version.rb +1 -1
- data/unleash-client.gemspec +1 -2
- metadata +8 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f2aacf28333e06f4ca46369b9ece6fd1472a8e363cdc4a0fe1aeb0810d879a2
|
|
4
|
+
data.tar.gz: bc8e366ec18bff858f835260af79650ab6179daa6af93bf84a675eb3d74ad904
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9c397ef806b4e77fb8a1d8afbacd3ded420f5979fcf1999b03e524d77dca3f04205fa28e4a1e83037c7670837654c5f0e193f74b53654dedb034c1e9016fb22e
|
|
7
|
+
data.tar.gz: 07bfa665ecb17ffbe86b9dbb66c3247d824a27e27d846000f181ad5783d8af3a6e9adb9a47d2e2f37732bec80c137683609b63726cd58616164efe464a4fcd4c
|
data/CHANGELOG.md
CHANGED
|
@@ -13,6 +13,16 @@ Note: These changes are not considered notable:
|
|
|
13
13
|
|
|
14
14
|
## [Unreleased]
|
|
15
15
|
|
|
16
|
+
## [6.5.0] - 2026-01-29
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
- Impact metrics
|
|
20
|
+
|
|
21
|
+
## [6.4.1] - 2025-12-04
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- Bump yggdrasil-engine
|
|
25
|
+
|
|
16
26
|
## [6.4.0] - 2025-08-12
|
|
17
27
|
### Added
|
|
18
28
|
- Experimental streaming support
|
data/README.md
CHANGED
|
@@ -28,7 +28,7 @@ You can use this client with [Unleash Enterprise](https://www.getunleash.io/pric
|
|
|
28
28
|
Add this line to your application's Gemfile:
|
|
29
29
|
|
|
30
30
|
```ruby
|
|
31
|
-
gem 'unleash', '~> 6.
|
|
31
|
+
gem 'unleash', '~> 6.5.0'
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
And then execute:
|
|
@@ -534,6 +534,56 @@ Unleash.configure do |config|
|
|
|
534
534
|
end
|
|
535
535
|
```
|
|
536
536
|
|
|
537
|
+
## Impact metrics
|
|
538
|
+
|
|
539
|
+
Impact metrics are lightweight, application-level time-series metrics stored and visualized directly inside Unleash. They allow you to connect specific application data, such as request counts, error rates, or latency, to your feature flags and release plans.
|
|
540
|
+
|
|
541
|
+
These metrics help validate feature impact and automate release processes. For instance, you can monitor usage patterns or performance to determine if a feature meets its goals.
|
|
542
|
+
|
|
543
|
+
The SDK automatically attaches context labels to metrics: `appName` and `environment`.
|
|
544
|
+
|
|
545
|
+
### Counters
|
|
546
|
+
|
|
547
|
+
Use counters for cumulative values that only increase (total requests, errors):
|
|
548
|
+
|
|
549
|
+
```ruby
|
|
550
|
+
client = Unleash::Client.new
|
|
551
|
+
|
|
552
|
+
client.impact_metrics.define_counter(
|
|
553
|
+
'request_count',
|
|
554
|
+
'Total number of HTTP requests processed'
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
client.impact_metrics.increment_counter('request_count')
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### Gauges
|
|
561
|
+
|
|
562
|
+
Use gauges for point-in-time values that can go up or down:
|
|
563
|
+
|
|
564
|
+
```ruby
|
|
565
|
+
client.impact_metrics.define_gauge(
|
|
566
|
+
'total_users',
|
|
567
|
+
'Total number of registered users'
|
|
568
|
+
)
|
|
569
|
+
|
|
570
|
+
client.impact_metrics.update_gauge('total_users', user_count)
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### Histograms
|
|
574
|
+
|
|
575
|
+
Histograms measure value distribution (request duration, response size):
|
|
576
|
+
|
|
577
|
+
```ruby
|
|
578
|
+
client.impact_metrics.define_histogram(
|
|
579
|
+
'request_time_ms',
|
|
580
|
+
'Time taken to process a request in milliseconds',
|
|
581
|
+
[50, 100, 200, 500, 1000]
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
client.impact_metrics.observe_histogram('request_time_ms', 125)
|
|
585
|
+
```
|
|
586
|
+
|
|
537
587
|
## Development
|
|
538
588
|
|
|
539
589
|
After checking out the repo, run `bin/setup` to install dependencies.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'unleash/configuration'
|
|
2
|
+
|
|
3
|
+
module Unleash
|
|
4
|
+
class BackupFileReader
|
|
5
|
+
def self.read!
|
|
6
|
+
Unleash.logger.debug "read!()"
|
|
7
|
+
|
|
8
|
+
backup_file = Unleash.configuration.backup_file
|
|
9
|
+
return nil unless File.exist?(backup_file)
|
|
10
|
+
|
|
11
|
+
File.read(backup_file)
|
|
12
|
+
rescue IOError => e
|
|
13
|
+
# :nocov:
|
|
14
|
+
Unleash.logger.error "Unable to read the backup_file: #{e}"
|
|
15
|
+
# :nocov:
|
|
16
|
+
nil
|
|
17
|
+
rescue StandardError => e
|
|
18
|
+
# :nocov:
|
|
19
|
+
Unleash.logger.error "Unable to extract valid data from backup_file. Exception thrown: #{e}"
|
|
20
|
+
# :nocov:
|
|
21
|
+
nil
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'unleash/configuration'
|
|
2
|
+
|
|
3
|
+
module Unleash
|
|
4
|
+
class BackupFileWriter
|
|
5
|
+
def self.save!(toggle_data)
|
|
6
|
+
Unleash.logger.debug "Will save toggles to disk now"
|
|
7
|
+
|
|
8
|
+
backup_file = Unleash.configuration.backup_file
|
|
9
|
+
backup_file_tmp = "#{backup_file}.tmp-#{Process.pid}"
|
|
10
|
+
|
|
11
|
+
File.open(backup_file_tmp, "w") do |file|
|
|
12
|
+
file.write(toggle_data)
|
|
13
|
+
end
|
|
14
|
+
File.rename(backup_file_tmp, backup_file)
|
|
15
|
+
rescue StandardError => e
|
|
16
|
+
# This is not really the end of the world. Swallowing the exception.
|
|
17
|
+
Unleash.logger.error "Unable to save backup file. Exception thrown #{e.class}:'#{e}'"
|
|
18
|
+
Unleash.logger.error "stacktrace: #{e.backtrace}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/unleash/client.rb
CHANGED
|
@@ -6,12 +6,15 @@ require 'unleash/streaming_client_executor'
|
|
|
6
6
|
require 'unleash/variant'
|
|
7
7
|
require 'unleash/util/http'
|
|
8
8
|
require 'unleash/util/event_source_wrapper'
|
|
9
|
+
require 'unleash/environment_resolver'
|
|
10
|
+
require 'unleash/impact_metrics'
|
|
9
11
|
require 'logger'
|
|
10
12
|
require 'time'
|
|
11
13
|
|
|
12
14
|
module Unleash
|
|
13
15
|
class Client
|
|
14
16
|
attr_accessor :fetcher_scheduled_executor, :metrics_scheduled_executor
|
|
17
|
+
attr_reader :impact_metrics
|
|
15
18
|
|
|
16
19
|
# rubocop:disable Metrics/AbcSize
|
|
17
20
|
def initialize(*opts)
|
|
@@ -23,6 +26,8 @@ module Unleash
|
|
|
23
26
|
Unleash.engine = YggdrasilEngine.new
|
|
24
27
|
Unleash.engine.register_custom_strategies(Unleash.configuration.strategies.custom_strategies)
|
|
25
28
|
|
|
29
|
+
@impact_metrics = ImpactMetrics.new(Unleash.engine, Unleash.configuration.app_name)
|
|
30
|
+
|
|
26
31
|
Unleash.toggle_fetcher = Unleash::ToggleFetcher.new Unleash.engine unless Unleash.configuration.streaming_mode?
|
|
27
32
|
|
|
28
33
|
if Unleash.configuration.disable_client
|
|
@@ -107,6 +107,12 @@ module Unleash
|
|
|
107
107
|
self.experimental_mode[:format] == 'delta'
|
|
108
108
|
end
|
|
109
109
|
|
|
110
|
+
def generate_custom_http_headers
|
|
111
|
+
return self.custom_http_headers.call if self.custom_http_headers.respond_to?(:call)
|
|
112
|
+
|
|
113
|
+
self.custom_http_headers
|
|
114
|
+
end
|
|
115
|
+
|
|
110
116
|
private
|
|
111
117
|
|
|
112
118
|
def set_defaults
|
|
@@ -153,12 +159,6 @@ module Unleash
|
|
|
153
159
|
raise ArgumentError, "custom_http_headers must be a Hash or a Proc."
|
|
154
160
|
end
|
|
155
161
|
|
|
156
|
-
def generate_custom_http_headers
|
|
157
|
-
return self.custom_http_headers.call if self.custom_http_headers.respond_to?(:call)
|
|
158
|
-
|
|
159
|
-
self.custom_http_headers
|
|
160
|
-
end
|
|
161
|
-
|
|
162
162
|
def set_option(opt, val)
|
|
163
163
|
__send__("#{opt}=", val)
|
|
164
164
|
rescue NoMethodError
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Unleash
|
|
2
|
+
class EnvironmentResolver
|
|
3
|
+
def self.extract_environment_from_custom_headers(custom_headers)
|
|
4
|
+
authorization_header = extract_authorization_header(custom_headers)
|
|
5
|
+
extract_environment_from_header(authorization_header)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.extract_authorization_header(custom_headers)
|
|
9
|
+
return nil if custom_headers.nil? || !custom_headers.is_a?(Hash)
|
|
10
|
+
|
|
11
|
+
key = custom_headers.keys.find{ |k| k.to_s.downcase == 'authorization' }
|
|
12
|
+
custom_headers[key] if key
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.extract_environment_from_header(authorization_header)
|
|
16
|
+
return nil if authorization_header.nil? || authorization_header.empty?
|
|
17
|
+
|
|
18
|
+
after_colon = authorization_header.split(':', 2)[1]
|
|
19
|
+
return nil unless after_colon&.include?('.')
|
|
20
|
+
|
|
21
|
+
environment = after_colon.split('.')[0]
|
|
22
|
+
environment unless environment.empty?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private_class_method :extract_authorization_header, :extract_environment_from_header
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Unleash
|
|
2
|
+
class ImpactMetrics
|
|
3
|
+
def initialize(engine, app_name)
|
|
4
|
+
@engine = engine
|
|
5
|
+
@app_name = app_name
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def define_counter(name, help_text)
|
|
9
|
+
@engine.define_counter(name, help_text)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def increment_counter(name, value = 1)
|
|
13
|
+
@engine.inc_counter(name, value, base_labels)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def define_gauge(name, help_text)
|
|
17
|
+
@engine.define_gauge(name, help_text)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def update_gauge(name, value)
|
|
21
|
+
@engine.set_gauge(name, value, base_labels)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def define_histogram(name, help_text, buckets = nil)
|
|
25
|
+
@engine.define_histogram(name, help_text, buckets)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def observe_histogram(name, value)
|
|
29
|
+
@engine.observe_histogram(name, value, base_labels)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def base_labels
|
|
35
|
+
{
|
|
36
|
+
'appName' => @app_name,
|
|
37
|
+
'environment' => EnvironmentResolver.extract_environment_from_custom_headers(
|
|
38
|
+
Unleash.configuration.generate_custom_http_headers
|
|
39
|
+
) || Unleash.configuration.environment
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -23,7 +23,8 @@ module Unleash
|
|
|
23
23
|
def post
|
|
24
24
|
Unleash.logger.debug "post() Report"
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
impact_metrics = collect_impact_metrics_safely
|
|
27
|
+
report = build_report(impact_metrics)
|
|
27
28
|
return unless report
|
|
28
29
|
|
|
29
30
|
send_report(report)
|
|
@@ -44,15 +45,20 @@ module Unleash
|
|
|
44
45
|
}
|
|
45
46
|
end
|
|
46
47
|
|
|
47
|
-
def build_report
|
|
48
|
+
def build_report(impact_metrics)
|
|
48
49
|
report = generate_report
|
|
49
|
-
|
|
50
|
+
has_data = !report.nil? || !impact_metrics.empty?
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
return nil if !has_data && Time.now - self.last_time < LONGEST_WITHOUT_A_REPORT
|
|
53
|
+
|
|
54
|
+
report ||= generate_report_from_bucket({
|
|
52
55
|
'start': self.last_time.utc.iso8601,
|
|
53
56
|
'stop': Time.now.utc.iso8601,
|
|
54
57
|
'toggles': {}
|
|
55
58
|
})
|
|
59
|
+
|
|
60
|
+
report[:impactMetrics] = impact_metrics unless impact_metrics.empty?
|
|
61
|
+
report
|
|
56
62
|
end
|
|
57
63
|
|
|
58
64
|
def send_report(report)
|
|
@@ -66,8 +72,24 @@ module Unleash
|
|
|
66
72
|
else
|
|
67
73
|
# :nocov:
|
|
68
74
|
Unleash.logger.error "Error when sending report to unleash server. Server responded with http code #{response.code}."
|
|
75
|
+
restore_impact_metrics(report[:impactMetrics])
|
|
69
76
|
# :nocov:
|
|
70
77
|
end
|
|
71
78
|
end
|
|
79
|
+
|
|
80
|
+
def restore_impact_metrics(impact_metrics)
|
|
81
|
+
return if impact_metrics.nil? || impact_metrics.empty?
|
|
82
|
+
|
|
83
|
+
Unleash.engine&.restore_impact_metrics(impact_metrics)
|
|
84
|
+
rescue StandardError => e
|
|
85
|
+
Unleash.logger.warn "Failed to restore impact metrics: #{e.message}"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def collect_impact_metrics_safely
|
|
89
|
+
Unleash.engine&.collect_impact_metrics || []
|
|
90
|
+
rescue StandardError => e
|
|
91
|
+
Unleash.logger.warn "Failed to collect impact metrics: #{e.message}"
|
|
92
|
+
[]
|
|
93
|
+
end
|
|
72
94
|
end
|
|
73
95
|
end
|
data/lib/unleash/spec_version.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
require 'unleash/streaming_event_processor'
|
|
2
|
+
require 'unleash/bootstrap/handler'
|
|
3
|
+
require 'unleash/backup_file_reader'
|
|
2
4
|
require 'unleash/util/event_source_wrapper'
|
|
3
5
|
|
|
4
6
|
module Unleash
|
|
@@ -10,6 +12,20 @@ module Unleash
|
|
|
10
12
|
self.event_source = nil
|
|
11
13
|
self.event_processor = Unleash::StreamingEventProcessor.new(engine)
|
|
12
14
|
self.running = false
|
|
15
|
+
|
|
16
|
+
begin
|
|
17
|
+
# if bootstrap configuration is available, initialize. Otherwise read backup file
|
|
18
|
+
if Unleash.configuration.use_bootstrap?
|
|
19
|
+
bootstrap(engine)
|
|
20
|
+
else
|
|
21
|
+
read_backup_file!(engine)
|
|
22
|
+
end
|
|
23
|
+
rescue StandardError => e
|
|
24
|
+
# fall back to reading the backup file
|
|
25
|
+
Unleash.logger.warn "StreamingClientExecutor was unable to initialize, attempting to read from backup file."
|
|
26
|
+
Unleash.logger.debug "Exception Caught: #{e}"
|
|
27
|
+
read_backup_file!(engine)
|
|
28
|
+
end
|
|
13
29
|
end
|
|
14
30
|
|
|
15
31
|
def run(&_block)
|
|
@@ -81,5 +97,18 @@ module Unleash
|
|
|
81
97
|
Unleash.logger.error "Streaming client #{self.name} threw exception #{e.class}: '#{e}'"
|
|
82
98
|
Unleash.logger.debug "stacktrace: #{e.backtrace}"
|
|
83
99
|
end
|
|
100
|
+
|
|
101
|
+
def read_backup_file!(engine)
|
|
102
|
+
backup_data = Unleash::BackupFileReader.read!
|
|
103
|
+
engine.take_state(backup_data) if backup_data
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def bootstrap(engine)
|
|
107
|
+
bootstrap_payload = Unleash::Bootstrap::Handler.new(Unleash.configuration.bootstrap_config).retrieve_toggles
|
|
108
|
+
engine.take_state(bootstrap_payload)
|
|
109
|
+
|
|
110
|
+
# reset Unleash.configuration.bootstrap_data to free up memory, as we will never use it again
|
|
111
|
+
Unleash.configuration.bootstrap_config = nil
|
|
112
|
+
end
|
|
84
113
|
end
|
|
85
114
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'json'
|
|
2
|
+
require 'unleash/backup_file_writer'
|
|
2
3
|
|
|
3
4
|
module Unleash
|
|
4
5
|
class StreamingEventProcessor
|
|
@@ -41,7 +42,8 @@ module Unleash
|
|
|
41
42
|
def handle_updated_event(event)
|
|
42
43
|
handle_delta_event(event.data)
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
full_state = @toggle_engine.get_state
|
|
46
|
+
Unleash::BackupFileWriter.save!(full_state)
|
|
45
47
|
rescue JSON::ParserError => e
|
|
46
48
|
Unleash.logger.error "Unable to parse JSON from streaming event data. Exception thrown #{e.class}: '#{e}'"
|
|
47
49
|
Unleash.logger.debug "stacktrace: #{e.backtrace}"
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
require 'unleash/configuration'
|
|
2
2
|
require 'unleash/bootstrap/handler'
|
|
3
|
+
require 'unleash/backup_file_writer'
|
|
4
|
+
require 'unleash/backup_file_reader'
|
|
3
5
|
require 'net/http'
|
|
4
6
|
require 'json'
|
|
5
7
|
require 'yggdrasil_engine'
|
|
@@ -23,10 +25,10 @@ module Unleash
|
|
|
23
25
|
fetch
|
|
24
26
|
end
|
|
25
27
|
rescue StandardError => e
|
|
26
|
-
#
|
|
28
|
+
# fall back to reading the backup file
|
|
27
29
|
Unleash.logger.warn "ToggleFetcher was unable to fetch from the network, attempting to read from backup file."
|
|
28
30
|
Unleash.logger.debug "Exception Caught: #{e}"
|
|
29
|
-
|
|
31
|
+
read_backup_file!
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
# once initialized, somewhere else you will want to start a loop with fetch()
|
|
@@ -54,25 +56,7 @@ module Unleash
|
|
|
54
56
|
# always synchronize with the local cache when fetching:
|
|
55
57
|
update_engine_state!(response.body)
|
|
56
58
|
|
|
57
|
-
save! response.body
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def save!(toggle_data)
|
|
61
|
-
Unleash.logger.debug "Will save toggles to disk now"
|
|
62
|
-
|
|
63
|
-
backup_file = Unleash.configuration.backup_file
|
|
64
|
-
backup_file_tmp = "#{backup_file}.tmp"
|
|
65
|
-
|
|
66
|
-
self.toggle_lock.synchronize do
|
|
67
|
-
File.open(backup_file_tmp, "w") do |file|
|
|
68
|
-
file.write(toggle_data)
|
|
69
|
-
end
|
|
70
|
-
File.rename(backup_file_tmp, backup_file)
|
|
71
|
-
end
|
|
72
|
-
rescue StandardError => e
|
|
73
|
-
# This is not really the end of the world. Swallowing the exception.
|
|
74
|
-
Unleash.logger.error "Unable to save backup file. Exception thrown #{e.class}:'#{e}'"
|
|
75
|
-
Unleash.logger.error "stacktrace: #{e.backtrace}"
|
|
59
|
+
Unleash::BackupFileWriter.save! response.body
|
|
76
60
|
end
|
|
77
61
|
|
|
78
62
|
private
|
|
@@ -88,25 +72,9 @@ module Unleash
|
|
|
88
72
|
Unleash.logger.error "Failed to hydrate state: #{e.backtrace}"
|
|
89
73
|
end
|
|
90
74
|
|
|
91
|
-
def
|
|
92
|
-
Unleash.
|
|
93
|
-
|
|
94
|
-
return nil unless File.exist?(backup_file)
|
|
95
|
-
|
|
96
|
-
backup_data = File.read(backup_file)
|
|
97
|
-
update_engine_state!(backup_data)
|
|
98
|
-
rescue IOError => e
|
|
99
|
-
# :nocov:
|
|
100
|
-
Unleash.logger.error "Unable to read the backup_file: #{e}"
|
|
101
|
-
# :nocov:
|
|
102
|
-
rescue JSON::ParserError => e
|
|
103
|
-
# :nocov:
|
|
104
|
-
Unleash.logger.error "Unable to parse JSON from existing backup_file: #{e}"
|
|
105
|
-
# :nocov:
|
|
106
|
-
rescue StandardError => e
|
|
107
|
-
# :nocov:
|
|
108
|
-
Unleash.logger.error "Unable to extract valid data from backup_file. Exception thrown: #{e}"
|
|
109
|
-
# :nocov:
|
|
75
|
+
def read_backup_file!
|
|
76
|
+
backup_data = Unleash::BackupFileReader.read!
|
|
77
|
+
update_engine_state!(backup_data) if backup_data
|
|
110
78
|
end
|
|
111
79
|
|
|
112
80
|
def bootstrap
|
data/lib/unleash/version.rb
CHANGED
data/unleash-client.gemspec
CHANGED
|
@@ -24,12 +24,11 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
spec.required_ruby_version = ">= 2.7"
|
|
25
25
|
|
|
26
26
|
spec.add_dependency "ld-eventsource", "2.2.4" unless RUBY_ENGINE == 'jruby'
|
|
27
|
-
spec.add_dependency "yggdrasil-engine", "~> 1.
|
|
27
|
+
spec.add_dependency "yggdrasil-engine", "~> 1.2.1"
|
|
28
28
|
|
|
29
29
|
spec.add_dependency "base64", "~> 0.3.0"
|
|
30
30
|
spec.add_dependency "logger", "~> 1.6"
|
|
31
31
|
|
|
32
|
-
spec.add_development_dependency "bundler", "~> 2.1"
|
|
33
32
|
spec.add_development_dependency "rake", "~> 12.3"
|
|
34
33
|
spec.add_development_dependency "rspec", "~> 3.12"
|
|
35
34
|
spec.add_development_dependency "rspec-json_expectations", "~> 2.2"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: unleash
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.
|
|
4
|
+
version: 6.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Renato Arruda
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-01-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ld-eventsource
|
|
@@ -30,14 +30,14 @@ dependencies:
|
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 1.
|
|
33
|
+
version: 1.2.1
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 1.
|
|
40
|
+
version: 1.2.1
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: base64
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -66,20 +66,6 @@ dependencies:
|
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '1.6'
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: bundler
|
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
|
72
|
-
requirements:
|
|
73
|
-
- - "~>"
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
version: '2.1'
|
|
76
|
-
type: :development
|
|
77
|
-
prerelease: false
|
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
-
requirements:
|
|
80
|
-
- - "~>"
|
|
81
|
-
- !ruby/object:Gem::Version
|
|
82
|
-
version: '2.1'
|
|
83
69
|
- !ruby/object:Gem::Dependency
|
|
84
70
|
name: rake
|
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -209,6 +195,8 @@ files:
|
|
|
209
195
|
- examples/simple.rb
|
|
210
196
|
- examples/streaming.rb
|
|
211
197
|
- lib/unleash.rb
|
|
198
|
+
- lib/unleash/backup_file_reader.rb
|
|
199
|
+
- lib/unleash/backup_file_writer.rb
|
|
212
200
|
- lib/unleash/bootstrap/configuration.rb
|
|
213
201
|
- lib/unleash/bootstrap/handler.rb
|
|
214
202
|
- lib/unleash/bootstrap/provider/base.rb
|
|
@@ -217,6 +205,8 @@ files:
|
|
|
217
205
|
- lib/unleash/client.rb
|
|
218
206
|
- lib/unleash/configuration.rb
|
|
219
207
|
- lib/unleash/context.rb
|
|
208
|
+
- lib/unleash/environment_resolver.rb
|
|
209
|
+
- lib/unleash/impact_metrics.rb
|
|
220
210
|
- lib/unleash/metrics_reporter.rb
|
|
221
211
|
- lib/unleash/scheduled_executor.rb
|
|
222
212
|
- lib/unleash/spec_version.rb
|