splitclient-rb 8.11.0.pre.rc3-java → 8.11.1-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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: adc131ee06c937b8f58b9b080aa31020bb6f27ab180e3cb8c7044033e180f955
4
- data.tar.gz: 921724ee2c32de95c7bae36a9e24ae212526d2de03faacc2f6a9514ccc181a53
3
+ metadata.gz: 42f4513d606ae1bd73cac99c13e599ee584143fc939d099761654718b45646ce
4
+ data.tar.gz: 429ed13faae4bbe470e75ecf6c03d8a03dd684eb96571d8d92c86d59f5e1ab4d
5
5
  SHA512:
6
- metadata.gz: 0e8e36bdaa283d0ce1d00b23ca25a2d5904e82f2caeb6d610eeb7b18705268a44661e5aaf6b8b179ab116b9ea904802b69b33655c65a5acdc9f4b05aacc95526
7
- data.tar.gz: b5dbcc2c74fe8830a9d2ec091f1bac1f20814c47f5e69fad8f565e478bc52b08c0c8604cc10c1523567d8b7df79143887f0275f1cb969f83b64274f24294454f
6
+ metadata.gz: 50a4fd241f140432f70e56addfe105adeac5a678bbe8f1448a9bd49764de9aba7dd623ea7df473f36d7beccdf0dcd889c081c416360f5d91ccaa28fc772bdff1
7
+ data.tar.gz: 2726e5c96355472ab3e7f6ec035c43dca55d9f22d6f6db026715c252769fcd02da7ad282797d61aaed69fa08b17ad33c82ddc659d9243bc08a2987caae9bdf33
data/CHANGES.txt CHANGED
@@ -1,5 +1,15 @@
1
1
  CHANGES
2
2
 
3
+ 8.11.1 (Jul, 23, 2026)
4
+ - Added a retry mechanism in case the initial SSE socket connection failed, and extended the list of retryable errors when socket exceptions are caught during streaming.
5
+ - Fixed debug logging in rule-based segment matcher class when debug_enabled parameter is not set in configuration .
6
+ - Fixed a debug log that caused exception when streaming socket closes.
7
+
8
+ 8.11.0 (Mar, 12, 2026)
9
+ - Added the ability to listen to different events triggered by the SDK. Read more in our docs.
10
+ - SDK_UPDATE notify when a flag or user segment has changed
11
+ - SDK_READY notify when the SDK is ready to evaluate
12
+
3
13
  8.10.1 (Jan 28, 2025)
4
14
  - Fixed rule-based segment matcher to exit when a conition is met.
5
15
  - Fixed impressions properties format in redis mode.
data/LICENSE CHANGED
@@ -157,7 +157,7 @@ Apache License
157
157
  file or class name and description of purpose be included on the
158
158
  same "printed page" as the copyright notice for easier
159
159
  identification within third-party archives.
160
- Copyright [yyyy] [name of copyright owner]
160
+ Copyright 2025 Harness Corporation
161
161
  Licensed under the Apache License, Version 2.0 (the "License");
162
162
  you may not use this file except in compliance with the License.
163
163
  You may obtain a copy of the License at
@@ -40,7 +40,7 @@ module SplitIoClient
40
40
  break if matched
41
41
  end
42
42
 
43
- @logger.debug("[InRuleSegmentMatcher] #{@segment_name} is in rule based segment -> #{matched}")
43
+ @config.logger.debug("[InRuleSegmentMatcher] #{@segment_name} is in rule based segment -> #{matched}") if @config.debug_enabled
44
44
  matched
45
45
  end
46
46
 
@@ -16,17 +16,21 @@ module SplitIoClient
16
16
  response = @auth_api_client.authenticate(@api_key)
17
17
  @config.logger.debug("Auth service response push_enabled: #{response[:push_enabled]}") if @config.debug_enabled
18
18
 
19
- if response[:push_enabled] && @sse_handler.start(response[:token], response[:channels])
20
- schedule_next_token_refresh(response[:exp])
21
- @back_off.reset
22
- record_telemetry(response[:exp])
19
+ unless response[:push_enabled]
20
+ schedule_next_token_refresh(@back_off.interval) if response[:retry]
21
+ return false
22
+ end
23
23
 
24
- return true
24
+ unless @sse_handler.start(response[:token], response[:channels])
25
+ @config.logger.debug('Streaming server returned error') if @config.debug_enabled
26
+ stop_sse
27
+ return false
25
28
  end
26
29
 
27
- stop_sse
28
- schedule_next_token_refresh(@back_off.interval) if response[:retry]
29
- false
30
+ schedule_next_token_refresh(response[:exp])
31
+ @back_off.reset
32
+ record_telemetry(response[:exp])
33
+ true
30
34
  rescue StandardError => e
