launchdarkly-server-sdk 8.11.1-java → 8.11.3-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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ldclient-rb/config.rb +66 -3
  3. data/lib/ldclient-rb/context.rb +1 -1
  4. data/lib/ldclient-rb/data_system.rb +243 -0
  5. data/lib/ldclient-rb/events.rb +35 -20
  6. data/lib/ldclient-rb/flags_state.rb +1 -1
  7. data/lib/ldclient-rb/impl/big_segments.rb +4 -4
  8. data/lib/ldclient-rb/impl/cache_store.rb +44 -0
  9. data/lib/ldclient-rb/impl/data_source/null_processor.rb +52 -0
  10. data/lib/ldclient-rb/impl/data_source/polling.rb +108 -0
  11. data/lib/ldclient-rb/impl/data_source/requestor.rb +106 -0
  12. data/lib/ldclient-rb/impl/data_source/status_provider.rb +78 -0
  13. data/lib/ldclient-rb/impl/data_source/stream.rb +198 -0
  14. data/lib/ldclient-rb/impl/data_source.rb +3 -3
  15. data/lib/ldclient-rb/impl/data_store/data_kind.rb +108 -0
  16. data/lib/ldclient-rb/impl/data_store/feature_store_client_wrapper.rb +187 -0
  17. data/lib/ldclient-rb/impl/data_store/in_memory_feature_store.rb +130 -0
  18. data/lib/ldclient-rb/impl/data_store/status_provider.rb +82 -0
  19. data/lib/ldclient-rb/impl/data_store/store.rb +371 -0
  20. data/lib/ldclient-rb/impl/data_store.rb +11 -97
  21. data/lib/ldclient-rb/impl/data_system/fdv1.rb +178 -0
  22. data/lib/ldclient-rb/impl/data_system/fdv2.rb +471 -0
  23. data/lib/ldclient-rb/impl/data_system/polling.rb +601 -0
  24. data/lib/ldclient-rb/impl/data_system/protocolv2.rb +264 -0
  25. data/lib/ldclient-rb/impl/data_system.rb +298 -0
  26. data/lib/ldclient-rb/impl/dependency_tracker.rb +21 -9
  27. data/lib/ldclient-rb/impl/evaluator.rb +3 -2
  28. data/lib/ldclient-rb/impl/event_sender.rb +4 -3
  29. data/lib/ldclient-rb/impl/expiring_cache.rb +79 -0
  30. data/lib/ldclient-rb/impl/integrations/file_data_source.rb +9 -9
  31. data/lib/ldclient-rb/impl/integrations/test_data/test_data_source.rb +0 -1
  32. data/lib/ldclient-rb/impl/integrations/test_data/test_data_source_v2.rb +288 -0
  33. data/lib/ldclient-rb/impl/memoized_value.rb +34 -0
  34. data/lib/ldclient-rb/impl/migrations/migrator.rb +2 -1
  35. data/lib/ldclient-rb/impl/migrations/tracker.rb +2 -1
  36. data/lib/ldclient-rb/impl/model/serialization.rb +6 -6
  37. data/lib/ldclient-rb/impl/non_blocking_thread_pool.rb +48 -0
  38. data/lib/ldclient-rb/impl/repeating_task.rb +2 -2
  39. data/lib/ldclient-rb/impl/simple_lru_cache.rb +27 -0
  40. data/lib/ldclient-rb/impl/util.rb +65 -0
  41. data/lib/ldclient-rb/impl.rb +1 -2
  42. data/lib/ldclient-rb/in_memory_store.rb +1 -18
  43. data/lib/ldclient-rb/integrations/test_data/flag_builder.rb +9 -9
  44. data/lib/ldclient-rb/integrations/test_data.rb +11 -11
  45. data/lib/ldclient-rb/integrations/test_data_v2/flag_builder_v2.rb +582 -0
  46. data/lib/ldclient-rb/integrations/test_data_v2.rb +248 -0
  47. data/lib/ldclient-rb/integrations/util/store_wrapper.rb +3 -2
  48. data/lib/ldclient-rb/interfaces/data_system.rb +755 -0
  49. data/lib/ldclient-rb/interfaces/feature_store.rb +3 -0
  50. data/lib/ldclient-rb/ldclient.rb +55 -149
  51. data/lib/ldclient-rb/util.rb +11 -70
  52. data/lib/ldclient-rb/version.rb +1 -1
  53. data/lib/ldclient-rb.rb +8 -17
  54. metadata +52 -17
  55. data/lib/ldclient-rb/cache_store.rb +0 -45
  56. data/lib/ldclient-rb/expiring_cache.rb +0 -77
  57. data/lib/ldclient-rb/memoized_value.rb +0 -32
  58. data/lib/ldclient-rb/non_blocking_thread_pool.rb +0 -46
  59. data/lib/ldclient-rb/polling.rb +0 -102
  60. data/lib/ldclient-rb/requestor.rb +0 -102
  61. data/lib/ldclient-rb/simple_lru_cache.rb +0 -25
  62. data/lib/ldclient-rb/stream.rb +0 -196
