Skip to content

Commit 87b94d0

Browse files
authored
Merge pull request #356 from splitio/development
[7.2.3] Development into Master
2 parents e49c9d7 + 1a90236 commit 87b94d0

23 files changed

Lines changed: 463 additions & 351 deletions

.rubocop.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ Metrics/MethodLength:
1010
Metrics/ClassLength:
1111
Max: 150
1212

13+
Metrics/CyclomaticComplexity:
14+
Max: 8
15+
1316
Metrics/LineLength:
1417
Max: 130
1518
Exclude:

CHANGES.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
CHANGES
22

3+
7.2.3 (Feb 24, 2021)
4+
- Fixed missing segment fetch after an SPLIT_UPDATE.
5+
- Updated streaming logic to support multiregion.
6+
- Updated sse client connection logic to read confirmation event.
7+
- Updated naming of retryable erros.
8+
39
7.2.2 (Dec 18, 2020)
410
- Fixed issue: undefined local variable or method post_impressions_count
511

lib/splitclient-rb/cache/fetchers/segment_fetcher.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,22 @@ def call
2727
end
2828
end
2929

30+
def fetch_segments_if_not_exists(names)
31+
names.each do |name|
32+
change_number = @segments_repository.get_change_number(name)
33+
34+
fetch_segment(name) if change_number == -1
35+
end
36+
rescue StandardError => error
37+
@config.log_found_exception(__method__.to_s, error)
38+
end
39+
3040
def fetch_segment(name)
3141
@semaphore.synchronize do
3242
segments_api.fetch_segments_by_names([name])
33-
true
3443
end
3544
rescue StandardError => error
3645
@config.log_found_exception(__method__.to_s, error)
37-
false
3846
end
3947

4048
def fetch_segments

lib/splitclient-rb/cache/fetchers/split_fetcher.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ def fetch_splits
4141
@config.logger.debug("segments seen(#{data[:segment_names].length}): #{data[:segment_names].to_a}") if @config.debug_enabled
4242

4343
@sdk_blocker.splits_ready!
44-
true
44+
45+
data[:segment_names]
4546
end
4647
rescue StandardError => error
4748
@config.log_found_exception(__method__.to_s, error)
48-
false
4949
end
5050

5151
def stop_splits_thread

lib/splitclient-rb/constants.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,10 @@ class SplitIoClient::Constants
66
CONTROL_SEC = 'control_sec'
77
OCCUPANCY_CHANNEL_PREFIX = '[?occupancy=metrics.publishers]'
88
FETCH_BACK_OFF_BASE_RETRIES = 1
9+
PUSH_CONNECTED = 'PUSH_CONNECTED'
10+
PUSH_RETRYABLE_ERROR = 'PUSH_RETRYABLE_ERROR'
11+
PUSH_NONRETRYABLE_ERROR = 'PUSH_NONRETRYABLE_ERROR'
12+
PUSH_SUBSYSTEM_DOWN = 'PUSH_SUBSYSTEM_DOWN'
13+
PUSH_SUBSYSTEM_READY = 'PUSH_SUBSYSTEM_READY'
14+
PUSH_SUBSYSTEM_OFF = 'PUSH_SUBSYSTEM_OFF'
915
end
10-

lib/splitclient-rb/engine/push_manager.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ def start_sse
1919
if response[:push_enabled] && @sse_handler.start(response[:token], response[:channels])
2020
schedule_next_token_refresh(response[:exp])
2121
@back_off.reset
22-
return
22+
return true
2323
end
2424

2525
stop_sse
2626

2727
schedule_next_token_refresh(@back_off.interval) if response[:retry]
28+
false
2829
rescue StandardError => e
2930
@config.logger.error("start_sse: #{e.inspect}")
3031
end

