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