@@ -1,196 +0,0 @@
1
- require "ldclient-rb/impl/model/serialization"
2
-
3
- require "concurrent/atomics"
4
- require "json"
5
- require "ld-eventsource"
6
-
7
- module LaunchDarkly
8
- # @private
9
- PUT = :put
10
- # @private
11
- PATCH = :patch
12
- # @private
13
- DELETE = :delete
14
- # @private
15
- READ_TIMEOUT_SECONDS = 300 # 5 minutes; the stream should send a ping every 3 minutes
16
-
17
- # @private
18
- KEY_PATHS = {
19
- FEATURES => "/flags/",
20
- SEGMENTS => "/segments/",
21
- }
22
-
23
- # @private
24
- class StreamProcessor
25
- def initialize(sdk_key, config, diagnostic_accumulator = nil)
26
- @sdk_key = sdk_key
27
- @config = config
28
- @data_source_update_sink = config.data_source_update_sink
29
- @feature_store = config.feature_store
30
- @initialized = Concurrent::AtomicBoolean.new(false)
31
- @started = Concurrent::AtomicBoolean.new(false)
32
- @stopped = Concurrent::AtomicBoolean.new(false)
33
- @ready = Concurrent::Event.new
34
- @connection_attempt_start_time = 0
35
- end
36
-
37
- def initialized?
38
- @initialized.value
39
- end
40
-
41
- def start
42
- return @ready unless @started.make_true
43
-
44
- @config.logger.info { "[LDClient] Initializing stream connection" }
45
-
46
- headers = Impl::Util.default_http_headers(@sdk_key, @config)
47
- opts = {
48
- headers: headers,
49
- read_timeout: READ_TIMEOUT_SECONDS,
50
- logger: @config.logger,
51
- socket_factory: @config.socket_factory,
52
- reconnect_time: @config.initial_reconnect_delay,
53
- }
54
- log_connection_started
55
-
56
- uri = Util.add_payload_filter_key(@config.stream_uri + "/all", @config)
57
- @es = SSE::Client.new(uri, **opts) do |conn|
58
- conn.on_event { |event| process_message(event) }
59
- conn.on_error { |err|
60
- log_connection_result(false)
61
- case err
62
- when SSE::Errors::HTTPStatusError
63
- status = err.status
64
- error_info = LaunchDarkly::Interfaces::DataSource::ErrorInfo.new(
65
- LaunchDarkly::Interfaces::DataSource::ErrorInfo::ERROR_RESPONSE, status, nil, Time.now)
66
- message = Util.http_error_message(status, "streaming connection", "will retry")
67
- @config.logger.error { "[LDClient] #{message}" }
68
-
69
- if Util.http_error_recoverable?(status)
70
- @data_source_update_sink&.update_status(
71
- LaunchDarkly::Interfaces::DataSource::Status::INTERRUPTED,
72
- error_info
73
- )
74
- else
75
- @ready.set # if client was waiting on us, make it stop waiting - has no effect if already set
76
- stop_with_error_info error_info
77
- end
78
- when SSE::Errors::HTTPContentTypeError, SSE::Errors::HTTPProxyError, SSE::Errors::ReadTimeoutError
79
- @data_source_update_sink&.update_status(
80
- LaunchDarkly::Interfaces::DataSource::Status::INTERRUPTED,
81
- LaunchDarkly::Interfaces::DataSource::ErrorInfo.new(LaunchDarkly::Interfaces::DataSource::ErrorInfo::NETWORK_ERROR, 0, err.to_s, Time.now)
82
- )
83
-
84
- else
85
- @data_source_update_sink&.update_status(
86
- LaunchDarkly::Interfaces::DataSource::Status::INTERRUPTED,
87
- LaunchDarkly::Interfaces::DataSource::ErrorInfo.new(LaunchDarkly::Interfaces::DataSource::ErrorInfo::UNKNOWN, 0, err.to_s, Time.now)
88
- )
89
- end
90
- }
91
- end
92
-
93
- @ready
94
- end
95
-
96
- def stop
97
- stop_with_error_info
98
- end
99
-
100
- private
101
-
102
- #
103
- # @param [LaunchDarkly::Interfaces::DataSource::ErrorInfo, nil] error_info
104
- #
105
- def stop_with_error_info(error_info = nil)
106
- if @stopped.make_true
107
- @es.close
108
- @data_source_update_sink&.update_status(LaunchDarkly::Interfaces::DataSource::Status::OFF, error_info)
109
- @config.logger.info { "[LDClient] Stream connection stopped" }
110
- end
111
- end
112
-
113
- #
114
- # The original implementation of this class relied on the feature store
115
- # directly, which we are trying to move away from. Customers who might have
116
- # instantiated this directly for some reason wouldn't know they have to set
117
- # the config's sink manually, so we have to fall back to the store if the
118
- # sink isn't present.
119
- #
120
- # The next major release should be able to simplify this structure and
121
- # remove the need for fall back to the data store because the update sink
122
- # should always be present.
123
- #
124
- def update_sink_or_data_store
125
- @data_source_update_sink || @feature_store
126
- end
127
-
128
- def process_message(message)
129
- log_connection_result(true)
130
- method = message.type
131
- @config.logger.debug { "[LDClient] Stream received #{method} message: #{message.data}" }
132
-
133
- begin
134
- if method == PUT
135
- message = JSON.parse(message.data, symbolize_names: true)
136
- all_data = Impl::Model.make_all_store_data(message[:data], @config.logger)
137
- update_sink_or_data_store.init(all_data)
138
- @initialized.make_true
139
- @config.logger.info { "[LDClient] Stream initialized" }
140
- @ready.set
141
- elsif method == PATCH
142
- data = JSON.parse(message.data, symbolize_names: true)
143
- for kind in [FEATURES, SEGMENTS]
144
- key = key_for_path(kind, data[:path])
145
- if key
146
- item = Impl::Model.deserialize(kind, data[:data], @config.logger)
147
- update_sink_or_data_store.upsert(kind, item)
148
- break
149
- end
150
- end
151
- elsif method == DELETE
152
- data = JSON.parse(message.data, symbolize_names: true)
153
- for kind in [FEATURES, SEGMENTS]
154
- key = key_for_path(kind, data[:path])
155
- if key
156
- update_sink_or_data_store.delete(kind, key, data[:version])
157
- break
158
- end
159
- end
160
- else
161
- @config.logger.warn { "[LDClient] Unknown message received: #{method}" }
162
- end
163
-
164
- @data_source_update_sink&.update_status(LaunchDarkly::Interfaces::DataSource::Status::VALID, nil)
165
- rescue JSON::ParserError => e
166
- @config.logger.error { "[LDClient] JSON parsing failed for method #{method}. Ignoring event." }
167
- error_info = LaunchDarkly::Interfaces::DataSource::ErrorInfo.new(
168
- LaunchDarkly::Interfaces::DataSource::ErrorInfo::INVALID_DATA,
169
- 0,
170
- e.to_s,
171
- Time.now
172
- )
173
- @data_source_update_sink&.update_status(LaunchDarkly::Interfaces::DataSource::Status::INTERRUPTED, error_info)
174
-
175
- # Re-raise the exception so the SSE implementation can catch it and restart the stream.
176
- raise
177
- end
178
- end
179
-
180
- def key_for_path(kind, path)
181
- path.start_with?(KEY_PATHS[kind]) ? path[KEY_PATHS[kind].length..-1] : nil
182
- end
183
-
184
- def log_connection_started
185
- @connection_attempt_start_time = Impl::Util::current_time_millis
186
- end
187
-
188
- def log_connection_result(is_success)
189
- if !@diagnostic_accumulator.nil? && @connection_attempt_start_time > 0
190
- @diagnostic_accumulator.record_stream_init(@connection_attempt_start_time, !is_success,
191
- Impl::Util::current_time_millis - @connection_attempt_start_time)
192
- @connection_attempt_start_time = 0
193
- end
194
- end
195
- end
196
- end