launchdarkly-server-sdk 8.12.2 → 8.12.3
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/lib/ldclient-rb/config.rb +4 -4
- data/lib/ldclient-rb/data_system/config_builder.rb +104 -0
- data/lib/ldclient-rb/data_system/data_source_builder_common.rb +82 -0
- data/lib/ldclient-rb/data_system/polling_data_source_builder.rb +227 -0
- data/lib/ldclient-rb/data_system/streaming_data_source_builder.rb +73 -0
- data/lib/ldclient-rb/data_system.rb +50 -85
- data/lib/ldclient-rb/impl/data_source.rb +1 -1
- data/lib/ldclient-rb/impl/data_store/in_memory_feature_store.rb +3 -3
- data/lib/ldclient-rb/impl/data_store/store.rb +5 -5
- data/lib/ldclient-rb/impl/data_system/polling.rb +3 -126
- data/lib/ldclient-rb/impl/data_system/streaming.rb +1 -41
- data/lib/ldclient-rb/impl/dependency_tracker.rb +1 -1
- data/lib/ldclient-rb/impl/flag_tracker.rb +1 -1
- data/lib/ldclient-rb/interfaces/flag_tracker.rb +5 -5
- data/lib/ldclient-rb/version.rb +1 -1
- metadata +6 -3
- data/lib/ldclient-rb/impl/data_system/data_source_builder_common.rb +0 -77
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 57906761b3e8ac33ce67cb5fe508b930bced9dc76dc7627a11494ef30669cd31
|
|
4
|
+
data.tar.gz: 577eba2114e248f6c09e5d690d61a6213430c23a0edbef173c5ed60f4e3a0a58
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3935eb8fbfee75a13469a4ebadf223654ac1116a8d5075948fa3f260ef35faaf0207c443b4af04f6ad1a71579db880790ea3506ec1c5591087e111c9b7659915
|
|
7
|
+
data.tar.gz: d3470ce5c0877f180aaafa35aa98cae50daef51148caeaaa8d61a9e3b3ca50770ec65a654d3fcc18f6069876eece3d51551b325ac988ba4c9fcc02f71ecc772b
|
data/lib/ldclient-rb/config.rb
CHANGED
|
@@ -468,7 +468,7 @@ module LaunchDarkly
|
|
|
468
468
|
# @return [String] "https://sdk.launchdarkly.com"
|
|
469
469
|
#
|
|
470
470
|
def self.default_base_uri
|
|
471
|
-
|
|
471
|
+
DataSystem::PollingDataSourceBuilder::DEFAULT_BASE_URI
|
|
472
472
|
end
|
|
473
473
|
|
|
474
474
|
#
|
|
@@ -476,7 +476,7 @@ module LaunchDarkly
|
|
|
476
476
|
# @return [String] "https://stream.launchdarkly.com"
|
|
477
477
|
#
|
|
478
478
|
def self.default_stream_uri
|
|
479
|
-
|
|
479
|
+
DataSystem::StreamingDataSourceBuilder::DEFAULT_BASE_URI
|
|
480
480
|
end
|
|
481
481
|
|
|
482
482
|
#
|
|
@@ -516,7 +516,7 @@ module LaunchDarkly
|
|
|
516
516
|
# @return [Float] 1
|
|
517
517
|
#
|
|
518
518
|
def self.default_initial_reconnect_delay
|
|
519
|
-
|
|
519
|
+
DataSystem::StreamingDataSourceBuilder::DEFAULT_INITIAL_RECONNECT_DELAY
|
|
520
520
|
end
|
|
521
521
|
|
|
522
522
|
#
|
|
@@ -578,7 +578,7 @@ module LaunchDarkly
|
|
|
578
578
|
# @return [Float] 30
|
|
579
579
|
#
|
|
580
580
|
def self.default_poll_interval
|
|
581
|
-
|
|
581
|
+
DataSystem::PollingDataSourceBuilder::DEFAULT_POLL_INTERVAL
|
|
582
582
|
end
|
|
583
583
|
|
|
584
584
|
#
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ldclient-rb/interfaces/data_system"
|
|
4
|
+
|
|
5
|
+
module LaunchDarkly
|
|
6
|
+
module DataSystem
|
|
7
|
+
#
|
|
8
|
+
# Builder for the data system configuration.
|
|
9
|
+
#
|
|
10
|
+
# This builder configures the overall data acquisition strategy for the SDK,
|
|
11
|
+
# including which data sources to use for initialization and synchronization,
|
|
12
|
+
# and how to interact with a persistent data store.
|
|
13
|
+
#
|
|
14
|
+
# @see DataSystem.default
|
|
15
|
+
# @see DataSystem.streaming
|
|
16
|
+
# @see DataSystem.polling
|
|
17
|
+
# @see DataSystem.custom
|
|
18
|
+
#
|
|
19
|
+
class ConfigBuilder
|
|
20
|
+
def initialize
|
|
21
|
+
@initializers = nil
|
|
22
|
+
@synchronizers = nil
|
|
23
|
+
@fdv1_fallback_synchronizer = nil
|
|
24
|
+
@data_store_mode = LaunchDarkly::Interfaces::DataSystem::DataStoreMode::READ_ONLY
|
|
25
|
+
@data_store = nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
#
|
|
29
|
+
# Sets the initializers for the data system.
|
|
30
|
+
#
|
|
31
|
+
# Initializers are used to fetch an initial set of data when the SDK starts.
|
|
32
|
+
# They are tried in order; if the first one fails, the next is tried, and so on.
|
|
33
|
+
#
|
|
34
|
+
# @param initializers [Array<#build(String, Config)>]
|
|
35
|
+
# Array of builders that respond to build(sdk_key, config) and return an Initializer
|
|
36
|
+
# @return [ConfigBuilder] self for chaining
|
|
37
|
+
#
|
|
38
|
+
def initializers(initializers)
|
|
39
|
+
@initializers = initializers
|
|
40
|
+
self
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
# Sets the synchronizers for the data system.
|
|
45
|
+
#
|
|
46
|
+
# Synchronizers keep data up-to-date after initialization. Like initializers,
|
|
47
|
+
# they are tried in order. If the primary synchronizer fails, the next one
|
|
48
|
+
# takes over.
|
|
49
|
+
#
|
|
50
|
+
# @param synchronizers [Array<#build(String, Config)>]
|
|
51
|
+
# Array of builders that respond to build(sdk_key, config) and return a Synchronizer
|
|
52
|
+
# @return [ConfigBuilder] self for chaining
|
|
53
|
+
#
|
|
54
|
+
def synchronizers(synchronizers)
|
|
55
|
+
@synchronizers = synchronizers
|
|
56
|
+
self
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
#
|
|
60
|
+
# Configures the SDK with a fallback synchronizer that is compatible with
|
|
61
|
+
# the Flag Delivery v1 API.
|
|
62
|
+
#
|
|
63
|
+
# This fallback is used when the server signals that the environment should
|
|
64
|
+
# revert to FDv1 protocol. Most users will not need to set this directly.
|
|
65
|
+
#
|
|
66
|
+
# @param fallback [#build(String, Config)] Builder that responds to build(sdk_key, config) and returns the fallback Synchronizer
|
|
67
|
+
# @return [ConfigBuilder] self for chaining
|
|
68
|
+
#
|
|
69
|
+
def fdv1_compatible_synchronizer(fallback)
|
|
70
|
+
@fdv1_fallback_synchronizer = fallback
|
|
71
|
+
self
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
#
|
|
75
|
+
# Sets the data store configuration for the data system.
|
|
76
|
+
#
|
|
77
|
+
# @param data_store [LaunchDarkly::Interfaces::FeatureStore] The data store
|
|
78
|
+
# @param store_mode [Symbol] The store mode (use constants from
|
|
79
|
+
# {LaunchDarkly::Interfaces::DataSystem::DataStoreMode})
|
|
80
|
+
# @return [ConfigBuilder] self for chaining
|
|
81
|
+
#
|
|
82
|
+
def data_store(data_store, store_mode)
|
|
83
|
+
@data_store = data_store
|
|
84
|
+
@data_store_mode = store_mode
|
|
85
|
+
self
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
#
|
|
89
|
+
# Builds the data system configuration.
|
|
90
|
+
#
|
|
91
|
+
# @return [DataSystemConfig]
|
|
92
|
+
#
|
|
93
|
+
def build
|
|
94
|
+
DataSystemConfig.new(
|
|
95
|
+
initializers: @initializers,
|
|
96
|
+
synchronizers: @synchronizers,
|
|
97
|
+
data_store_mode: @data_store_mode,
|
|
98
|
+
data_store: @data_store,
|
|
99
|
+
fdv1_fallback_synchronizer: @fdv1_fallback_synchronizer
|
|
100
|
+
)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ldclient-rb/impl/data_system/http_config_options"
|
|
4
|
+
|
|
5
|
+
module LaunchDarkly
|
|
6
|
+
module DataSystem
|
|
7
|
+
#
|
|
8
|
+
# Common HTTP configuration methods shared by all data source builders.
|
|
9
|
+
#
|
|
10
|
+
# This module is included by {PollingDataSourceBuilder},
|
|
11
|
+
# {FDv1PollingDataSourceBuilder}, and {StreamingDataSourceBuilder} to provide
|
|
12
|
+
# a consistent set of HTTP connection settings.
|
|
13
|
+
#
|
|
14
|
+
# Each builder that includes this module must define a +DEFAULT_BASE_URI+ constant
|
|
15
|
+
# which is used as the fallback when {#base_uri} has not been called.
|
|
16
|
+
#
|
|
17
|
+
module DataSourceBuilderCommon
|
|
18
|
+
#
|
|
19
|
+
# Sets the base URI for HTTP requests.
|
|
20
|
+
#
|
|
21
|
+
# Use this to point the SDK at a Relay Proxy instance or any other URI
|
|
22
|
+
# that implements the corresponding LaunchDarkly API.
|
|
23
|
+
#
|
|
24
|
+
# @param uri [String] The base URI (e.g. "https://relay.example.com")
|
|
25
|
+
# @return [self] the builder, for chaining
|
|
26
|
+
#
|
|
27
|
+
def base_uri(uri)
|
|
28
|
+
@base_uri = uri
|
|
29
|
+
self
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
#
|
|
33
|
+
# Sets a custom socket factory for HTTP connections.
|
|
34
|
+
#
|
|
35
|
+
# @param factory [#open] A socket factory that responds to +open+
|
|
36
|
+
# @return [self] the builder, for chaining
|
|
37
|
+
#
|
|
38
|
+
def socket_factory(factory)
|
|
39
|
+
@socket_factory = factory
|
|
40
|
+
self
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
# Sets the read timeout for HTTP connections.
|
|
45
|
+
#
|
|
46
|
+
# @param timeout [Float] Timeout in seconds
|
|
47
|
+
# @return [self] the builder, for chaining
|
|
48
|
+
#
|
|
49
|
+
def read_timeout(timeout)
|
|
50
|
+
@read_timeout = timeout
|
|
51
|
+
self
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#
|
|
55
|
+
# Sets the connect timeout for HTTP connections.
|
|
56
|
+
#
|
|
57
|
+
# @param timeout [Float] Timeout in seconds
|
|
58
|
+
# @return [self] the builder, for chaining
|
|
59
|
+
#
|
|
60
|
+
def connect_timeout(timeout)
|
|
61
|
+
@connect_timeout = timeout
|
|
62
|
+
self
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#
|
|
66
|
+
# Builds an HttpConfigOptions instance from the current builder settings.
|
|
67
|
+
# Uses +self.class::DEFAULT_BASE_URI+ if {#base_uri} was not explicitly set.
|
|
68
|
+
# Read/connect timeouts default to HttpConfigOptions defaults if not set.
|
|
69
|
+
#
|
|
70
|
+
# @return [LaunchDarkly::Impl::DataSystem::HttpConfigOptions]
|
|
71
|
+
#
|
|
72
|
+
private def build_http_config
|
|
73
|
+
LaunchDarkly::Impl::DataSystem::HttpConfigOptions.new(
|
|
74
|
+
base_uri: (@base_uri || self.class::DEFAULT_BASE_URI).chomp("/"),
|
|
75
|
+
socket_factory: @socket_factory,
|
|
76
|
+
read_timeout: @read_timeout,
|
|
77
|
+
connect_timeout: @connect_timeout
|
|
78
|
+
)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ldclient-rb/data_system/data_source_builder_common"
|
|
4
|
+
|
|
5
|
+
module LaunchDarkly
|
|
6
|
+
module DataSystem
|
|
7
|
+
#
|
|
8
|
+
# Interface for custom polling requesters.
|
|
9
|
+
#
|
|
10
|
+
# A Requester is responsible for fetching data from a data source. The SDK
|
|
11
|
+
# ships with built-in HTTP requesters for both FDv2 and FDv1 polling endpoints,
|
|
12
|
+
# but you can implement this interface to provide custom data fetching logic
|
|
13
|
+
# (e.g., reading from a file, a database, or a custom API).
|
|
14
|
+
#
|
|
15
|
+
# == Implementing a Custom Requester
|
|
16
|
+
#
|
|
17
|
+
# To create a custom requester, include this module and implement the {#fetch}
|
|
18
|
+
# method:
|
|
19
|
+
#
|
|
20
|
+
# class MyCustomRequester
|
|
21
|
+
# include LaunchDarkly::DataSystem::Requester
|
|
22
|
+
#
|
|
23
|
+
# def fetch(selector)
|
|
24
|
+
# # Fetch data and return a Result containing [ChangeSet, headers]
|
|
25
|
+
# # ...
|
|
26
|
+
# LaunchDarkly::Result.success([change_set, {}])
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# def stop
|
|
30
|
+
# # Clean up resources
|
|
31
|
+
# end
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# polling = LaunchDarkly::DataSystem.polling_ds_builder
|
|
35
|
+
# .requester(MyCustomRequester.new)
|
|
36
|
+
#
|
|
37
|
+
# @see PollingDataSourceBuilder#requester
|
|
38
|
+
#
|
|
39
|
+
module Requester
|
|
40
|
+
#
|
|
41
|
+
# Fetches data for the given selector.
|
|
42
|
+
#
|
|
43
|
+
# @param selector [LaunchDarkly::Interfaces::DataSystem::Selector, nil]
|
|
44
|
+
# The selector describing what data to fetch. May be nil if no
|
|
45
|
+
# selector is available (e.g., on the first request).
|
|
46
|
+
# @return [LaunchDarkly::Result] A Result containing a tuple of
|
|
47
|
+
# [ChangeSet, headers] on success, or an error message on failure.
|
|
48
|
+
#
|
|
49
|
+
def fetch(selector)
|
|
50
|
+
raise NotImplementedError
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
#
|
|
54
|
+
# Releases any resources held by this requester (e.g., persistent HTTP
|
|
55
|
+
# connections). Called when the requester is no longer needed.
|
|
56
|
+
#
|
|
57
|
+
# Implementations should handle being called multiple times gracefully.
|
|
58
|
+
# The default implementation is a no-op.
|
|
59
|
+
#
|
|
60
|
+
def stop
|
|
61
|
+
# Optional - implementations may override if they need cleanup
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#
|
|
66
|
+
# Builder for a polling data source that communicates with LaunchDarkly's
|
|
67
|
+
# FDv2 polling endpoint.
|
|
68
|
+
#
|
|
69
|
+
# This builder can be used with {ConfigBuilder#initializers} or
|
|
70
|
+
# {ConfigBuilder#synchronizers} to create custom data system configurations.
|
|
71
|
+
#
|
|
72
|
+
# The polling data source periodically fetches data from LaunchDarkly. It
|
|
73
|
+
# supports conditional requests via ETags, so subsequent polls after the
|
|
74
|
+
# initial request only transfer data if changes have occurred.
|
|
75
|
+
#
|
|
76
|
+
# == Example
|
|
77
|
+
#
|
|
78
|
+
# polling = LaunchDarkly::DataSystem.polling_ds_builder
|
|
79
|
+
# .poll_interval(60)
|
|
80
|
+
# .base_uri("https://custom-endpoint.example.com")
|
|
81
|
+
#
|
|
82
|
+
# data_system = LaunchDarkly::DataSystem.custom
|
|
83
|
+
# .synchronizers([polling])
|
|
84
|
+
#
|
|
85
|
+
# @see DataSystem.polling_ds_builder
|
|
86
|
+
#
|
|
87
|
+
class PollingDataSourceBuilder
|
|
88
|
+
include LaunchDarkly::DataSystem::DataSourceBuilderCommon
|
|
89
|
+
|
|
90
|
+
# @return [String] The default base URI for polling requests
|
|
91
|
+
DEFAULT_BASE_URI = "https://sdk.launchdarkly.com"
|
|
92
|
+
|
|
93
|
+
# @return [Float] The default polling interval in seconds
|
|
94
|
+
DEFAULT_POLL_INTERVAL = 30
|
|
95
|
+
|
|
96
|
+
def initialize
|
|
97
|
+
@requester = nil
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
#
|
|
101
|
+
# Sets the polling interval in seconds.
|
|
102
|
+
#
|
|
103
|
+
# This controls how frequently the SDK polls LaunchDarkly for updates.
|
|
104
|
+
# Lower values mean more frequent updates but higher network traffic.
|
|
105
|
+
# The default is {DEFAULT_POLL_INTERVAL} seconds.
|
|
106
|
+
#
|
|
107
|
+
# @param secs [Float] Polling interval in seconds
|
|
108
|
+
# @return [PollingDataSourceBuilder] self for chaining
|
|
109
|
+
#
|
|
110
|
+
def poll_interval(secs)
|
|
111
|
+
@poll_interval = secs
|
|
112
|
+
self
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
#
|
|
116
|
+
# Sets a custom {Requester} for this polling data source.
|
|
117
|
+
#
|
|
118
|
+
# By default, the builder uses an HTTP requester that communicates with
|
|
119
|
+
# LaunchDarkly's FDv2 polling endpoint. Use this method to provide a
|
|
120
|
+
# custom requester implementation for testing or non-standard environments.
|
|
121
|
+
#
|
|
122
|
+
# @param requester [Requester] A custom requester that implements the
|
|
123
|
+
# {Requester} interface
|
|
124
|
+
# @return [PollingDataSourceBuilder] self for chaining
|
|
125
|
+
#
|
|
126
|
+
# @see Requester
|
|
127
|
+
#
|
|
128
|
+
def requester(requester)
|
|
129
|
+
@requester = requester
|
|
130
|
+
self
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
#
|
|
134
|
+
# Builds the polling data source with the configured parameters.
|
|
135
|
+
#
|
|
136
|
+
# This method is called internally by the SDK. You do not need to call it
|
|
137
|
+
# directly; instead, pass the builder to {ConfigBuilder#initializers} or
|
|
138
|
+
# {ConfigBuilder#synchronizers}.
|
|
139
|
+
#
|
|
140
|
+
# @param sdk_key [String] The SDK key
|
|
141
|
+
# @param config [LaunchDarkly::Config] The SDK configuration
|
|
142
|
+
# @return [LaunchDarkly::Impl::DataSystem::PollingDataSource]
|
|
143
|
+
#
|
|
144
|
+
def build(sdk_key, config)
|
|
145
|
+
http_opts = build_http_config
|
|
146
|
+
requester = @requester || LaunchDarkly::Impl::DataSystem::HTTPPollingRequester.new(sdk_key, http_opts, config)
|
|
147
|
+
LaunchDarkly::Impl::DataSystem::PollingDataSource.new(@poll_interval || DEFAULT_POLL_INTERVAL, requester, config.logger)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
#
|
|
152
|
+
# Builder for a polling data source that communicates with LaunchDarkly's
|
|
153
|
+
# FDv1 (Flag Delivery v1) polling endpoint.
|
|
154
|
+
#
|
|
155
|
+
# This builder is typically used with {ConfigBuilder#fdv1_compatible_synchronizer}
|
|
156
|
+
# to provide a fallback when the server signals that the environment should
|
|
157
|
+
# revert to the FDv1 protocol.
|
|
158
|
+
#
|
|
159
|
+
# Most users will not need to interact with this builder directly, as the
|
|
160
|
+
# predefined strategies ({DataSystem.default}, {DataSystem.streaming},
|
|
161
|
+
# {DataSystem.polling}) already configure an appropriate FDv1 fallback.
|
|
162
|
+
#
|
|
163
|
+
# @see DataSystem.fdv1_fallback_ds_builder
|
|
164
|
+
#
|
|
165
|
+
class FDv1PollingDataSourceBuilder
|
|
166
|
+
include LaunchDarkly::DataSystem::DataSourceBuilderCommon
|
|
167
|
+
|
|
168
|
+
# @return [String] The default base URI for FDv1 polling requests
|
|
169
|
+
DEFAULT_BASE_URI = "https://sdk.launchdarkly.com"
|
|
170
|
+
|
|
171
|
+
# @return [Float] The default polling interval in seconds
|
|
172
|
+
DEFAULT_POLL_INTERVAL = 30
|
|
173
|
+
|
|
174
|
+
def initialize
|
|
175
|
+
@requester = nil
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
#
|
|
179
|
+
# Sets the polling interval in seconds.
|
|
180
|
+
#
|
|
181
|
+
# This controls how frequently the SDK polls LaunchDarkly for updates.
|
|
182
|
+
# The default is {DEFAULT_POLL_INTERVAL} seconds.
|
|
183
|
+
#
|
|
184
|
+
# @param secs [Float] Polling interval in seconds
|
|
185
|
+
# @return [FDv1PollingDataSourceBuilder] self for chaining
|
|
186
|
+
#
|
|
187
|
+
def poll_interval(secs)
|
|
188
|
+
@poll_interval = secs
|
|
189
|
+
self
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
#
|
|
193
|
+
# Sets a custom {Requester} for this polling data source.
|
|
194
|
+
#
|
|
195
|
+
# By default, the builder uses an HTTP requester that communicates with
|
|
196
|
+
# LaunchDarkly's FDv1 polling endpoint. Use this method to provide a
|
|
197
|
+
# custom requester implementation.
|
|
198
|
+
#
|
|
199
|
+
# @param requester [Requester] A custom requester that implements the
|
|
200
|
+
# {Requester} interface
|
|
201
|
+
# @return [FDv1PollingDataSourceBuilder] self for chaining
|
|
202
|
+
#
|
|
203
|
+
# @see Requester
|
|
204
|
+
#
|
|
205
|
+
def requester(requester)
|
|
206
|
+
@requester = requester
|
|
207
|
+
self
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
#
|
|
211
|
+
# Builds the FDv1 polling data source with the configured parameters.
|
|
212
|
+
#
|
|
213
|
+
# This method is called internally by the SDK. You do not need to call it
|
|
214
|
+
# directly; instead, pass the builder to {ConfigBuilder#fdv1_compatible_synchronizer}.
|
|
215
|
+
#
|
|
216
|
+
# @param sdk_key [String] The SDK key
|
|
217
|
+
# @param config [LaunchDarkly::Config] The SDK configuration
|
|
218
|
+
# @return [LaunchDarkly::Impl::DataSystem::PollingDataSource]
|
|
219
|
+
#
|
|
220
|
+
def build(sdk_key, config)
|
|
221
|
+
http_opts = build_http_config
|
|
222
|
+
requester = @requester || LaunchDarkly::Impl::DataSystem::HTTPFDv1PollingRequester.new(sdk_key, http_opts, config)
|
|
223
|
+
LaunchDarkly::Impl::DataSystem::PollingDataSource.new(@poll_interval || DEFAULT_POLL_INTERVAL, requester, config.logger)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ldclient-rb/data_system/data_source_builder_common"
|
|
4
|
+
|
|
5
|
+
module LaunchDarkly
|
|
6
|
+
module DataSystem
|
|
7
|
+
#
|
|
8
|
+
# Builder for a streaming data source that uses Server-Sent Events (SSE)
|
|
9
|
+
# to receive real-time updates from LaunchDarkly's Flag Delivery services.
|
|
10
|
+
#
|
|
11
|
+
# This builder can be used with {ConfigBuilder#synchronizers} to create
|
|
12
|
+
# custom data system configurations. Streaming provides the lowest latency
|
|
13
|
+
# for flag updates compared to polling.
|
|
14
|
+
#
|
|
15
|
+
# == Example
|
|
16
|
+
#
|
|
17
|
+
# streaming = LaunchDarkly::DataSystem.streaming_ds_builder
|
|
18
|
+
# .initial_reconnect_delay(2)
|
|
19
|
+
# .base_uri("https://custom-stream.example.com")
|
|
20
|
+
#
|
|
21
|
+
# data_system = LaunchDarkly::DataSystem.custom
|
|
22
|
+
# .synchronizers([streaming])
|
|
23
|
+
#
|
|
24
|
+
# @see DataSystem.streaming_ds_builder
|
|
25
|
+
#
|
|
26
|
+
class StreamingDataSourceBuilder
|
|
27
|
+
include LaunchDarkly::DataSystem::DataSourceBuilderCommon
|
|
28
|
+
|
|
29
|
+
# @return [String] The default base URI for streaming connections
|
|
30
|
+
DEFAULT_BASE_URI = "https://stream.launchdarkly.com"
|
|
31
|
+
|
|
32
|
+
# @return [Float] The default initial reconnect delay in seconds
|
|
33
|
+
DEFAULT_INITIAL_RECONNECT_DELAY = 1
|
|
34
|
+
|
|
35
|
+
def initialize
|
|
36
|
+
# No initialization needed - defaults applied in build via nil-check
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# Sets the initial delay before reconnecting after a stream connection error.
|
|
41
|
+
#
|
|
42
|
+
# The SDK uses an exponential backoff strategy starting from this delay.
|
|
43
|
+
# The default is {DEFAULT_INITIAL_RECONNECT_DELAY} second.
|
|
44
|
+
#
|
|
45
|
+
# @param delay [Float] Delay in seconds
|
|
46
|
+
# @return [StreamingDataSourceBuilder] self for chaining
|
|
47
|
+
#
|
|
48
|
+
def initial_reconnect_delay(delay)
|
|
49
|
+
@initial_reconnect_delay = delay
|
|
50
|
+
self
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
#
|
|
54
|
+
# Builds the streaming data source with the configured parameters.
|
|
55
|
+
#
|
|
56
|
+
# This method is called internally by the SDK. You do not need to call it
|
|
57
|
+
# directly; instead, pass the builder to {ConfigBuilder#synchronizers}.
|
|
58
|
+
#
|
|
59
|
+
# @param sdk_key [String] The SDK key
|
|
60
|
+
# @param config [LaunchDarkly::Config] The SDK configuration
|
|
61
|
+
# @return [LaunchDarkly::Impl::DataSystem::StreamingDataSource]
|
|
62
|
+
#
|
|
63
|
+
def build(sdk_key, config)
|
|
64
|
+
http_opts = build_http_config
|
|
65
|
+
LaunchDarkly::Impl::DataSystem::StreamingDataSource.new(
|
|
66
|
+
sdk_key, http_opts,
|
|
67
|
+
@initial_reconnect_delay || DEFAULT_INITIAL_RECONNECT_DELAY,
|
|
68
|
+
config
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -4,100 +4,66 @@ require 'ldclient-rb/interfaces/data_system'
|
|
|
4
4
|
require 'ldclient-rb/config'
|
|
5
5
|
require 'ldclient-rb/impl/data_system/polling'
|
|
6
6
|
require 'ldclient-rb/impl/data_system/streaming'
|
|
7
|
+
require 'ldclient-rb/data_system/config_builder'
|
|
8
|
+
require 'ldclient-rb/data_system/polling_data_source_builder'
|
|
9
|
+
require 'ldclient-rb/data_system/streaming_data_source_builder'
|
|
7
10
|
|
|
8
11
|
module LaunchDarkly
|
|
9
12
|
#
|
|
10
13
|
# Configuration for LaunchDarkly's data acquisition strategy.
|
|
11
14
|
#
|
|
12
|
-
# This module provides factory methods for creating data system configurations
|
|
15
|
+
# This module provides factory methods for creating data system configurations,
|
|
16
|
+
# as well as builder classes for constructing individual data sources (polling
|
|
17
|
+
# and streaming).
|
|
18
|
+
#
|
|
19
|
+
# == Quick Start
|
|
20
|
+
#
|
|
21
|
+
# For most users, the predefined strategies are sufficient:
|
|
22
|
+
#
|
|
23
|
+
# # Use the default strategy (recommended)
|
|
24
|
+
# config = LaunchDarkly::Config.new(
|
|
25
|
+
# data_system: LaunchDarkly::DataSystem.default
|
|
26
|
+
# )
|
|
27
|
+
#
|
|
28
|
+
# # Use streaming only
|
|
29
|
+
# config = LaunchDarkly::Config.new(
|
|
30
|
+
# data_system: LaunchDarkly::DataSystem.streaming
|
|
31
|
+
# )
|
|
32
|
+
#
|
|
33
|
+
# # Use polling only
|
|
34
|
+
# config = LaunchDarkly::Config.new(
|
|
35
|
+
# data_system: LaunchDarkly::DataSystem.polling
|
|
36
|
+
# )
|
|
37
|
+
#
|
|
38
|
+
# == Custom Configurations
|
|
39
|
+
#
|
|
40
|
+
# For advanced use cases, you can build custom configurations using the
|
|
41
|
+
# data source builders:
|
|
42
|
+
#
|
|
43
|
+
# polling = LaunchDarkly::DataSystem.polling_ds_builder
|
|
44
|
+
# .poll_interval(60)
|
|
45
|
+
# .base_uri("https://custom-polling.example.com")
|
|
46
|
+
#
|
|
47
|
+
# streaming = LaunchDarkly::DataSystem.streaming_ds_builder
|
|
48
|
+
# .initial_reconnect_delay(2)
|
|
49
|
+
# .base_uri("https://custom-streaming.example.com")
|
|
50
|
+
#
|
|
51
|
+
# data_system = LaunchDarkly::DataSystem.custom
|
|
52
|
+
# .initializers([polling])
|
|
53
|
+
# .synchronizers([streaming, polling])
|
|
54
|
+
#
|
|
55
|
+
# config = LaunchDarkly::Config.new(data_system: data_system)
|
|
13
56
|
#
|
|
14
57
|
module DataSystem
|
|
15
|
-
#
|
|
16
|
-
# Builder for the data system configuration.
|
|
17
|
-
#
|
|
18
|
-
class ConfigBuilder
|
|
19
|
-
def initialize
|
|
20
|
-
@initializers = nil
|
|
21
|
-
@synchronizers = nil
|
|
22
|
-
@fdv1_fallback_synchronizer = nil
|
|
23
|
-
@data_store_mode = LaunchDarkly::Interfaces::DataSystem::DataStoreMode::READ_ONLY
|
|
24
|
-
@data_store = nil
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
#
|
|
28
|
-
# Sets the initializers for the data system.
|
|
29
|
-
#
|
|
30
|
-
# @param initializers [Array<#build(String, Config)>]
|
|
31
|
-
# Array of builders that respond to build(sdk_key, config) and return an Initializer
|
|
32
|
-
# @return [ConfigBuilder] self for chaining
|
|
33
|
-
#
|
|
34
|
-
def initializers(initializers)
|
|
35
|
-
@initializers = initializers
|
|
36
|
-
self
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
#
|
|
40
|
-
# Sets the synchronizers for the data system.
|
|
41
|
-
#
|
|
42
|
-
# @param synchronizers [Array<#build(String, Config)>]
|
|
43
|
-
# Array of builders that respond to build(sdk_key, config) and return a Synchronizer
|
|
44
|
-
# @return [ConfigBuilder] self for chaining
|
|
45
|
-
#
|
|
46
|
-
def synchronizers(synchronizers)
|
|
47
|
-
@synchronizers = synchronizers
|
|
48
|
-
self
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
#
|
|
52
|
-
# Configures the SDK with a fallback synchronizer that is compatible with
|
|
53
|
-
# the Flag Delivery v1 API.
|
|
54
|
-
#
|
|
55
|
-
# @param fallback [#build(String, Config)] Builder that responds to build(sdk_key, config) and returns the fallback Synchronizer
|
|
56
|
-
# @return [ConfigBuilder] self for chaining
|
|
57
|
-
#
|
|
58
|
-
def fdv1_compatible_synchronizer(fallback)
|
|
59
|
-
@fdv1_fallback_synchronizer = fallback
|
|
60
|
-
self
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
#
|
|
64
|
-
# Sets the data store configuration for the data system.
|
|
65
|
-
#
|
|
66
|
-
# @param data_store [LaunchDarkly::Interfaces::FeatureStore] The data store
|
|
67
|
-
# @param store_mode [Symbol] The store mode
|
|
68
|
-
# @return [ConfigBuilder] self for chaining
|
|
69
|
-
#
|
|
70
|
-
def data_store(data_store, store_mode)
|
|
71
|
-
@data_store = data_store
|
|
72
|
-
@data_store_mode = store_mode
|
|
73
|
-
self
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
#
|
|
77
|
-
# Builds the data system configuration.
|
|
78
|
-
#
|
|
79
|
-
# @return [DataSystemConfig]
|
|
80
|
-
#
|
|
81
|
-
def build
|
|
82
|
-
DataSystemConfig.new(
|
|
83
|
-
initializers: @initializers,
|
|
84
|
-
synchronizers: @synchronizers,
|
|
85
|
-
data_store_mode: @data_store_mode,
|
|
86
|
-
data_store: @data_store,
|
|
87
|
-
fdv1_fallback_synchronizer: @fdv1_fallback_synchronizer
|
|
88
|
-
)
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
58
|
#
|
|
93
59
|
# Returns a builder for creating a polling data source.
|
|
94
60
|
# This is a building block that can be used with {ConfigBuilder#initializers}
|
|
95
61
|
# or {ConfigBuilder#synchronizers} to create custom data system configurations.
|
|
96
62
|
#
|
|
97
|
-
# @return [
|
|
63
|
+
# @return [PollingDataSourceBuilder]
|
|
98
64
|
#
|
|
99
65
|
def self.polling_ds_builder
|
|
100
|
-
|
|
66
|
+
PollingDataSourceBuilder.new
|
|
101
67
|
end
|
|
102
68
|
|
|
103
69
|
#
|
|
@@ -105,10 +71,10 @@ module LaunchDarkly
|
|
|
105
71
|
# This is a building block that can be used with {ConfigBuilder#fdv1_compatible_synchronizer}
|
|
106
72
|
# to provide FDv1 compatibility in custom data system configurations.
|
|
107
73
|
#
|
|
108
|
-
# @return [
|
|
74
|
+
# @return [FDv1PollingDataSourceBuilder]
|
|
109
75
|
#
|
|
110
76
|
def self.fdv1_fallback_ds_builder
|
|
111
|
-
|
|
77
|
+
FDv1PollingDataSourceBuilder.new
|
|
112
78
|
end
|
|
113
79
|
|
|
114
80
|
#
|
|
@@ -116,10 +82,10 @@ module LaunchDarkly
|
|
|
116
82
|
# This is a building block that can be used with {ConfigBuilder#synchronizers}
|
|
117
83
|
# to create custom data system configurations.
|
|
118
84
|
#
|
|
119
|
-
# @return [
|
|
85
|
+
# @return [StreamingDataSourceBuilder]
|
|
120
86
|
#
|
|
121
87
|
def self.streaming_ds_builder
|
|
122
|
-
|
|
88
|
+
StreamingDataSourceBuilder.new
|
|
123
89
|
end
|
|
124
90
|
|
|
125
91
|
#
|
|
@@ -224,4 +190,3 @@ module LaunchDarkly
|
|
|
224
190
|
end
|
|
225
191
|
end
|
|
226
192
|
end
|
|
227
|
-
|
|
@@ -178,7 +178,7 @@ module LaunchDarkly
|
|
|
178
178
|
private def send_change_events(affected_items)
|
|
179
179
|
affected_items.each do |item|
|
|
180
180
|
if item[:kind] == Impl::DataStore::FEATURES
|
|
181
|
-
@flag_change_broadcaster.broadcast(LaunchDarkly::Interfaces::FlagChange.new(item[:key]))
|
|
181
|
+
@flag_change_broadcaster.broadcast(LaunchDarkly::Interfaces::FlagChange.new(item[:key].to_s))
|
|
182
182
|
end
|
|
183
183
|
end
|
|
184
184
|
end
|
|
@@ -58,7 +58,7 @@ module LaunchDarkly
|
|
|
58
58
|
#
|
|
59
59
|
# Initializes the store with a full set of data, replacing any existing data.
|
|
60
60
|
#
|
|
61
|
-
# @param collections [Hash<LaunchDarkly::Impl::DataStore::DataKind, Hash<
|
|
61
|
+
# @param collections [Hash<LaunchDarkly::Impl::DataStore::DataKind, Hash<Symbol, Hash>>] Hash of data kinds to collections of items
|
|
62
62
|
# @return [Boolean] true if successful, false otherwise
|
|
63
63
|
#
|
|
64
64
|
def set_basis(collections)
|
|
@@ -80,7 +80,7 @@ module LaunchDarkly
|
|
|
80
80
|
#
|
|
81
81
|
# Applies a delta update to the store.
|
|
82
82
|
#
|
|
83
|
-
# @param collections [Hash<LaunchDarkly::Impl::DataStore::DataKind, Hash<
|
|
83
|
+
# @param collections [Hash<LaunchDarkly::Impl::DataStore::DataKind, Hash<Symbol, Hash>>] Hash of data kinds to collections with updates
|
|
84
84
|
# @return [Boolean] true if successful, false otherwise
|
|
85
85
|
#
|
|
86
86
|
def apply_delta(collections)
|
|
@@ -105,7 +105,7 @@ module LaunchDarkly
|
|
|
105
105
|
#
|
|
106
106
|
# Decodes a collection of items.
|
|
107
107
|
#
|
|
108
|
-
# @param collections [Hash<LaunchDarkly::Impl::DataStore::DataKind, Hash<
|
|
108
|
+
# @param collections [Hash<LaunchDarkly::Impl::DataStore::DataKind, Hash<Symbol, Hash>>] Hash of data kinds to collections
|
|
109
109
|
# @return [Hash<LaunchDarkly::Impl::DataStore::DataKind, Hash<Symbol, Hash>>, nil] Decoded collection with symbol keys, or nil on error
|
|
110
110
|
#
|
|
111
111
|
private def decode_collection(collections)
|
|
@@ -193,7 +193,7 @@ module LaunchDarkly
|
|
|
193
193
|
#
|
|
194
194
|
# Set the basis of the store. Any existing data is discarded.
|
|
195
195
|
#
|
|
196
|
-
# @param collections [Hash{Object => Hash{
|
|
196
|
+
# @param collections [Hash{Object => Hash{Symbol => Hash}}] Hash of data kinds to collections of items
|
|
197
197
|
# @param selector [LaunchDarkly::Interfaces::DataSystem::Selector, nil] The selector
|
|
198
198
|
# @param persist [Boolean] Whether to persist the data
|
|
199
199
|
# @return [void]
|
|
@@ -234,7 +234,7 @@ module LaunchDarkly
|
|
|
234
234
|
#
|
|
235
235
|
# Apply a delta update to the store.
|
|
236
236
|
#
|
|
237
|
-
# @param collections [Hash{Object => Hash{
|
|
237
|
+
# @param collections [Hash{Object => Hash{Symbol => Hash}}] Hash of data kinds to collections with updates
|
|
238
238
|
# @param selector [LaunchDarkly::Interfaces::DataSystem::Selector, nil] The selector
|
|
239
239
|
# @param persist [Boolean] Whether to persist the changes
|
|
240
240
|
# @return [void]
|
|
@@ -328,7 +328,7 @@ module LaunchDarkly
|
|
|
328
328
|
private def send_change_events(affected_items)
|
|
329
329
|
affected_items.each do |item|
|
|
330
330
|
if item[:kind] == FEATURES
|
|
331
|
-
@flag_change_broadcaster.broadcast(LaunchDarkly::Interfaces::FlagChange.new(item[:key]))
|
|
331
|
+
@flag_change_broadcaster.broadcast(LaunchDarkly::Interfaces::FlagChange.new(item[:key].to_s))
|
|
332
332
|
end
|
|
333
333
|
end
|
|
334
334
|
end
|
|
@@ -336,8 +336,8 @@ module LaunchDarkly
|
|
|
336
336
|
#
|
|
337
337
|
# Compute which items changed between old and new data sets.
|
|
338
338
|
#
|
|
339
|
-
# @param old_data [Hash{DataKind => Hash{
|
|
340
|
-
# @param new_data [Hash{DataKind => Hash{
|
|
339
|
+
# @param old_data [Hash{DataKind => Hash{Symbol => Hash}}] Old data hash
|
|
340
|
+
# @param new_data [Hash{DataKind => Hash{Symbol => Hash}}] New data hash
|
|
341
341
|
# @return [Set<Hash>] Set of {kind:, key:} hashes
|
|
342
342
|
#
|
|
343
343
|
private def compute_changed_items_for_full_data_set(old_data, new_data)
|
|
@@ -4,7 +4,7 @@ require "ldclient-rb/interfaces"
|
|
|
4
4
|
require "ldclient-rb/interfaces/data_system"
|
|
5
5
|
require "ldclient-rb/impl/data_system"
|
|
6
6
|
require "ldclient-rb/impl/data_system/protocolv2"
|
|
7
|
-
require "ldclient-rb/
|
|
7
|
+
require "ldclient-rb/data_system/polling_data_source_builder"
|
|
8
8
|
require "ldclient-rb/impl/data_source/requestor"
|
|
9
9
|
require "ldclient-rb/impl/util"
|
|
10
10
|
require "concurrent"
|
|
@@ -21,32 +21,6 @@ module LaunchDarkly
|
|
|
21
21
|
LD_ENVID_HEADER = "X-LD-EnvID"
|
|
22
22
|
LD_FD_FALLBACK_HEADER = "X-LD-FD-Fallback"
|
|
23
23
|
|
|
24
|
-
#
|
|
25
|
-
# Requester protocol for polling data source
|
|
26
|
-
#
|
|
27
|
-
module Requester
|
|
28
|
-
#
|
|
29
|
-
# Fetches the data for the given selector.
|
|
30
|
-
# Returns a Result containing a tuple of [ChangeSet, headers],
|
|
31
|
-
# or an error if the data could not be retrieved.
|
|
32
|
-
#
|
|
33
|
-
# @param selector [LaunchDarkly::Interfaces::DataSystem::Selector, nil]
|
|
34
|
-
# @return [Result]
|
|
35
|
-
#
|
|
36
|
-
def fetch(selector)
|
|
37
|
-
raise NotImplementedError
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
#
|
|
41
|
-
# Closes any persistent connections and releases resources.
|
|
42
|
-
# This method should be called when the requester is no longer needed.
|
|
43
|
-
# Implementations should handle being called multiple times gracefully.
|
|
44
|
-
#
|
|
45
|
-
def stop
|
|
46
|
-
# Optional - implementations may override if they need cleanup
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
24
|
#
|
|
51
25
|
# PollingDataSource is a data source that can retrieve information from
|
|
52
26
|
# LaunchDarkly either as an Initializer or as a Synchronizer.
|
|
@@ -246,7 +220,7 @@ module LaunchDarkly
|
|
|
246
220
|
# requests to the FDv2 polling endpoint.
|
|
247
221
|
#
|
|
248
222
|
class HTTPPollingRequester
|
|
249
|
-
include Requester
|
|
223
|
+
include LaunchDarkly::DataSystem::Requester
|
|
250
224
|
|
|
251
225
|
#
|
|
252
226
|
# @param sdk_key [String]
|
|
@@ -338,7 +312,7 @@ module LaunchDarkly
|
|
|
338
312
|
# requests to the FDv1 polling endpoint.
|
|
339
313
|
#
|
|
340
314
|
class HTTPFDv1PollingRequester
|
|
341
|
-
include Requester
|
|
315
|
+
include LaunchDarkly::DataSystem::Requester
|
|
342
316
|
|
|
343
317
|
#
|
|
344
318
|
# @param sdk_key [String]
|
|
@@ -526,103 +500,6 @@ module LaunchDarkly
|
|
|
526
500
|
LaunchDarkly::Result.success(builder.finish(selector))
|
|
527
501
|
end
|
|
528
502
|
|
|
529
|
-
#
|
|
530
|
-
# Builder for a PollingDataSource.
|
|
531
|
-
#
|
|
532
|
-
class PollingDataSourceBuilder
|
|
533
|
-
include DataSourceBuilderCommon
|
|
534
|
-
|
|
535
|
-
DEFAULT_BASE_URI = "https://sdk.launchdarkly.com"
|
|
536
|
-
DEFAULT_POLL_INTERVAL = 30
|
|
537
|
-
|
|
538
|
-
def initialize
|
|
539
|
-
@requester = nil
|
|
540
|
-
end
|
|
541
|
-
|
|
542
|
-
#
|
|
543
|
-
# Sets the polling interval in seconds.
|
|
544
|
-
#
|
|
545
|
-
# @param secs [Float] Polling interval in seconds
|
|
546
|
-
# @return [PollingDataSourceBuilder]
|
|
547
|
-
#
|
|
548
|
-
def poll_interval(secs)
|
|
549
|
-
@poll_interval = secs
|
|
550
|
-
self
|
|
551
|
-
end
|
|
552
|
-
|
|
553
|
-
#
|
|
554
|
-
# Sets a custom Requester for the PollingDataSource.
|
|
555
|
-
#
|
|
556
|
-
# @param requester [Requester]
|
|
557
|
-
# @return [PollingDataSourceBuilder]
|
|
558
|
-
#
|
|
559
|
-
def requester(requester)
|
|
560
|
-
@requester = requester
|
|
561
|
-
self
|
|
562
|
-
end
|
|
563
|
-
|
|
564
|
-
#
|
|
565
|
-
# Builds the PollingDataSource with the configured parameters.
|
|
566
|
-
#
|
|
567
|
-
# @param sdk_key [String]
|
|
568
|
-
# @param config [LaunchDarkly::Config]
|
|
569
|
-
# @return [PollingDataSource]
|
|
570
|
-
#
|
|
571
|
-
def build(sdk_key, config)
|
|
572
|
-
http_opts = build_http_config
|
|
573
|
-
requester = @requester || HTTPPollingRequester.new(sdk_key, http_opts, config)
|
|
574
|
-
PollingDataSource.new(@poll_interval || DEFAULT_POLL_INTERVAL, requester, config.logger)
|
|
575
|
-
end
|
|
576
|
-
end
|
|
577
|
-
|
|
578
|
-
#
|
|
579
|
-
# Builder for an FDv1 PollingDataSource.
|
|
580
|
-
#
|
|
581
|
-
class FDv1PollingDataSourceBuilder
|
|
582
|
-
include DataSourceBuilderCommon
|
|
583
|
-
|
|
584
|
-
DEFAULT_BASE_URI = "https://sdk.launchdarkly.com"
|
|
585
|
-
DEFAULT_POLL_INTERVAL = 30
|
|
586
|
-
|
|
587
|
-
def initialize
|
|
588
|
-
@requester = nil
|
|
589
|
-
end
|
|
590
|
-
|
|
591
|
-
#
|
|
592
|
-
# Sets the polling interval in seconds.
|
|
593
|
-
#
|
|
594
|
-
# @param secs [Float] Polling interval in seconds
|
|
595
|
-
# @return [FDv1PollingDataSourceBuilder]
|
|
596
|
-
#
|
|
597
|
-
def poll_interval(secs)
|
|
598
|
-
@poll_interval = secs
|
|
599
|
-
self
|
|
600
|
-
end
|
|
601
|
-
|
|
602
|
-
#
|
|
603
|
-
# Sets a custom Requester for the PollingDataSource.
|
|
604
|
-
#
|
|
605
|
-
# @param requester [Requester]
|
|
606
|
-
# @return [FDv1PollingDataSourceBuilder]
|
|
607
|
-
#
|
|
608
|
-
def requester(requester)
|
|
609
|
-
@requester = requester
|
|
610
|
-
self
|
|
611
|
-
end
|
|
612
|
-
|
|
613
|
-
#
|
|
614
|
-
# Builds the PollingDataSource with the configured parameters.
|
|
615
|
-
#
|
|
616
|
-
# @param sdk_key [String]
|
|
617
|
-
# @param config [LaunchDarkly::Config]
|
|
618
|
-
# @return [PollingDataSource]
|
|
619
|
-
#
|
|
620
|
-
def build(sdk_key, config)
|
|
621
|
-
http_opts = build_http_config
|
|
622
|
-
requester = @requester || HTTPFDv1PollingRequester.new(sdk_key, http_opts, config)
|
|
623
|
-
PollingDataSource.new(@poll_interval || DEFAULT_POLL_INTERVAL, requester, config.logger)
|
|
624
|
-
end
|
|
625
|
-
end
|
|
626
503
|
end
|
|
627
504
|
end
|
|
628
505
|
end
|
|
@@ -5,7 +5,7 @@ require "ldclient-rb/interfaces/data_system"
|
|
|
5
5
|
require "ldclient-rb/impl/data_system"
|
|
6
6
|
require "ldclient-rb/impl/data_system/protocolv2"
|
|
7
7
|
require "ldclient-rb/impl/data_system/polling" # For shared constants
|
|
8
|
-
require "ldclient-rb/
|
|
8
|
+
require "ldclient-rb/data_system/streaming_data_source_builder"
|
|
9
9
|
require "ldclient-rb/impl/util"
|
|
10
10
|
require "concurrent"
|
|
11
11
|
require "json"
|
|
@@ -356,46 +356,6 @@ module LaunchDarkly
|
|
|
356
356
|
end
|
|
357
357
|
end
|
|
358
358
|
|
|
359
|
-
#
|
|
360
|
-
# Builder for a StreamingDataSource.
|
|
361
|
-
#
|
|
362
|
-
class StreamingDataSourceBuilder
|
|
363
|
-
include DataSourceBuilderCommon
|
|
364
|
-
|
|
365
|
-
DEFAULT_BASE_URI = "https://stream.launchdarkly.com"
|
|
366
|
-
DEFAULT_INITIAL_RECONNECT_DELAY = 1
|
|
367
|
-
|
|
368
|
-
def initialize
|
|
369
|
-
# No initialization needed - defaults applied in build via nil-check
|
|
370
|
-
end
|
|
371
|
-
|
|
372
|
-
#
|
|
373
|
-
# Sets the initial delay before reconnecting after an error.
|
|
374
|
-
#
|
|
375
|
-
# @param delay [Float] Delay in seconds
|
|
376
|
-
# @return [StreamingDataSourceBuilder]
|
|
377
|
-
#
|
|
378
|
-
def initial_reconnect_delay(delay)
|
|
379
|
-
@initial_reconnect_delay = delay
|
|
380
|
-
self
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
#
|
|
384
|
-
# Builds the StreamingDataSource with the configured parameters.
|
|
385
|
-
#
|
|
386
|
-
# @param sdk_key [String]
|
|
387
|
-
# @param config [LaunchDarkly::Config]
|
|
388
|
-
# @return [StreamingDataSource]
|
|
389
|
-
#
|
|
390
|
-
def build(sdk_key, config)
|
|
391
|
-
http_opts = build_http_config
|
|
392
|
-
StreamingDataSource.new(
|
|
393
|
-
sdk_key, http_opts,
|
|
394
|
-
@initial_reconnect_delay || DEFAULT_INITIAL_RECONNECT_DELAY,
|
|
395
|
-
config
|
|
396
|
-
)
|
|
397
|
-
end
|
|
398
|
-
end
|
|
399
359
|
end
|
|
400
360
|
end
|
|
401
361
|
end
|
|
@@ -13,7 +13,7 @@ module LaunchDarkly
|
|
|
13
13
|
# Updates the dependency graph when an item has changed.
|
|
14
14
|
#
|
|
15
15
|
# @param from_kind [Object] the changed item's kind
|
|
16
|
-
# @param from_key [
|
|
16
|
+
# @param from_key [Symbol] the changed item's key
|
|
17
17
|
# @param from_item [Object] the changed item (can be a Hash, model object, or nil)
|
|
18
18
|
#
|
|
19
19
|
def update_dependencies_from(from_kind, from_key, from_item)
|
|
@@ -26,7 +26,7 @@ module LaunchDarkly
|
|
|
26
26
|
# An adapter which turns a normal flag change listener into a flag value change listener.
|
|
27
27
|
#
|
|
28
28
|
class FlagValueChangeAdapter
|
|
29
|
-
# @param [
|
|
29
|
+
# @param [String] flag_key
|
|
30
30
|
# @param [LaunchDarkly::LDContext] context
|
|
31
31
|
# @param [#update] listener
|
|
32
32
|
# @param [#call] eval_fn
|
|
@@ -66,7 +66,7 @@ module LaunchDarkly
|
|
|
66
66
|
# The returned listener represents the subscription that was created by this method
|
|
67
67
|
# call; to unsubscribe, pass that object (not your listener) to {#remove_listener}.
|
|
68
68
|
#
|
|
69
|
-
# @param key [
|
|
69
|
+
# @param key [String]
|
|
70
70
|
# @param context [LaunchDarkly::LDContext]
|
|
71
71
|
# @param listener [#update]
|
|
72
72
|
#
|
|
@@ -79,7 +79,7 @@ module LaunchDarkly
|
|
|
79
79
|
class FlagChange
|
|
80
80
|
attr_accessor :key
|
|
81
81
|
|
|
82
|
-
# @param [
|
|
82
|
+
# @param key [String]
|
|
83
83
|
def initialize(key)
|
|
84
84
|
@key = key
|
|
85
85
|
end
|
|
@@ -93,9 +93,9 @@ module LaunchDarkly
|
|
|
93
93
|
attr_accessor :old_value
|
|
94
94
|
attr_accessor :new_value
|
|
95
95
|
|
|
96
|
-
# @param [
|
|
97
|
-
# @param [Object]
|
|
98
|
-
# @param [Object]
|
|
96
|
+
# @param key [String]
|
|
97
|
+
# @param old_value [Object]
|
|
98
|
+
# @param new_value [Object]
|
|
99
99
|
def initialize(key, old_value, new_value)
|
|
100
100
|
@key = key
|
|
101
101
|
@old_value = old_value
|
data/lib/ldclient-rb/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: launchdarkly-server-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.12.
|
|
4
|
+
version: 8.12.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- LaunchDarkly
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-03-
|
|
11
|
+
date: 2026-03-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: aws-sdk-dynamodb
|
|
@@ -370,6 +370,10 @@ files:
|
|
|
370
370
|
- lib/ldclient-rb/config.rb
|
|
371
371
|
- lib/ldclient-rb/context.rb
|
|
372
372
|
- lib/ldclient-rb/data_system.rb
|
|
373
|
+
- lib/ldclient-rb/data_system/config_builder.rb
|
|
374
|
+
- lib/ldclient-rb/data_system/data_source_builder_common.rb
|
|
375
|
+
- lib/ldclient-rb/data_system/polling_data_source_builder.rb
|
|
376
|
+
- lib/ldclient-rb/data_system/streaming_data_source_builder.rb
|
|
373
377
|
- lib/ldclient-rb/evaluation_detail.rb
|
|
374
378
|
- lib/ldclient-rb/events.rb
|
|
375
379
|
- lib/ldclient-rb/flags_state.rb
|
|
@@ -392,7 +396,6 @@ files:
|
|
|
392
396
|
- lib/ldclient-rb/impl/data_store/status_provider.rb
|
|
393
397
|
- lib/ldclient-rb/impl/data_store/store.rb
|
|
394
398
|
- lib/ldclient-rb/impl/data_system.rb
|
|
395
|
-
- lib/ldclient-rb/impl/data_system/data_source_builder_common.rb
|
|
396
399
|
- lib/ldclient-rb/impl/data_system/fdv1.rb
|
|
397
400
|
- lib/ldclient-rb/impl/data_system/fdv2.rb
|
|
398
401
|
- lib/ldclient-rb/impl/data_system/http_config_options.rb
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "ldclient-rb/impl/data_system/http_config_options"
|
|
4
|
-
|
|
5
|
-
module LaunchDarkly
|
|
6
|
-
module Impl
|
|
7
|
-
module DataSystem
|
|
8
|
-
#
|
|
9
|
-
# DataSourceBuilderCommon is a mixin that provides common HTTP configuration
|
|
10
|
-
# setters for data source builders (polling and streaming).
|
|
11
|
-
#
|
|
12
|
-
# Each builder that includes this module must define a DEFAULT_BASE_URI constant.
|
|
13
|
-
#
|
|
14
|
-
module DataSourceBuilderCommon
|
|
15
|
-
#
|
|
16
|
-
# Sets the base URI for HTTP requests.
|
|
17
|
-
#
|
|
18
|
-
# @param uri [String]
|
|
19
|
-
# @return [self]
|
|
20
|
-
#
|
|
21
|
-
def base_uri(uri)
|
|
22
|
-
@base_uri = uri
|
|
23
|
-
self
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
#
|
|
27
|
-
# Sets a custom socket factory for HTTP connections.
|
|
28
|
-
#
|
|
29
|
-
# @param factory [Object]
|
|
30
|
-
# @return [self]
|
|
31
|
-
#
|
|
32
|
-
def socket_factory(factory)
|
|
33
|
-
@socket_factory = factory
|
|
34
|
-
self
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
#
|
|
38
|
-
# Sets the read timeout for HTTP connections.
|
|
39
|
-
#
|
|
40
|
-
# @param timeout [Float] Timeout in seconds
|
|
41
|
-
# @return [self]
|
|
42
|
-
#
|
|
43
|
-
def read_timeout(timeout)
|
|
44
|
-
@read_timeout = timeout
|
|
45
|
-
self
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
#
|
|
49
|
-
# Sets the connect timeout for HTTP connections.
|
|
50
|
-
#
|
|
51
|
-
# @param timeout [Float] Timeout in seconds
|
|
52
|
-
# @return [self]
|
|
53
|
-
#
|
|
54
|
-
def connect_timeout(timeout)
|
|
55
|
-
@connect_timeout = timeout
|
|
56
|
-
self
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
#
|
|
60
|
-
# Builds an HttpConfigOptions instance from the current builder settings.
|
|
61
|
-
# Uses self.class::DEFAULT_BASE_URI if base_uri was not explicitly set.
|
|
62
|
-
# Read/connect timeouts default to HttpConfigOptions defaults if not set.
|
|
63
|
-
#
|
|
64
|
-
# @return [HttpConfigOptions]
|
|
65
|
-
#
|
|
66
|
-
private def build_http_config
|
|
67
|
-
HttpConfigOptions.new(
|
|
68
|
-
base_uri: (@base_uri || self.class::DEFAULT_BASE_URI).chomp("/"),
|
|
69
|
-
socket_factory: @socket_factory,
|
|
70
|
-
read_timeout: @read_timeout,
|
|
71
|
-
connect_timeout: @connect_timeout
|
|
72
|
-
)
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|