Skip to content

Commit dda586a

Browse files
committed
address feedback and add contract test
1 parent d908f5e commit dda586a

File tree

2 files changed

+304
-176
lines changed

2 files changed

+304
-176
lines changed

lib/ldclient-rb/impl/datasystem.rb

Lines changed: 113 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,121 @@
11
module LaunchDarkly
22
module Impl
3+
#
4+
# Mixin that defines the required methods of a data system implementation. The data system
5+
# is responsible for managing the SDK's data model, including storage, retrieval, and change
6+
# detection for feature flag configurations.
7+
#
8+
# This module also contains supporting classes and additional mixins for data system
9+
# implementations, such as DataAvailability, Update, and protocol-specific mixins.
10+
#
11+
# For operations that can fail, use {LaunchDarkly::Result} from util.rb.
12+
#
13+
# Application code should not need to implement this directly; it is used internally by the
14+
# SDK's data system implementations.
15+
#
16+
# @private
17+
#
318
module DataSystem
419
#
5-
# This module contains the generic interfaces used for the data system (v1 and
6-
# v2), as well as types for v1 and v2 specific protocols.
20+
# Starts the data system.
721
#
8-
# @private
22+
# This method will return immediately. The provided event will be set when the system
23+
# has reached an initial state (either permanently failed, e.g. due to bad auth, or succeeded).
924
#
25+
# @param ready_event [Concurrent::Event] Event to set when initialization is complete
26+
# @return [void]
27+
#
28+
def start(ready_event)
29+
raise NotImplementedError, "#{self.class} must implement #start"
30+
end
31+
32+
#
33+
# Halts the data system. Should be called when the client is closed to stop any long running
34+
# operations.
35+
#
36+
# @return [void]
37+
#
38+
def stop
39+
raise NotImplementedError, "#{self.class} must implement #stop"
40+
end
41+
42+
#
43+
# Returns an interface for tracking the status of the data source.
44+
#
45+
# The data source is the mechanism that the SDK uses to get feature flag configurations, such
46+
# as a streaming connection (the default) or poll requests.
47+
#
48+
# @return [LaunchDarkly::Interfaces::DataSource::StatusProvider]
49+
#
50+
def data_source_status_provider
51+
raise NotImplementedError, "#{self.class} must implement #data_source_status_provider"
52+
end
53+
54+
#
55+
# Returns an interface for tracking the status of a persistent data store.
56+
#
57+
# The provider has methods for checking whether the data store is (as far
58+
# as the SDK knows) currently operational, tracking changes in this
59+
# status, and getting cache statistics. These are only relevant for a
60+
# persistent data store; if you are using an in-memory data store, then
61+
# this method will return a stub object that provides no information.
62+
#
63+
# @return [LaunchDarkly::Interfaces::DataStore::StatusProvider]
64+
#
65+
def data_store_status_provider
66+
raise NotImplementedError, "#{self.class} must implement #data_store_status_provider"
67+
end
68+
69+
#
70+
# Returns an interface for tracking changes in feature flag configurations.
71+
#
72+
# @return [LaunchDarkly::Interfaces::FlagTracker]
73+
#
74+
def flag_tracker
75+
raise NotImplementedError, "#{self.class} must implement #flag_tracker"
76+
end
77+
78+
#
79+
# Indicates what form of data is currently available.
80+
#
81+
# @return [Symbol] One of DataAvailability constants
82+
#
83+
def data_availability
84+
raise NotImplementedError, "#{self.class} must implement #data_availability"
85+
end
86+
87+
#
88+
# Indicates the ideal form of data attainable given the current configuration.
89+
#
90+
# @return [Symbol] One of DataAvailability constants
91+
#
92+
def target_availability
93+
raise NotImplementedError, "#{self.class} must implement #target_availability"
94+
end
95+
96+
#
97+
# Returns the data store used by the data system.
98+
#
99+
# @return [Object] The read-only store
100+
#
101+
def store
102+
raise NotImplementedError, "#{self.class} must implement #store"
103+
end
104+
105+
#
106+
# Injects the flag value evaluation function used by the flag tracker to
107+
# compute FlagValueChange events. The function signature should be
108+
# (key, context) -> value.
109+
#
110+
# This method must be called after initialization to enable the flag tracker
111+
# to compute value changes for flag change listeners.
112+
#
113+
# @param eval_fn [Proc] The evaluation function
114+
# @return [void]
115+
#
116+
def set_flag_value_eval_fn(eval_fn)
117+
raise NotImplementedError, "#{self.class} must implement #set_flag_value_eval_fn"
118+
end
10119

11120
#
12121
# Represents the availability of data in the SDK.
@@ -39,116 +148,6 @@ def self.at_least?(self_level, other)
39148
end
40149
end
41150