31
35
  @config.logger.error("start_sse: #{e.inspect}")
32
36
  end
@@ -6,14 +6,8 @@ module SplitIoClient
6
6
  SYNC_MODE_STREAMING = 0
7
7
  SYNC_MODE_POLLING = 1
8
8
 
9
- def initialize(config,
10
- synchronizer,
11
- telemetry_runtime_producer,
12
- telemetry_synchronizer,
13
- status_manager,
14
- sse_handler,
15
- push_manager,
16
- status_queue)
9
+ def initialize(config, synchronizer, telemetry_runtime_producer, telemetry_synchronizer,
10
+ status_manager, sse_handler, push_manager, status_queue)
17
11
  @config = config
18
12
  @synchronizer = synchronizer
19
13
  @telemetry_runtime_producer = telemetry_runtime_producer
@@ -23,6 +17,7 @@ module SplitIoClient
23
17
  @push_manager = push_manager
24
18
  @status_queue = status_queue
25
19
  @sse_connected = Concurrent::AtomicBoolean.new(false)
20
+ @back_off = Engine::BackOff.new(1, 3)
26
21
  end
27
22
 
28
23
  def start
@@ -119,7 +114,7 @@ module SplitIoClient
119
114
  end
120
115
 
121
116
  def process_disconnect(reconnect)
122
- unless @sse_connected.value
117
+ unless @sse_connected.value || reconnect
123
118
  @config.logger.debug('Streaming already disconnected.') if @config.debug_enabled
124
119
  return
125
120
  end
@@ -130,6 +125,9 @@ module SplitIoClient
130
125
  record_telemetry(Telemetry::Domain::Constants::SYNC_MODE, SYNC_MODE_POLLING)
131
126
 
132
127
  if reconnect
128
+ wait_interval = @back_off.interval
129
+ @config.logger.debug("Retrying streaming connection in: #{wait_interval} seconds")
130
+ sleep(wait_interval)
133
131
  @push_manager.stop_sse
134
132
  @synchronizer.sync_all
135
133
  @push_manager.start_sse
@@ -155,6 +153,7 @@ module SplitIoClient
155
153
 
156
154
  case status
157
155
  when Constants::PUSH_CONNECTED
156
+ @back_off.reset
158
157
  process_connected
159
158
  when Constants::PUSH_RETRYABLE_ERROR
160
159
  process_disconnect(true)
@@ -55,8 +55,8 @@ module SplitIoClient
55
55
  end
56
56
 
57
57
  def start_periodic_fetch
58
- @split_fetcher.call
59
- @segment_fetcher.call
58
+ @split_fetcher.call unless Helpers::ThreadHelper.alive?(:split_fetcher, @config)
59
+ @segment_fetcher.call unless Helpers::ThreadHelper.alive?(:segment_fetcher, @config)
60
60
  end
61
61
 
62
62
  def stop_periodic_fetch
@@ -10,7 +10,7 @@ module SplitIoClient
10
10
  module EventSource
11
11
  class Client
12
12
  DEFAULT_READ_TIMEOUT = 70
13
- CONNECT_TIMEOUT = 30_000
13
+ CONNECT_TIMEOUT = 30
14
14
  OK_CODE = 200
15
15
  KEEP_ALIVE_RESPONSE = "c\r\n:keepalive\n\n\r\n".freeze
16
16
  ERROR_EVENT_TYPE = 'error'.freeze
@@ -37,17 +37,15 @@ module SplitIoClient
37
37
  end
38
38
 
39
39
  def close(status = nil)
40
- unless connected?
41
- @config.logger.debug('SSEClient already disconected.') if @config.debug_enabled
42
- return
43
- end
44
- @config.logger.debug("Closing SSEClient socket") if @config.debug_enabled
40
+ return if @socket.nil?
45
41
 
42
+ @config.logger.debug("Closing SSEClient socket") if @config.debug_enabled
46
43
  push_status(status)
47
44
  @connected.make_false
48
45
  @socket.sync_close = true if @socket.is_a? OpenSSL::SSL::SSLSocket
49
46
  @socket.close
50
- @config.logger.debug("SSEClient socket state #{@socket.state}") if @socket.is_a? OpenSSL::SSL::SSLSocket && @config.debug_enabled
47
+ @config.logger.debug("SSEClient socket state #{@socket.state}") if @socket.is_a?(OpenSSL::SSL::SSLSocket) && @config.debug_enabled
48
+ @socket = nil
51
49
  rescue StandardError => e
52
50
  @config.logger.error("SSEClient close Error: #{e.inspect}")
53
51
  end
@@ -80,21 +78,21 @@ module SplitIoClient
80
78
  @config.threads[:connect_stream] = Thread.new do
