splitclient-rb 8.10.1.pre.rc.2-java → 8.11.0.pre.rc1-java
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/CHANGES.txt +3 -2
- data/NOTICE.txt +5 -0
- data/lib/splitclient-rb/cache/repositories/rule_based_segments_repository.rb +14 -1
- data/lib/splitclient-rb/cache/repositories/segments_repository.rb +11 -1
- data/lib/splitclient-rb/cache/repositories/splits_repository.rb +23 -1
- data/lib/splitclient-rb/clients/split_client.rb +10 -1
- data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +1 -0
- data/lib/splitclient-rb/engine/events/events_delivery.rb +20 -0
- data/lib/splitclient-rb/engine/events/events_manager.rb +188 -0
- data/lib/splitclient-rb/engine/events/events_manager_config.rb +96 -0
- data/lib/splitclient-rb/engine/events/events_task.rb +50 -0
- data/lib/splitclient-rb/engine/events/noop_events_queue.rb +13 -0
- data/lib/splitclient-rb/engine/models/event_active_subscriptions.rb +14 -0
- data/lib/splitclient-rb/engine/models/events_metadata.rb +10 -0
- data/lib/splitclient-rb/engine/models/sdk_event.rb +4 -0
- data/lib/splitclient-rb/engine/models/sdk_event_type.rb +4 -0
- data/lib/splitclient-rb/engine/models/sdk_internal_event.rb +8 -0
- data/lib/splitclient-rb/engine/models/sdk_internal_event_notification.rb +14 -0
- data/lib/splitclient-rb/engine/models/valid_sdk_event.rb +14 -0
- data/lib/splitclient-rb/engine/status_manager.rb +7 -1
- data/lib/splitclient-rb/split_factory.rb +20 -5
- data/lib/splitclient-rb/sse/event_source/client.rb +1 -1
- data/lib/splitclient-rb/version.rb +1 -1
- data/lib/splitclient-rb.rb +12 -0
- metadata +15 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e1a766e8eda7c19daa9bda7ff20535560c61a6fdc54798d6a8baba2fd5894d04
|
|
4
|
+
data.tar.gz: 9c438e87b0963497f20222affd684b7ba400ec89324f8eab52a07034a24b8e8d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 41db0b240627dfd66a96f40c7d7611ae6047babe02c2d468d5b1a4632e7036b5d97ccc81bad1e011eff1b6cc3177a21829293103b47434d67d86b1fb5d40acc6
|
|
7
|
+
data.tar.gz: f1ce49dc17672aad15a6a7602f5613bb036e7791eeae6fff31e4a36ad85d53877202e6bd012b9ef2978b933d2b0ba697111d983882e2baa77d4e7acad287bfb4
|
data/CHANGES.txt
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
CHANGES
|
|
2
2
|
|
|
3
|
-
8.10.1 (Jan
|
|
4
|
-
- Fixed rule-based segment matcher.
|
|
3
|
+
8.10.1 (Jan 28, 2025)
|
|
4
|
+
- Fixed rule-based segment matcher to exit when a conition is met.
|
|
5
|
+
- Fixed impressions properties format in redis mode.
|
|
5
6
|
|
|
6
7
|
8.10.0 (Nov 28, 2025)
|
|
7
8
|
- Updated socketry gem used in streaming feature with built-in socket lib.
|
data/NOTICE.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Harness Feature Management JavaScript SDK Copyright 2024-2026 Harness Inc.
|
|
2
|
+
|
|
3
|
+
This product includes software developed at Harness Inc. (https://harness.io/).
|
|
4
|
+
|
|
5
|
+
This product includes software originally developed by Split Software, Inc. (https://www.split.io/). Copyright 2016-2024 Split Software, Inc.
|
|
@@ -28,7 +28,7 @@ module SplitIoClient
|
|
|
28
28
|
RB_SEGMENTS_PREFIX = '.rbsegment.'
|
|
29
29
|
REGISTERED_PREFIX = '.segments.registered'
|
|
30
30
|
|
|
31
|
-
def initialize(config)
|
|
31
|
+
def initialize(config, internal_events_queue)
|
|
32
32
|
super(config)
|
|
33
33
|
@adapter = case @config.cache_adapter.class.to_s
|
|
34
34
|
when 'SplitIoClient::Cache::Adapters::RedisAdapter'
|
|
@@ -40,12 +40,25 @@ module SplitIoClient
|
|
|
40
40
|
@adapter.set_string(namespace_key(TILL_PREFIX), '-1')
|
|
41
41
|
@adapter.initialize_map(namespace_key(REGISTERED_PREFIX))
|
|
42
42
|
end
|
|
43
|
+
@internal_events_queue = internal_events_queue
|
|
43
44
|
end
|
|
44
45
|
|
|
45
46
|
def update(to_add, to_delete, new_change_number)
|
|
46
47
|
to_add.each{ |rule_based_segment| add_rule_based_segment(rule_based_segment) }
|
|
47
48
|
to_delete.each{ |rule_based_segment| remove_rule_based_segment(rule_based_segment) }
|
|
48
49
|
set_change_number(new_change_number)
|
|
50
|
+
|
|
51
|
+
if to_add.length > 0 || to_delete.length > 0
|
|
52
|
+
@internal_events_queue.push(
|
|
53
|
+
SplitIoClient::Engine::Models::SdkInternalEventNotification.new(
|
|
54
|
+
SplitIoClient::Engine::Models::SdkInternalEvent::RB_SEGMENTS_UPDATED,
|
|
55
|
+
SplitIoClient::Engine::Models::EventsMetadata.new(
|
|
56
|
+
SplitIoClient::Engine::Models::SdkEventType::SEGMENTS_UPDATE,
|
|
57
|
+
[]
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
end
|
|
49
62
|
end
|
|
50
63
|
|
|
51
64
|
def get_rule_based_segment(name)
|
|
@@ -6,7 +6,7 @@ module SplitIoClient
|
|
|
6
6
|
|
|
7
7
|
attr_reader :adapter
|
|
8
8
|
|
|
9
|
-
def initialize(config)
|
|
9
|
+
def initialize(config, internal_events_queue)
|
|
10
10
|
super(config)
|
|
11
11
|
@adapter = case @config.cache_adapter.class.to_s
|
|
12
12
|
when 'SplitIoClient::Cache::Adapters::RedisAdapter'
|
|
@@ -15,6 +15,7 @@ module SplitIoClient
|
|
|
15
15
|
@config.cache_adapter
|
|
16
16
|
end
|
|
17
17
|
@adapter.set_bool(namespace_key('.ready'), false) unless @config.mode.equal?(:consumer)
|
|
18
|
+
@internal_events_queue = internal_events_queue
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
# Receives segment data, adds and removes segements from the store
|
|
@@ -25,6 +26,15 @@ module SplitIoClient
|
|
|
25
26
|
|
|
26
27
|
add_keys(name, segment[:added])
|
|
27
28
|
remove_keys(name, segment[:removed])
|
|
29
|
+
@internal_events_queue.push(
|
|
30
|
+
SplitIoClient::Engine::Models::SdkInternalEventNotification.new(
|
|
31
|
+
SplitIoClient::Engine::Models::SdkInternalEvent::SEGMENTS_UPDATED,
|
|
32
|
+
SplitIoClient::Engine::Models::EventsMetadata.new(
|
|
33
|
+
SplitIoClient::Engine::Models::SdkEventType::SEGMENTS_UPDATE,
|
|
34
|
+
[]
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
)
|
|
28
38
|
end
|
|
29
39
|
|
|
30
40
|
def get_segment_keys(name)
|
|
@@ -35,7 +35,7 @@ module SplitIoClient
|
|
|
35
35
|
SPLIT_PREFIX = '.split.'
|
|
36
36
|
READY_PREFIX = '.splits.ready'
|
|
37
37
|
|
|
38
|
-
def initialize(config, flag_sets_repository, flag_set_filter)
|
|
38
|
+
def initialize(config, flag_sets_repository, flag_set_filter, internal_events_queue)
|
|
39
39
|
super(config)
|
|
40
40
|
@tt_cache = {}
|
|
41
41
|
@adapter = case @config.cache_adapter.class.to_s
|
|
@@ -46,6 +46,7 @@ module SplitIoClient
|
|
|
46
46
|
end
|
|
47
47
|
@flag_sets = flag_sets_repository
|
|
48
48
|
@flag_set_filter = flag_set_filter
|
|
49
|
+
@internal_events_queue = internal_events_queue
|
|
49
50
|
initialize_keys
|
|
50
51
|
end
|
|
51
52
|
|
|
@@ -53,6 +54,18 @@ module SplitIoClient
|
|
|
53
54
|
to_add.each{ |feature_flag| add_feature_flag(feature_flag) }
|
|
54
55
|
to_delete.each{ |feature_flag| remove_feature_flag(feature_flag) }
|
|
55
56
|
set_change_number(new_change_number)
|
|
57
|
+
|
|
58
|
+
if to_add.length > 0 || to_delete.length > 0
|
|
59
|
+
@internal_events_queue.push(
|
|
60
|
+
SplitIoClient::Engine::Models::SdkInternalEventNotification.new(
|
|
61
|
+
SplitIoClient::Engine::Models::SdkInternalEvent::FLAGS_UPDATED,
|
|
62
|
+
SplitIoClient::Engine::Models::EventsMetadata.new(
|
|
63
|
+
SplitIoClient::Engine::Models::SdkEventType::FLAG_UPDATE,
|
|
64
|
+
to_add.map {|flag| flag[:name]} | to_delete.map {|flag| flag[:name]}
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
)
|
|
68
|
+
end
|
|
56
69
|
end
|
|
57
70
|
|
|
58
71
|
def get_split(name)
|
|
@@ -140,6 +153,15 @@ module SplitIoClient
|
|
|
140
153
|
split[:changeNumber] = change_number
|
|
141
154
|
|
|
142
155
|
@adapter.set_string(namespace_key(".split.#{split_name}"), split.to_json)
|
|
156
|
+
@internal_events_queue.push(
|
|
157
|
+
SplitIoClient::Engine::Models::SdkInternalEventNotification.new(
|
|
158
|
+
SplitIoClient::Engine::Models::SdkInternalEvent::FLAG_KILLED_NOTIFICATION,
|
|
159
|
+
SplitIoClient::Engine::Models::EventsMetadata.new(
|
|
160
|
+
SplitIoClient::Engine::Models::SdkEventType::FLAG_UPDATE,
|
|
161
|
+
[split_name]
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
)
|
|
143
165
|
end
|
|
144
166
|
|
|
145
167
|
def splits_count
|
|
@@ -18,7 +18,7 @@ module SplitIoClient
|
|
|
18
18
|
# @param sdk_key [String] the SDK key for your split account
|
|
19
19
|
#
|
|
20
20
|
# @return [SplitIoClient] split.io client instance
|
|
21
|
-
def initialize(sdk_key, repositories, status_manager, config, impressions_manager, telemetry_evaluation_producer, evaluator, split_validator, fallback_treatment_calculator)
|
|
21
|
+
def initialize(sdk_key, repositories, status_manager, config, impressions_manager, telemetry_evaluation_producer, evaluator, split_validator, fallback_treatment_calculator, events_manager)
|
|
22
22
|
@api_key = sdk_key
|
|
23
23
|
@splits_repository = repositories[:splits]
|
|
24
24
|
@segments_repository = repositories[:segments]
|
|
@@ -33,6 +33,7 @@ module SplitIoClient
|
|
|
33
33
|
@split_validator = split_validator
|
|
34
34
|
@evaluator = evaluator
|
|
35
35
|
@fallback_treatment_calculator = fallback_treatment_calculator
|
|
36
|
+
@events_manager = events_manager
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
def get_treatment(
|
|
@@ -176,6 +177,14 @@ module SplitIoClient
|
|
|
176
177
|
@status_manager.wait_until_ready(time) if @status_manager
|
|
177
178
|
end
|
|
178
179
|
|
|
180
|
+
def register(sdk_event, handler)
|
|
181
|
+
@events_manager.register(sdk_event, handler)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def unregister(sdk_event, handler)
|
|
185
|
+
@events_manager.unregister(sdk_event)
|
|
186
|
+
end
|
|
187
|
+
|
|
179
188
|
private
|
|
180
189
|
|
|
181
190
|
def check_properties_size(properties_size, msg = "Event not queued")
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SplitIoClient
|
|
4
|
+
module Engine
|
|
5
|
+
module Events
|
|
6
|
+
class EventsDelivery
|
|
7
|
+
def initialize(config)
|
|
8
|
+
@config = config
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def deliver(sdk_event, event_metadata, event_handler)
|
|
12
|
+
event_handler.call(event_metadata)
|
|
13
|
+
rescue StandardError => e
|
|
14
|
+
@config.logger.error("Exception when calling handler for Sdk Event #{sdk_event}")
|
|
15
|
+
@config.log_found_exception(__method__.to_s, e)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SplitIoClient
|
|
4
|
+
module Engine
|
|
5
|
+
module Events
|
|
6
|
+
class EventsManager
|
|
7
|
+
def initialize(events_manager_config, events_delivery, config)
|
|
8
|
+
@manager_config = events_manager_config
|
|
9
|
+
@events_delivery = events_delivery
|
|
10
|
+
@active_subscriptions = {}
|
|
11
|
+
@internal_events_status = {}
|
|
12
|
+
@mutex = Mutex.new
|
|
13
|
+
@config = config
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def register(sdk_event, event_handler)
|
|
17
|
+
return if @active_subscriptions.key?(sdk_event) && !get_event_handler(sdk_event).nil?
|
|
18
|
+
|
|
19
|
+
@mutex.synchronize do
|
|
20
|
+
# SDK ready already fired
|
|
21
|
+
if sdk_event == SplitIoClient::Engine::Models::SdkEvent::SDK_READY && event_already_triggered(sdk_event)
|
|
22
|
+
@active_subscriptions[sdk_event] = SplitIoClient::Engine::Models::EventActiveSubscriptions.new(true, event_handler)
|
|
23
|
+
@config.logger.debug('EventsManager: Firing SDK_READY event for new subscription') if @config.debug_enabled
|
|
24
|
+
fire_sdk_event(sdk_event, nil)
|
|
25
|
+
return
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
@config.logger.debug("EventsManager: Register event: #{sdk_event}") if @config.debug_enabled
|
|
29
|
+
@active_subscriptions[sdk_event] = SplitIoClient::Engine::Models::EventActiveSubscriptions.new(false, event_handler)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def unregister(sdk_event)
|
|
34
|
+
return unless @active_subscriptions.key?(sdk_event)
|
|
35
|
+
|
|
36
|
+
@mutex.synchronize do
|
|
37
|
+
@active_subscriptions.delete(sdk_event)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def notify_internal_event(sdk_internal_event, event_metadata)
|
|
42
|
+
@mutex.synchronize do
|
|
43
|
+
update_internal_event_status(sdk_internal_event, true)
|
|
44
|
+
@manager_config.evaluation_order.each do |sorted_event|
|
|
45
|
+
if get_sdk_event_if_applicable(sdk_internal_event).include?(sorted_event) &&
|
|
46
|
+
!get_event_handler(sorted_event).nil?
|
|
47
|
+
fire_sdk_event(sorted_event, event_metadata)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# if client is not subscribed to SDK_READY
|
|
51
|
+
if sorted_event == SplitIoClient::Engine::Models::SdkEvent::SDK_READY && get_event_handler(sorted_event).nil?
|
|
52
|
+
@config.logger.debug('EventsManager: Registering SDK_READY event as fired') if @config.debug_enabled
|
|
53
|
+
@active_subscriptions[Engine::Models::SdkEvent::SDK_READY] = Engine::Models::EventActiveSubscriptions.new(true, nil)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def destroy
|
|
60
|
+
@mutex.synchronize do
|
|
61
|
+
@active_subscriptions = {}
|
|
62
|
+
@internal_events_status = {}
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def fire_sdk_event(sdk_event, event_metadata)
|
|
69
|
+
@config.logger.debug("EventsManager: Firing Sdk event: #{sdk_event}") if @config.debug_enabled
|
|
70
|
+
@config.threads[:sdk_event_notify] = Thread.new do
|
|
71
|
+
@events_delivery.deliver(sdk_event, event_metadata, get_event_handler(sdk_event))
|
|
72
|
+
end
|
|
73
|
+
sdk_event_triggered(sdk_event)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def event_already_triggered(sdk_event)
|
|
77
|
+
return @active_subscriptions[sdk_event].triggered if @active_subscriptions.key?(sdk_event)
|
|
78
|
+
|
|
79
|
+
false
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def get_internal_event_status(sdk_internal_event)
|
|
83
|
+
return @internal_events_status[sdk_internal_event] if @internal_events_status.key?(sdk_internal_event)
|
|
84
|
+
|
|
85
|
+
false
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def update_internal_event_status(sdk_internal_event, status)
|
|
89
|
+
@internal_events_status[sdk_internal_event] = status
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def sdk_event_triggered(sdk_event)
|
|
93
|
+
return unless @active_subscriptions.key?(sdk_event)
|
|
94
|
+
|
|
95
|
+
return if @active_subscriptions[sdk_event].triggered
|
|
96
|
+
|
|
97
|
+
@active_subscriptions[sdk_event].triggered = true
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def get_event_handler(sdk_event)
|
|
101
|
+
return nil unless @active_subscriptions.key?(sdk_event)
|
|
102
|
+
|
|
103
|
+
@active_subscriptions[sdk_event].handler
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def get_sdk_event_if_applicable(sdk_internal_event)
|
|
107
|
+
final_sdk_event = SplitIoClient::Engine::Models::ValidSdkEvent.new(nil, false)
|
|
108
|
+
|
|
109
|
+
events_to_fire = []
|
|
110
|
+
require_any_sdk_event = check_require_any(sdk_internal_event)
|
|
111
|
+
if require_any_sdk_event.valid
|
|
112
|
+
if (!event_already_triggered(require_any_sdk_event.sdk_event) &&
|
|
113
|
+
execution_limit(require_any_sdk_event.sdk_event) == 1) ||
|
|
114
|
+
execution_limit(require_any_sdk_event.sdk_event) == -1
|
|
115
|
+
final_sdk_event = SplitIoClient::Engine::Models::ValidSdkEvent.new(
|
|
116
|
+
require_any_sdk_event.sdk_event,
|
|
117
|
+
check_prerequisites(require_any_sdk_event.sdk_event) &&
|
|
118
|
+
check_suppressed_by(require_any_sdk_event.sdk_event)
|
|
119
|
+
)
|
|
120
|
+
end
|
|
121
|
+
events_to_fire.push(final_sdk_event.sdk_event) if final_sdk_event.valid
|
|
122
|
+
end
|
|
123
|
+
check_require_all.each { |sdk_event| events_to_fire.push(sdk_event) }
|
|
124
|
+
|
|
125
|
+
events_to_fire
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def check_require_all
|
|
129
|
+
events = []
|
|
130
|
+
@manager_config.require_all.each do |require_name, require_value|
|
|
131
|
+
final_status = true
|
|
132
|
+
require_value.each { |val| final_status &= get_internal_event_status(val) }
|
|
133
|
+
events.push(require_name) if check_event_eligible_conditions(final_status, require_name, require_value)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
events
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def check_event_eligible_conditions(final_status, require_name, require_value)
|
|
140
|
+
final_status &&
|
|
141
|
+
check_prerequisites(require_name) &&
|
|
142
|
+
((!event_already_triggered(require_name) &&
|
|
143
|
+
execution_limit(require_name) == 1) ||
|
|
144
|
+
execution_limit(require_name) == -1) &&
|
|
145
|
+
require_value.length.positive?
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def check_prerequisites(sdk_event)
|
|
149
|
+
@manager_config.prerequisites.each do |name, value|
|
|
150
|
+
value.each do |val|
|
|
151
|
+
return false if name == sdk_event && !event_already_triggered(val)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
true
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def check_suppressed_by(sdk_event)
|
|
159
|
+
@manager_config.suppressed_by.each do |name, value|
|
|
160
|
+
value.each do |val|
|
|
161
|
+
return false if name == sdk_event && event_already_triggered(val)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
true
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def execution_limit(sdk_event)
|
|
169
|
+
return -1 unless @manager_config.execution_limits.key?(sdk_event)
|
|
170
|
+
|
|
171
|
+
@manager_config.execution_limits[sdk_event]
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def check_require_any(sdk_internal_event)
|
|
175
|
+
valid_sdk_event = SplitIoClient::Engine::Models::ValidSdkEvent.new(nil, false)
|
|
176
|
+
@manager_config.require_any.each do |name, val|
|
|
177
|
+
if val.include?(sdk_internal_event)
|
|
178
|
+
valid_sdk_event = SplitIoClient::Engine::Models::ValidSdkEvent.new(name, true)
|
|
179
|
+
return valid_sdk_event
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
valid_sdk_event
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SplitIoClient
|
|
4
|
+
module Engine
|
|
5
|
+
module Events
|
|
6
|
+
class EventsManagerConfig
|
|
7
|
+
attr_accessor :require_all, :prerequisites, :require_any, :suppressed_by, :execution_limits, :evaluation_order
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@require_all = construct_require_all
|
|
11
|
+
@prerequisites = construct_prerequisites
|
|
12
|
+
@require_any = construct_require_any
|
|
13
|
+
@suppressed_by = construct_suppressed_by
|
|
14
|
+
@execution_limits = construct_execution_limits
|
|
15
|
+
@evaluation_order = construct_sorted_events
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def construct_require_all
|
|
21
|
+
{
|
|
22
|
+
SplitIoClient::Engine::Models::SdkEvent::SDK_READY => Set.new([SplitIoClient::Engine::Models::SdkInternalEvent::SDK_READY])
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def construct_prerequisites
|
|
27
|
+
{
|
|
28
|
+
SplitIoClient::Engine::Models::SdkEvent::SDK_UPDATE => Set.new([SplitIoClient::Engine::Models::SdkEvent::SDK_READY])
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def construct_require_any
|
|
33
|
+
{
|
|
34
|
+
SplitIoClient::Engine::Models::SdkEvent::SDK_UPDATE => Set.new(
|
|
35
|
+
[
|
|
36
|
+
SplitIoClient::Engine::Models::SdkInternalEvent::FLAG_KILLED_NOTIFICATION,
|
|
37
|
+
SplitIoClient::Engine::Models::SdkInternalEvent::FLAGS_UPDATED,
|
|
38
|
+
SplitIoClient::Engine::Models::SdkInternalEvent::RB_SEGMENTS_UPDATED,
|
|
39
|
+
SplitIoClient::Engine::Models::SdkInternalEvent::SEGMENTS_UPDATED
|
|
40
|
+
]
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def construct_suppressed_by
|
|
46
|
+
{}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def construct_execution_limits
|
|
50
|
+
{
|
|
51
|
+
SplitIoClient::Engine::Models::SdkEvent::SDK_READY => 1,
|
|
52
|
+
SplitIoClient::Engine::Models::SdkEvent::SDK_UPDATE => -1
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def construct_sorted_events
|
|
57
|
+
sorted_events = []
|
|
58
|
+
[SplitIoClient::Engine::Models::SdkEvent::SDK_READY, SplitIoClient::Engine::Models::SdkEvent::SDK_UPDATE].each do |sdk_event|
|
|
59
|
+
sorted_events = dfs_recursive(sdk_event, sorted_events)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
sorted_events
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def dfs_recursive(sdk_event, added)
|
|
66
|
+
return added if added.include?(sdk_event)
|
|
67
|
+
|
|
68
|
+
get_dependencies(sdk_event).each do |dependent_event|
|
|
69
|
+
added = dfs_recursive(dependent_event, added)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
added.push(sdk_event)
|
|
73
|
+
|
|
74
|
+
added
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def get_dependencies(sdk_event)
|
|
78
|
+
dependencies = Set.new
|
|
79
|
+
@prerequisites.each do |prerequisites_event_name, prerequisites_event_value|
|
|
80
|
+
next unless prerequisites_event_name == sdk_event
|
|
81
|
+
|
|
82
|
+
prerequisites_event_value.each do |prereq_event|
|
|
83
|
+
dependencies.add(prereq_event)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
@suppressed_by.each do |suppressed_event_name, suppressed_event_value|
|
|
88
|
+
dependencies.add(suppressed_event_name) if suppressed_event_value.include?(sdk_event)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
dependencies
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SplitIoClient
|
|
4
|
+
module Engine
|
|
5
|
+
module Events
|
|
6
|
+
class EventsTask
|
|
7
|
+
attr_accessor :running
|
|
8
|
+
|
|
9
|
+
def initialize(notify_internal_events, internal_events_queue, config)
|
|
10
|
+
@notify_internal_events = notify_internal_events
|
|
11
|
+
@internal_events_queue = internal_events_queue
|
|
12
|
+
@config = config
|
|
13
|
+
@running = false
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def start
|
|
17
|
+
return if @running
|
|
18
|
+
|
|
19
|
+
@config.logger.info('Starting Internal Events Task.')
|
|
20
|
+
@running = true
|
|
21
|
+
@config.threads[:internal_events_task] = Thread.new do
|
|
22
|
+
worker_thread
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def stop
|
|
27
|
+
return unless @running
|
|
28
|
+
|
|
29
|
+
@config.logger.info('Stopping Internal Events Task.')
|
|
30
|
+
@running = false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def worker_thread
|
|
36
|
+
while (event = @internal_events_queue.pop)
|
|
37
|
+
break unless @running
|
|
38
|
+
|
|
39
|
+
@config.logger.debug("Processing sdk internal event: #{event.internal_event}") if @config.debug_enabled
|
|
40
|
+
begin
|
|
41
|
+
@notify_internal_events.call(event.internal_event, event.metadata)
|
|
42
|
+
rescue StandardError => e
|
|
43
|
+
@config.log_found_exception(__method__.to_s, e)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: false
|
|
2
|
+
|
|
3
|
+
module SplitIoClient
|
|
4
|
+
module Engine::Models
|
|
5
|
+
class EventActiveSubscriptions
|
|
6
|
+
attr_accessor :triggered, :handler
|
|
7
|
+
|
|
8
|
+
def initialize(triggered, handler)
|
|
9
|
+
@triggered = triggered
|
|
10
|
+
@handler = handler
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
class SplitIoClient::Engine::Models::SdkInternalEvent
|
|
2
|
+
SDK_READY = 'SDK_READY'
|
|
3
|
+
FLAGS_UPDATED = 'FLAGS_UPDATED'
|
|
4
|
+
FLAG_KILLED_NOTIFICATION = 'FLAG_KILLED_NOTIFICATION'
|
|
5
|
+
SEGMENTS_UPDATED = 'SEGMENTS_UPDATED'
|
|
6
|
+
RB_SEGMENTS_UPDATED = 'RB_SEGMENTS_UPDATED'
|
|
7
|
+
LARGE_SEGMENTS_UPDATED = 'LARGE_SEGMENTS_UPDATED'
|
|
8
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: false
|
|
2
|
+
|
|
3
|
+
module SplitIoClient
|
|
4
|
+
module Engine::Models
|
|
5
|
+
class SdkInternalEventNotification
|
|
6
|
+
attr_reader :internal_event, :metadata
|
|
7
|
+
|
|
8
|
+
def initialize(internal_event, metadata)
|
|
9
|
+
@internal_event = internal_event
|
|
10
|
+
@metadata = metadata
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
module SplitIoClient
|
|
4
4
|
module Engine
|
|
5
5
|
class StatusManager
|
|
6
|
-
def initialize(config)
|
|
6
|
+
def initialize(config, internal_events_queue)
|
|
7
7
|
@config = config
|
|
8
8
|
@sdk_ready = Concurrent::CountDownLatch.new(1)
|
|
9
|
+
@internal_events_queue = internal_events_queue
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
def ready?
|
|
@@ -19,6 +20,11 @@ module SplitIoClient
|
|
|
19
20
|
|
|
20
21
|
@sdk_ready.count_down
|
|
21
22
|
@config.logger.info('SplitIO SDK is ready')
|
|
23
|
+
@internal_events_queue.push(
|
|
24
|
+
SplitIoClient::Engine::Models::SdkInternalEventNotification.new(
|
|
25
|
+
SplitIoClient::Engine::Models::SdkInternalEvent::SDK_READY, nil
|
|
26
|
+
)
|
|
27
|
+
)
|
|
22
28
|
end
|
|
23
29
|
|
|
24
30
|
def wait_until_ready(seconds = nil)
|
|
@@ -45,6 +45,7 @@ module SplitIoClient
|
|
|
45
45
|
|
|
46
46
|
register_factory
|
|
47
47
|
|
|
48
|
+
build_events_manager
|
|
48
49
|
build_telemetry_components
|
|
49
50
|
build_flag_sets_filter
|
|
50
51
|
build_repositories
|
|
@@ -53,13 +54,13 @@ module SplitIoClient
|
|
|
53
54
|
build_unique_keys_tracker
|
|
54
55
|
build_impressions_components
|
|
55
56
|
|
|
56
|
-
@status_manager = Engine::StatusManager.new(@config)
|
|
57
|
+
@status_manager = Engine::StatusManager.new(@config, @internal_events_queue)
|
|
57
58
|
@split_validator = SplitIoClient::Validators.new(@config)
|
|
58
59
|
@evaluator = Engine::Parser::Evaluator.new(@segments_repository, @splits_repository, @rule_based_segment_repository, @config)
|
|
59
60
|
|
|
60
61
|
start!
|
|
61
62
|
fallback_treatment_calculator = SplitIoClient::Engine::FallbackTreatmentCalculator.new(@config.fallback_treatments_configuration)
|
|
62
|
-
@client = SplitClient.new(@api_key, repositories, @status_manager, @config, @impressions_manager, @evaluation_producer, @evaluator, @split_validator, fallback_treatment_calculator)
|
|
63
|
+
@client = SplitClient.new(@api_key, repositories, @status_manager, @config, @impressions_manager, @evaluation_producer, @evaluator, @split_validator, fallback_treatment_calculator, @events_manager)
|
|
63
64
|
@manager = SplitManager.new(@splits_repository, @status_manager, @config)
|
|
64
65
|
end
|
|
65
66
|
|
|
@@ -219,9 +220,9 @@ module SplitIoClient
|
|
|
219
220
|
else
|
|
220
221
|
@flag_sets_repository = SplitIoClient::Cache::Repositories::MemoryFlagSetsRepository.new(@config.flag_sets_filter)
|
|
221
222
|
end
|
|
222
|
-
@splits_repository = SplitsRepository.new(@config, @flag_sets_repository, @flag_sets_filter)
|
|
223
|
-
@segments_repository = SegmentsRepository.new(@config)
|
|
224
|
-
@rule_based_segment_repository = RuleBasedSegmentsRepository.new(@config)
|
|
223
|
+
@splits_repository = SplitsRepository.new(@config, @flag_sets_repository, @flag_sets_filter, @internal_events_queue)
|
|
224
|
+
@segments_repository = SegmentsRepository.new(@config, @internal_events_queue)
|
|
225
|
+
@rule_based_segment_repository = RuleBasedSegmentsRepository.new(@config, @internal_events_queue)
|
|
225
226
|
@impressions_repository = ImpressionsRepository.new(@config)
|
|
226
227
|
@events_repository = EventsRepository.new(@config, @api_key, @runtime_producer)
|
|
227
228
|
end
|
|
@@ -265,5 +266,19 @@ module SplitIoClient
|
|
|
265
266
|
def build_flag_sets_filter
|
|
266
267
|
@flag_sets_filter = SplitIoClient::Cache::Filter::FlagSetsFilter.new(@config.flag_sets_filter)
|
|
267
268
|
end
|
|
269
|
+
|
|
270
|
+
def build_events_manager
|
|
271
|
+
@events_manager = Engine::Events::EventsManager.new(Engine::Events::EventsManagerConfig.new,
|
|
272
|
+
Engine::Events::EventsDelivery.new(@config),
|
|
273
|
+
@config)
|
|
274
|
+
if @config.consumer?
|
|
275
|
+
@internal_events_queue = Engine::Events::NoOpEventsQueue.new
|
|
276
|
+
return
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
@internal_events_queue = Queue.new
|
|
280
|
+
@events_task = Engine::Events::EventsTask.new(@events_manager.method(:notify_internal_event), @internal_events_queue, @config)
|
|
281
|
+
@events_task.start
|
|
282
|
+
end
|
|
268
283
|
end
|
|
269
284
|
end
|
|
@@ -43,11 +43,11 @@ module SplitIoClient
|
|
|
43
43
|
end
|
|
44
44
|
@config.logger.debug("Closing SSEClient socket")
|
|
45
45
|
|
|
46
|
+
push_status(status)
|
|
46
47
|
@connected.make_false
|
|
47
48
|
@socket.sync_close = true if @socket.is_a? OpenSSL::SSL::SSLSocket
|
|
48
49
|
@socket.close
|
|
49
50
|
@config.logger.debug("SSEClient socket state #{@socket.state}") if @socket.is_a? OpenSSL::SSL::SSLSocket
|
|
50
|
-
push_status(status)
|
|
51
51
|
rescue StandardError => e
|
|
52
52
|
@config.logger.error("SSEClient close Error: #{e.inspect}")
|
|
53
53
|
end
|
data/lib/splitclient-rb.rb
CHANGED
|
@@ -66,6 +66,11 @@ require 'splitclient-rb/engine/api/telemetry_api'
|
|
|
66
66
|
require 'splitclient-rb/engine/common/impressions_counter'
|
|
67
67
|
require 'splitclient-rb/engine/common/impressions_manager'
|
|
68
68
|
require 'splitclient-rb/engine/common/noop_impressions_counter'
|
|
69
|
+
require 'splitclient-rb/engine/events/events_manager_config.rb'
|
|
70
|
+
require 'splitclient-rb/engine/events/events_manager.rb'
|
|
71
|
+
require 'splitclient-rb/engine/events/events_task.rb'
|
|
72
|
+
require 'splitclient-rb/engine/events/events_delivery.rb'
|
|
73
|
+
require 'splitclient-rb/engine/events/noop_events_queue.rb'
|
|
69
74
|
require 'splitclient-rb/engine/parser/condition'
|
|
70
75
|
require 'splitclient-rb/engine/parser/partition'
|
|
71
76
|
require 'splitclient-rb/engine/parser/evaluator'
|
|
@@ -112,6 +117,13 @@ require 'splitclient-rb/engine/models/split_http_response'
|
|
|
112
117
|
require 'splitclient-rb/engine/models/evaluation_options'
|
|
113
118
|
require 'splitclient-rb/engine/models/fallback_treatment.rb'
|
|
114
119
|
require 'splitclient-rb/engine/models/fallback_treatments_configuration.rb'
|
|
120
|
+
require 'splitclient-rb/engine/models/events_metadata.rb'
|
|
121
|
+
require 'splitclient-rb/engine/models/sdk_event_type.rb'
|
|
122
|
+
require 'splitclient-rb/engine/models/sdk_event.rb'
|
|
123
|
+
require 'splitclient-rb/engine/models/sdk_internal_event.rb'
|
|
124
|
+
require 'splitclient-rb/engine/models/sdk_internal_event_notification.rb'
|
|
125
|
+
require 'splitclient-rb/engine/models/valid_sdk_event.rb'
|
|
126
|
+
require 'splitclient-rb/engine/models/event_active_subscriptions.rb'
|
|
115
127
|
require 'splitclient-rb/engine/auth_api_client'
|
|
116
128
|
require 'splitclient-rb/engine/back_off'
|
|
117
129
|
require 'splitclient-rb/engine/fallback_treatment_calculator.rb'
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: splitclient-rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.
|
|
4
|
+
version: 8.11.0.pre.rc1
|
|
5
5
|
platform: java
|
|
6
6
|
authors:
|
|
7
7
|
- Split Software
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-03-09 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: allocation_stats
|
|
@@ -393,6 +393,7 @@ files:
|
|
|
393
393
|
- CONTRIBUTORS-GUIDE.md
|
|
394
394
|
- Gemfile
|
|
395
395
|
- LICENSE
|
|
396
|
+
- NOTICE.txt
|
|
396
397
|
- README.md
|
|
397
398
|
- Rakefile
|
|
398
399
|
- ext/murmurhash/MurmurHash3.java
|
|
@@ -454,6 +455,11 @@ files:
|
|
|
454
455
|
- lib/splitclient-rb/engine/common/impressions_manager.rb
|
|
455
456
|
- lib/splitclient-rb/engine/common/noop_impressions_counter.rb
|
|
456
457
|
- lib/splitclient-rb/engine/evaluator/splitter.rb
|
|
458
|
+
- lib/splitclient-rb/engine/events/events_delivery.rb
|
|
459
|
+
- lib/splitclient-rb/engine/events/events_manager.rb
|
|
460
|
+
- lib/splitclient-rb/engine/events/events_manager_config.rb
|
|
461
|
+
- lib/splitclient-rb/engine/events/events_task.rb
|
|
462
|
+
- lib/splitclient-rb/engine/events/noop_events_queue.rb
|
|
457
463
|
- lib/splitclient-rb/engine/fallback_treatment_calculator.rb
|
|
458
464
|
- lib/splitclient-rb/engine/impressions/noop_unique_keys_tracker.rb
|
|
459
465
|
- lib/splitclient-rb/engine/impressions/unique_keys_tracker.rb
|
|
@@ -489,13 +495,20 @@ files:
|
|
|
489
495
|
- lib/splitclient-rb/engine/matchers/whitelist_matcher.rb
|
|
490
496
|
- lib/splitclient-rb/engine/metrics/binary_search_latency_tracker.rb
|
|
491
497
|
- lib/splitclient-rb/engine/models/evaluation_options.rb
|
|
498
|
+
- lib/splitclient-rb/engine/models/event_active_subscriptions.rb
|
|
499
|
+
- lib/splitclient-rb/engine/models/events_metadata.rb
|
|
492
500
|
- lib/splitclient-rb/engine/models/fallback_treatment.rb
|
|
493
501
|
- lib/splitclient-rb/engine/models/fallback_treatments_configuration.rb
|
|
494
502
|
- lib/splitclient-rb/engine/models/label.rb
|
|
503
|
+
- lib/splitclient-rb/engine/models/sdk_event.rb
|
|
504
|
+
- lib/splitclient-rb/engine/models/sdk_event_type.rb
|
|
505
|
+
- lib/splitclient-rb/engine/models/sdk_internal_event.rb
|
|
506
|
+
- lib/splitclient-rb/engine/models/sdk_internal_event_notification.rb
|
|
495
507
|
- lib/splitclient-rb/engine/models/segment_type.rb
|
|
496
508
|
- lib/splitclient-rb/engine/models/split.rb
|
|
497
509
|
- lib/splitclient-rb/engine/models/split_http_response.rb
|
|
498
510
|
- lib/splitclient-rb/engine/models/treatment.rb
|
|
511
|
+
- lib/splitclient-rb/engine/models/valid_sdk_event.rb
|
|
499
512
|
- lib/splitclient-rb/engine/parser/condition.rb
|
|
500
513
|
- lib/splitclient-rb/engine/parser/evaluator.rb
|
|
501
514
|
- lib/splitclient-rb/engine/parser/partition.rb
|