42-
#
43-
# Mixin that defines the required methods of a data system implementation. The data system
44-
# is responsible for managing the SDK's data model, including storage, retrieval, and change
45-
# detection for feature flag configurations.
46-
#
47-
# Application code should not need to implement this directly; it is used internally by the
48-
# SDK's data system implementations.
49-
#
50-
module DataSystem
51-
#
52-
# Starts the data system.
53-
#
54-
# This method will return immediately. The system should signal when it has reached
55-
# an initial state (either permanently failed, e.g. due to bad auth, or succeeded).
56-
#
57-
# @return [void]
58-
#
59-
def start
60-
raise NotImplementedError, "#{self.class} must implement #start"
61-
end
62-
63-
#
64-
# Halts the data system. Should be called when the client is closed to stop any long running
65-
# operations.
66-
#
67-
# @return [void]
68-
#
69-
def stop
70-
raise NotImplementedError, "#{self.class} must implement #stop"
71-
end
72-
73-
#
74-
# Returns an interface for tracking the status of the data source.
75-
#
76-
# The data source is the mechanism that the SDK uses to get feature flag configurations, such
77-
# as a streaming connection (the default) or poll requests.
78-
#
79-
# @return [LaunchDarkly::Interfaces::DataSource::StatusProvider]
80-
#
81-
def data_source_status_provider
82-
raise NotImplementedError, "#{self.class} must implement #data_source_status_provider"
83-
end
84-
85-
#
86-
# Returns an interface for tracking the status of a persistent data store.
87-
#
88-
# The provider has methods for checking whether the data store is (as far
89-
# as the SDK knows) currently operational, tracking changes in this
90-
# status, and getting cache statistics. These are only relevant for a
91-
# persistent data store; if you are using an in-memory data store, then
92-
# this method will return a stub object that provides no information.
93-
#
94-
# @return [LaunchDarkly::Interfaces::DataStore::StatusProvider]
95-
#
96-
def data_store_status_provider
97-
raise NotImplementedError, "#{self.class} must implement #data_store_status_provider"
98-
end
99-
100-
#
101-
# Returns an interface for tracking changes in feature flag configurations.
102-
#
103-
# @return [LaunchDarkly::Interfaces::FlagTracker]
104-
#
105-
def flag_tracker
106-
raise NotImplementedError, "#{self.class} must implement #flag_tracker"
107-
end
108-
109-
#
110-
# Indicates what form of data is currently available.
111-
#
112-
# @return [Symbol] One of DataAvailability constants
113-
#
114-
def data_availability
115-
raise NotImplementedError, "#{self.class} must implement #data_availability"
116-
end
117-
118-
#
119-
# Indicates the ideal form of data attainable given the current configuration.
120-
#
121-
# @return [Symbol] One of DataAvailability constants
122-
#
123-
def target_availability
124-
raise NotImplementedError, "#{self.class} must implement #target_availability"
125-
end
126-
127-
#
128-
# Returns the data store used by the data system.
129-
#
130-
# @return [Object] The read-only store
131-
#
132-
def store
133-
raise NotImplementedError, "#{self.class} must implement #store"
134-
end
135-
136-
#
137-
# Injects the flag value evaluation function used by the flag tracker to
138-
# compute FlagValueChange events. The function signature should be
139-
# (key, context) -> value.
140-
#
141-
# This method must be called after initialization to enable the flag tracker
142-
# to compute value changes for flag change listeners.
143-
#
144-
# @param eval_fn [Proc] The evaluation function
145-
# @return [void]
146-
#
147-
def set_flag_value_eval_fn(eval_fn)
148-
raise NotImplementedError, "#{self.class} must implement #set_flag_value_eval_fn"
149-
end
150-
end
151-
152151
#
153152
# Mixin that defines the required methods of a diagnostic accumulator implementation.
154153
# The diagnostic accumulator is used for collecting and reporting diagnostic events
@@ -210,68 +209,6 @@ def set_diagnostic_accumulator(diagnostic_accumulator)
210209
end
211210
end
212211

213-
#
214-
# Result type for operations that can fail, containing either a successful value or an error message.
215-
#
216-
class Result
217-
# @return [Object, nil] The successful result value
218-
attr_reader :value
219-
220-
# @return [String, nil] The error message if operation failed
221-
attr_reader :error
222-
223-
# @return [Boolean] Whether the operation was successful
224-
attr_reader :success
225-
226-
#
227-
# @param value [Object, nil] The successful result value
228-
# @param error [String, nil] The error message
229-
#
230-
def initialize(value: nil, error: nil)
231-
@value = value
232-
@error = error
233-
@success = error.nil?
234-
end
235-
236-
#
237-
# Creates a successful result.
238-
#
239-
# @param value [Object] The successful result value
240-
# @return [Result]
241-
#
242-
def self.success(value)
243-
new(value: value)
244-
end
245-
246-
#
247-
# Creates a failed result.
248-
#
249-
# @param error [String] The error message
250-
# @return [Result]
251-
#
252-
def self.fail(error)
253-
new(error: error)
254-
end
255-
256-
#
257-
# Returns whether the result represents a success.
258-
#
259-
# @return [Boolean]
260-
#
261-
def success?
262-
@success
263-
end
264-
265-
#
266-
# Returns whether the result represents a failure.
267-
#
268-
# @return [Boolean]
269-
#
270-
def failure?
271-
!@success
272-
end
273-
end
274-
275212
#
276213
# Mixin that defines the required methods of an initializer implementation. An initializer
277214
# is a component capable of retrieving a single data result, such as from the LaunchDarkly
@@ -288,7 +225,7 @@ module Initializer
288225
# Fetch should retrieve the initial data set for the data source, returning
289226
# a Basis object on success, or an error message on failure.
290227
#
291-
# @return [Result] A Result containing either a Basis or an error message
228+
# @return [LaunchDarkly::Result] A Result containing either a Basis or an error message
292229
#
293230
def fetch
294231
raise NotImplementedError, "#{self.class} must implement #fetch"

0 commit comments

Comments
 (0)