81
79
  @config.logger.info('Starting connect_stream thread ...')
82
80
  new_status = connect_stream(latch)
83
- push_status(new_status)
81
+ push_status(new_status) unless new_status.nil?
84
82
  @config.logger.info('connect_stream thread finished.')
85
83
  end
86
84
  end
87
85
 
88
86
  def connect_stream(latch)
89
- return Constants::PUSH_NONRETRYABLE_ERROR unless socket_write(latch)
87
+ return Constants::PUSH_RETRYABLE_ERROR unless socket_write(latch)
90
88
  while connected? || @first_event.value
91
89
  begin
92
90
  if IO.select([@socket], nil, nil, @read_timeout)
93
91
  begin
94
92
  partial_data = @socket.readpartial(10_000)
95
- read_first_event(partial_data, latch)
96
93
 
97
- raise 'eof exception' if partial_data == :eof
94
+ first_event_status = read_first_event(partial_data, latch)
95
+ return first_event_status unless first_event_status.nil?
98
96
  rescue IO::WaitReadable => e
99
97
  @config.logger.debug("SSE client IO::WaitReadable transient error: #{e.inspect}") if @config.debug_enabled
100
98
  IO.select([@socket], nil, nil, @read_timeout)
@@ -107,8 +105,8 @@ module SplitIoClient
107
105
  @config.logger.error("SSE read operation timed out!: #{e.inspect}")
108
106
  return Constants::PUSH_RETRYABLE_ERROR
109
107
  rescue EOFError => e
110
- @config.logger.error("SSE read operation EOF Exception!: #{e.inspect}")
111
- raise 'eof exception'
108
+ @config.logger.error("SSE read operation EOF, server closed the connection, will reconnect: #{e.inspect}")
109
+ return Constants::PUSH_RETRYABLE_ERROR
112
110
  rescue Errno::EBADF, IOError => e
113
111
  @config.logger.error("SSE read operation EBADF or IOError: #{e.inspect}")
114
112
  return Constants::PUSH_RETRYABLE_ERROR
@@ -123,14 +121,9 @@ module SplitIoClient
123
121
  @config.logger.error("SSE read operation timed out, no data available.")
124
122
  return Constants::PUSH_RETRYABLE_ERROR
125
123
  end
126
- rescue Errno::EBADF
127
- @config.logger.debug("SSE socket is not connected (Errno::EBADF)") if @config.debug_enabled
128
- break
129
- rescue RuntimeError
130
- raise 'eof exception'
131
124
  rescue Exception => e
132
125
  @config.logger.debug("SSE socket is not connected: #{e.inspect}") if @config.debug_enabled
133
- break
126
+ return Constants::PUSH_RETRYABLE_ERROR
134
127
  end
135
128
 
136
129
  process_data(partial_data)
@@ -157,19 +150,20 @@ module SplitIoClient
157
150
  response_code = @event_parser.first_event(data)
158
151
  @config.logger.debug("SSE client first event code: #{response_code}") if @config.debug_enabled
159
152
 
160
- error_event = false
161
- events = @event_parser.parse(data)
162
- events.each { |e| error_event = true if e.event_type == ERROR_EVENT_TYPE }
163
153
  @first_event.make_false
164
154
 
165
- if response_code == OK_CODE && !error_event
166
- @connected.make_true
167
- @config.logger.debug("SSE client first event Connected is true") if @config.debug_enabled
168
- @telemetry_runtime_producer.record_streaming_event(Telemetry::Domain::Constants::SSE_CONNECTION_ESTABLISHED, nil)
169
- push_status(Constants::PUSH_CONNECTED)
155
+ if response_code != OK_CODE
156
+ @config.logger.error("SSE first event failed, code: #{response_code}")
157
+ latch.count_down
158
+ return Constants::PUSH_RETRYABLE_ERROR
170
159
  end
171
160
 
161
+ @connected.make_true
162
+ @config.logger.debug("SSE client first event Connected is true") if @config.debug_enabled
163
+ @telemetry_runtime_producer.record_streaming_event(Telemetry::Domain::Constants::SSE_CONNECTION_ESTABLISHED, nil)
164
+ push_status(Constants::PUSH_CONNECTED)
172
165
  latch.count_down
166
+ return nil
173
167
  end
174
168
 
175
169
  def socket_connect
@@ -1,3 +1,3 @@
1
1
  module SplitIoClient
2
- VERSION = '8.11.0-rc3'
2
+ VERSION = '8.11.1'
3
3
  end
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.11.0.pre.rc3
4
+ version: 8.11.1
5
5
  platform: java
6
6
  authors:
7
7
  - Split Software
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-03-11 00:00:00.000000000 Z
10
+ date: 2026-07-23 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: allocation_stats