lib/splitclient-rb/engine/sync_manager.rb

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ def initialize(
1111
)
1212
@synchronizer = synchronizer
1313
notification_manager_keeper = SplitIoClient::SSE::NotificationManagerKeeper.new(config) do |manager|
14-
manager.on_occupancy { |publisher_available| process_occupancy(publisher_available) }
15-
manager.on_push_shutdown { process_push_shutdown }
14+
manager.on_action { |action| process_action(action) }
1615
end
1716
@sse_handler = SplitIoClient::SSE::SSEHandler.new(
1817
config,
@@ -21,8 +20,7 @@ def initialize(
2120
repositories[:segments],
2221
notification_manager_keeper
2322
) do |handler|
24-
handler.on_connected { process_connected }
25-
handler.on_disconnect { |reconnect| process_disconnect(reconnect) }
23+
handler.on_action { |action| process_action(action) }
2624
end
2725

2826
@push_manager = PushManager.new(config, @sse_handler, api_key)
@@ -44,10 +42,10 @@ def start
4442
# Starts tasks if stream is enabled.
4543
def start_stream
4644
@config.logger.debug('Starting push mode ...')
47-
stream_start_thread
45+
sync_all_thread
4846
@synchronizer.start_periodic_data_recording
4947

50-
stream_start_sse_thread
48+
start_sse_connection_thread
5149
end
5250

5351
def start_poll
@@ -59,23 +57,24 @@ def start_poll
5957
end
6058

6159
# Starts thread which fetch splits and segments once and trigger task to periodic data recording.
62-
def stream_start_thread
60+
def sync_all_thread
6361
@config.threads[:sync_manager_start_stream] = Thread.new do
6462
begin
6563
@synchronizer.sync_all
6664
rescue StandardError => e
67-
@config.logger.error("stream_start_thread error : #{e.inspect}")
65+
@config.logger.error("sync_all_thread error : #{e.inspect}")
6866
end
6967
end
7068
end
7169

7270
# Starts thread which connect to sse and after that fetch splits and segments once.
73-
def stream_start_sse_thread
71+
def start_sse_connection_thread
7472
@config.threads[:sync_manager_start_sse] = Thread.new do
7573
begin
76-
@push_manager.start_sse
74+
connected = @push_manager.start_sse
75+
@synchronizer.start_periodic_fetch unless connected
7776
rescue StandardError => e
78-
@config.logger.error("stream_start_sse_thread error : #{e.inspect}")
77+
@config.logger.error("start_sse_connection_thread error : #{e.inspect}")
7978
end
8079
end
8180
end
@@ -84,6 +83,46 @@ def start_stream_forked
8483
PhusionPassenger.on_event(:starting_worker_process) { |forked| start_stream if forked }
8584
end
8685

86+
def process_action(action)
87+
case action
88+
when Constants::PUSH_CONNECTED
89+
process_connected
90+
when Constants::PUSH_RETRYABLE_ERROR
91+
process_disconnect(true)
92+
when Constants::PUSH_NONRETRYABLE_ERROR
93+
process_disconnect(false)
94+
when Constants::PUSH_SUBSYSTEM_DOWN
95+
process_subsystem_down
96+
when Constants::PUSH_SUBSYSTEM_READY
97+
process_subsystem_ready
98+
when Constants::PUSH_SUBSYSTEM_OFF
99+
process_push_shutdown
100+
else
101+
@config.logger.debug('Incorrect action type.')
102+
end
103+
rescue StandardError => e
104+
@config.logger.error("process_action error: #{e.inspect}")
105+
end
106+
107+
def process_subsystem_ready
108+
@synchronizer.stop_periodic_fetch
109+
@synchronizer.sync_all
110+
@sse_handler.start_workers
111+
end
112+
113+
def process_subsystem_down
114+
@sse_handler.stop_workers
115+
@synchronizer.start_periodic_fetch
116+
end
117+
118+
def process_push_shutdown
119+
@push_manager.stop_sse
120+
@sse_handler.stop_workers
121+
@synchronizer.start_periodic_fetch
122+
rescue StandardError => e
123+
@config.logger.error("process_push_shutdown error: #{e.inspect}")
124+
end
125+
87126
def process_connected
88127
if @sse_connected.value
89128
@config.logger.debug('Streaming already connected.')
@@ -115,28 +154,6 @@ def process_disconnect(reconnect)
115154
rescue StandardError => e
116155
@config.logger.error("process_disconnect error: #{e.inspect}")
117156
end
118-
119-
def process_occupancy(push_enable)
120-
if push_enable
121-
@synchronizer.stop_periodic_fetch
122-
@synchronizer.sync_all
123-
@sse_handler.start_workers
124-
return
125-
end
126-
127-
@sse_handler.stop_workers
128-
@synchronizer.start_periodic_fetch
129-
rescue StandardError => e
130-
@config.logger.error("process_occupancy error: #{e.inspect}")
131-
end
132-
133-
def process_push_shutdown
134-
@push_manager.stop_sse
135-
@sse_handler.stop_workers
136-
@synchronizer.start_periodic_fetch
137-
rescue StandardError => e
138-
@config.logger.error("process_push_shutdown error: #{e.inspect}")
139-
end
140157
end
141158
end
142159
end

lib/splitclient-rb/engine/synchronizer.rb

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def initialize(
3030
def sync_all
3131
@config.threads[:sync_all_thread] = Thread.new do
3232
@config.logger.debug('Synchronizing Splits and Segments ...') if @config.debug_enabled
33-
fetch_splits
33+
@split_fetcher.fetch_splits
3434
fetch_segments
3535
end
3636
end
@@ -53,21 +53,12 @@ def stop_periodic_fetch
5353
end
5454

5555
def fetch_splits
56-
back_off = SplitIoClient::SSE::EventSource::BackOff.new(SplitIoClient::Constants::FETCH_BACK_OFF_BASE_RETRIES, 1)
57-
loop do
58-
break if @split_fetcher.fetch_splits
59-
60-
sleep(back_off.interval)
61-
end
56+
segment_names = @split_fetcher.fetch_splits
57+
@segment_fetcher.fetch_segments_if_not_exists(segment_names) unless segment_names.empty?
6258
end
6359

6460
def fetch_segment(name)
65-
back_off = SplitIoClient::SSE::EventSource::BackOff.new(SplitIoClient::Constants::FETCH_BACK_OFF_BASE_RETRIES, 1)
66-
loop do
67-
break if @segment_fetcher.fetch_segment(name)
68-
69-
sleep(back_off.interval)
70-
end
61+
@segment_fetcher.fetch_segment(name)
7162
end
7263

7364
private

0 commit comments

Comments
 (0)