ff-ruby-server-sdk 0.0.2 → 1.0.0

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.run/build.sh.run.xml +17 -0
  3. data/.run/install.sh.run.xml +17 -0
  4. data/.run/openapi.sh.run.xml +17 -0
  5. data/.run/publish.sh.run.xml +17 -0
  6. data/.run/sdk_test.rb.run.xml +3 -3
  7. data/.run/unpublish.sh.run.xml +17 -0
  8. data/CHANGELOG.md +1 -1
  9. data/Gemfile +20 -3
  10. data/README.md +155 -7
  11. data/api.yaml +736 -0
  12. data/example/example.rb +99 -3
  13. data/lib/ff/ruby/server/sdk/api/auth_service.rb +91 -0
  14. data/lib/ff/ruby/server/sdk/api/cf_client.rb +93 -0
  15. data/lib/ff/ruby/server/sdk/api/client_callback.rb +45 -0
  16. data/lib/ff/ruby/server/sdk/api/config.rb +140 -0
  17. data/lib/ff/ruby/server/sdk/api/config_builder.rb +116 -0
  18. data/lib/ff/ruby/server/sdk/api/default_cache.rb +112 -0
  19. data/lib/ff/ruby/server/sdk/api/evaluation.rb +29 -0
  20. data/lib/ff/ruby/server/sdk/api/evaluator.rb +526 -0
  21. data/lib/ff/ruby/server/sdk/api/file_map_store.rb +60 -0
  22. data/lib/ff/ruby/server/sdk/api/flag_evaluate_callback.rb +13 -0
  23. data/lib/ff/ruby/server/sdk/api/inner_client.rb +311 -0
  24. data/lib/ff/ruby/server/sdk/api/inner_client_flag_evaluate_callback.rb +30 -0
  25. data/lib/ff/ruby/server/sdk/api/inner_client_metrics_callback.rb +33 -0
  26. data/lib/ff/ruby/server/sdk/api/inner_client_repository_callback.rb +44 -0
  27. data/lib/ff/ruby/server/sdk/api/inner_client_updater.rb +63 -0
  28. data/lib/ff/ruby/server/sdk/api/metrics_callback.rb +19 -0
  29. data/lib/ff/ruby/server/sdk/api/metrics_event.rb +16 -0
  30. data/lib/ff/ruby/server/sdk/api/metrics_processor.rb +297 -0
  31. data/lib/ff/ruby/server/sdk/api/operators.rb +20 -0
  32. data/lib/ff/ruby/server/sdk/api/polling_processor.rb +164 -0
  33. data/lib/ff/ruby/server/sdk/api/repository_callback.rb +28 -0
  34. data/lib/ff/ruby/server/sdk/api/storage_repository.rb +263 -0
  35. data/lib/ff/ruby/server/sdk/api/summary_metrics.rb +16 -0
  36. data/lib/ff/ruby/server/sdk/api/update_processor.rb +149 -0
  37. data/lib/ff/ruby/server/sdk/common/cache.rb +27 -0
  38. data/lib/ff/ruby/server/sdk/common/closeable.rb +7 -0
  39. data/lib/ff/ruby/server/sdk/common/destroyable.rb +12 -0
  40. data/lib/ff/ruby/server/sdk/common/repository.rb +45 -0
  41. data/lib/ff/ruby/server/sdk/common/storage.rb +29 -0
  42. data/lib/ff/ruby/server/sdk/connector/connector.rb +44 -0
  43. data/lib/ff/ruby/server/sdk/connector/events.rb +118 -0
  44. data/lib/ff/ruby/server/sdk/connector/harness_connector.rb +236 -0
  45. data/lib/ff/ruby/server/sdk/connector/service.rb +19 -0
  46. data/lib/ff/ruby/server/sdk/connector/updater.rb +32 -0
  47. data/lib/ff/ruby/server/sdk/dto/message.rb +13 -0
  48. data/lib/ff/ruby/server/sdk/dto/target.rb +24 -0
  49. data/lib/ff/ruby/server/sdk/version.rb +2 -1
  50. data/lib/ff/ruby/server/sdk.rb +39 -3
  51. data/openapitools.json +7 -0
  52. data/scripts/openapi.sh +35 -0
  53. data/scripts/sdk_specs.sh +1 -1
  54. metadata +46 -3
  55. data/lib/ff/ruby/server/sdk/cf_client.rb +0 -6
@@ -0,0 +1,311 @@
1
+ require_relative "evaluator"
2
+ require_relative "evaluation"
3
+ require_relative "auth_service"
4
+ require_relative "client_callback"
5
+ require_relative "update_processor"
6
+ require_relative "polling_processor"
7
+ require_relative "metrics_processor"
8
+ require_relative "storage_repository"
9
+ require_relative "inner_client_updater"
10
+ require_relative "inner_client_metrics_callback"
11
+ require_relative "inner_client_repository_callback"
12
+ require_relative "inner_client_flag_evaluate_callback"
13
+
14
+ require_relative "../connector/harness_connector"
15
+
16
+ class InnerClient < ClientCallback
17
+
18
+ def initialize(api_key = nil, config = nil, connector = nil)
19
+
20
+ if api_key == nil || api_key == ""
21
+
22
+ raise "SDK key is not provided"
23
+ end
24
+
25
+ if config == nil
26
+
27
+ @config = ConfigBuilder.new.build
28
+ else
29
+
30
+ unless config.kind_of?(Config)
31
+
32
+ raise "The 'config' parameter must be of '" + Config.to_s + "' data type"
33
+ end
34
+
35
+ @config = config
36
+ end
37
+
38
+ @config.logger.debug "Ruby SDK version: " + Ff::Ruby::Server::Sdk::VERSION
39
+
40
+ if connector == nil
41
+
42
+ @connector = HarnessConnector.new(api_key, config = @config, on_unauthorized = self)
43
+
44
+ else
45
+
46
+ unless connector.kind_of?(Connector)
47
+
48
+ raise "The 'connector' parameter must be of '" + Connector.to_s + "' data type"
49
+ end
50
+
51
+ @connector = connector
52
+ end
53
+
54
+ @closing = false
55
+ @failure = false
56
+ @initialized = false
57
+ @poller_ready = false
58
+ @stream_ready = false
59
+ @metrics_ready = false
60
+
61
+ @my_mutex = Mutex.new
62
+
63
+ @repository_callback = InnerClientRepositoryCallback.new(@config.logger)
64
+
65
+ setup
66
+ end
67
+
68
+ def bool_variation(identifier, target, default_value)
69
+
70
+ @evaluator.bool_variation(identifier, target, default_value, @evaluator_callback)
71
+ end
72
+
73
+ def string_variation(identifier, target, default_value)
74
+
75
+ @evaluator.string_variation(identifier, target, default_value, @evaluator_callback)
76
+ end
77
+
78
+ def number_variation(identifier, target, default_value)
79
+
80
+ @evaluator.number_variation(identifier, target, default_value, @evaluator_callback)
81
+ end
82
+
83
+ def json_variation(identifier, target, default_value)
84
+
85
+ @evaluator.json_variation(identifier, target, default_value, @evaluator_callback)
86
+ end
87
+
88
+ def on_auth_success
89
+
90
+ @config.logger.info "SDK successfully logged in"
91
+
92
+ if @closing
93
+
94
+ return
95
+ end
96
+
97
+ @poll_processor.start
98
+
99
+ if @config.stream_enabled
100
+
101
+ @update_processor.start
102
+ end
103
+
104
+ if @config.analytics_enabled
105
+
106
+ @metrics_processor.start
107
+ end
108
+
109
+ end
110
+
111
+ def close
112
+
113
+ @config.logger.info "Closing the client: " + self.to_s
114
+
115
+ @closing = true
116
+
117
+ off
118
+
119
+ @auth_service.close
120
+ @repository.close
121
+ @poll_processor.close
122
+ @update_processor.close
123
+ @metrics_processor.close
124
+ @connector.close
125
+ end
126
+
127
+ def is_closing
128
+
129
+ @closing
130
+ end
131
+
132
+ def off
133
+
134
+ # TODO: Implement - Reactivity support
135
+ end
136
+
137
+ def on_unauthorized
138
+
139
+ if @closing
140
+
141
+ return
142
+ end
143
+
144
+ @poll_processor.stop
145
+
146
+ if @config.stream_enabled
147
+
148
+ @update_processor.stop
149
+ end
150
+
151
+ if @config.analytics_enabled
152
+
153
+ @metrics_processor.stop
154
+ end
155
+
156
+ @auth_service.start_async
157
+ end
158
+
159
+ def on_poller_ready(poller)
160
+
161
+ on_processor_ready(poller)
162
+ end
163
+
164
+ def on_poller_error(e)
165
+
166
+ @config.logger.error "Poller error: " + e.to_s
167
+ end
168
+
169
+ def on_poller_iteration(poller)
170
+
171
+ @config.logger.debug "Poller iterated" + poller.to_s
172
+ end
173
+
174
+ def update(message, manual)
175
+
176
+ if @config.stream_enabled && manual
177
+
178
+ @config.logger.warn "You run the update method manually with the stream enabled. Please turn off the stream in this case."
179
+ end
180
+
181
+ @update_processor.update(message)
182
+ end
183
+
184
+ def on_update_processor_ready
185
+
186
+ on_processor_ready(@update_processor)
187
+ end
188
+
189
+ def on_metrics_processor_ready
190
+
191
+ on_processor_ready(@metrics_processor)
192
+ end
193
+
194
+ def on_processor_ready(processor)
195
+
196
+ if @closing
197
+
198
+ return
199
+ end
200
+
201
+ if processor == @poll_processor
202
+
203
+ @poller_ready = true
204
+ @config.logger.info "PollingProcessor ready"
205
+ end
206
+
207
+ if processor == @update_processor
208
+
209
+ @stream_ready = true
210
+ @config.logger.info "Updater ready"
211
+ end
212
+
213
+ if processor == @metrics_processor
214
+
215
+ @metrics_ready = true
216
+ @config.logger.info "Metrics ready"
217
+ end
218
+
219
+ if (@config.stream_enabled && !@stream_ready) ||
220
+ (@config.analytics_enabled && !@metrics_ready) ||
221
+ !@poller_ready
222
+
223
+ return
224
+ end
225
+
226
+ @initialized = true
227
+
228
+ # TODO: notify - Reactivity support
229
+ # TODO: notify_consumers - Reactivity support
230
+
231
+ @config.logger.info "Initialization is completed"
232
+ end
233
+
234
+ def wait_for_initialization
235
+
236
+ synchronize do
237
+
238
+ @config.logger.info "Waiting for the initialization to finish"
239
+
240
+ until @initialized
241
+
242
+ sleep(1)
243
+ end
244
+
245
+ if @failure
246
+
247
+ raise "Initialization failed"
248
+ end
249
+
250
+ @config.logger.info "Waiting for the initialization completed"
251
+ end
252
+ end
253
+
254
+ protected
255
+
256
+ def setup
257
+
258
+ @config.logger.info "SDK is not initialized yet! If store is used then values will be loaded from store" +
259
+ " otherwise default values will be used in meantime. You can use waitForInitialization method for SDK" +
260
+ " to be ready."
261
+
262
+ @repository = StorageRepository.new(@config.cache, @repository_callback, @config.store, @config.logger)
263
+
264
+ @metrics_callback = InnerClientMetricsCallback.new(self, @config.logger)
265
+ @metrics_processor = MetricsProcessor.new(@connector, @config, @metrics_callback)
266
+
267
+ @evaluator = Evaluator.new(@repository, logger = @config.logger)
268
+ @evaluator_callback = InnerClientFlagEvaluateCallback.new(@metrics_processor, logger = @config.logger)
269
+
270
+ @auth_service = AuthService.new(
271
+
272
+ connector = @connector,
273
+ poll_interval_in_sec = @config.poll_interval_in_seconds,
274
+ callback = self,
275
+ logger = @config.logger
276
+ )
277
+
278
+ @poll_processor = PollingProcessor.new(
279
+
280
+ connector = @connector,
281
+ repository = @repository,
282
+ poll_interval_in_sec = @config.poll_interval_in_seconds,
283
+ callback = self,
284
+ logger = @config.logger
285
+ )
286
+
287
+ @updater = InnerClientUpdater.new(
288
+
289
+ poll_processor = @poll_processor,
290
+ client_callback = self,
291
+ logger = @config.logger
292
+ )
293
+
294
+ @update_processor = UpdateProcessor.new(
295
+
296
+ connector = @connector,
297
+ repository = @repository,
298
+ callback = @updater,
299
+ logger = @config.logger
300
+ )
301
+
302
+ @auth_service.start_async
303
+ end
304
+
305
+ private
306
+
307
+ def synchronize(&block)
308
+
309
+ @my_mutex.synchronize(&block)
310
+ end
311
+ end
@@ -0,0 +1,30 @@
1
+ require_relative "metrics_processor"
2
+ require_relative "flag_evaluate_callback"
3
+
4
+ class InnerClientFlagEvaluateCallback < FlagEvaluateCallback
5
+
6
+ def initialize(metrics_processor, logger = nil)
7
+
8
+ unless metrics_processor.kind_of?(MetricsProcessor)
9
+
10
+ raise "The 'metrics_processor' parameter must be of '" + MetricsProcessor.to_s + "' data type"
11
+ end
12
+
13
+ if logger != nil
14
+
15
+ @logger = logger
16
+ else
17
+
18
+ @logger = Logger.new(STDOUT)
19
+ end
20
+
21
+ @metrics_processor = metrics_processor
22
+ end
23
+
24
+ def process_evaluation(feature_config, target, variation)
25
+
26
+ @logger.debug "Processing evaluation: " + feature_config.feature.to_s + ", " + target.identifier.to_s
27
+
28
+ @metrics_processor.push_to_queue(target, feature_config, variation)
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ require_relative "client_callback"
2
+ require_relative "metrics_callback"
3
+
4
+ class InnerClientMetricsCallback < MetricsCallback
5
+
6
+ def initialize(client_callback, logger = nil)
7
+
8
+ unless client_callback.kind_of?(ClientCallback)
9
+
10
+ raise "The 'client_callback' parameter must be of '" + ClientCallback.to_s + "' data type"
11
+ end
12
+
13
+ if logger != nil
14
+
15
+ @logger = logger
16
+ else
17
+
18
+ @logger = Logger.new(STDOUT)
19
+ end
20
+
21
+ @client_callback = client_callback
22
+ end
23
+
24
+ def on_metrics_ready
25
+
26
+ @client_callback.on_metrics_processor_ready
27
+ end
28
+
29
+ def on_metrics_error(error)
30
+
31
+ @logger.error "Metrics error: " + error.to_s
32
+ end
33
+ end
@@ -0,0 +1,44 @@
1
+ require_relative "inner_client"
2
+ require_relative "repository_callback"
3
+
4
+ class InnerClientRepositoryCallback < RepositoryCallback
5
+
6
+ def initialize(logger = nil)
7
+
8
+ if logger != nil
9
+
10
+ @logger = logger
11
+ else
12
+
13
+ @logger = Logger.new(STDOUT)
14
+ end
15
+ end
16
+
17
+ def on_flag_stored(identifier)
18
+
19
+ @logger.debug "On flag stored: " + identifier
20
+
21
+ # TODO: Notify consumers
22
+ end
23
+
24
+ def on_flag_deleted(identifier)
25
+
26
+ @logger.debug "On flag deleted: " + identifier
27
+
28
+ # TODO: Notify consumers
29
+ end
30
+
31
+ def on_segment_stored(identifier)
32
+
33
+ @logger.debug "On segment stored: " + identifier
34
+
35
+ # TODO: Notify consumers
36
+ end
37
+
38
+ def on_segment_deleted(identifier)
39
+
40
+ @logger.debug "On segment deleted: " + identifier
41
+
42
+ # TODO: Notify consumers
43
+ end
44
+ end
@@ -0,0 +1,63 @@
1
+ require "logger"
2
+
3
+ require_relative "../connector/updater"
4
+
5
+ class InnerClientUpdater < Updater
6
+
7
+ def initialize(
8
+
9
+ poll_processor,
10
+ client_callback,
11
+ logger = nil
12
+ )
13
+
14
+ unless poll_processor.kind_of?(PollingProcessor)
15
+
16
+ raise "The 'poll_processor' parameter must be of '" + PollingProcessor.to_s + "' data type"
17
+ end
18
+
19
+ unless client_callback.kind_of?(ClientCallback)
20
+
21
+ raise "The 'client_callback' parameter must be of '" + ClientCallback.to_s + "' data type"
22
+ end
23
+
24
+ if logger != nil
25
+
26
+ @logger = logger
27
+ else
28
+
29
+ @logger = Logger.new(STDOUT)
30
+ end
31
+
32
+ @poll_processor = poll_processor
33
+ @client_callback = client_callback
34
+ end
35
+
36
+ def on_connected
37
+
38
+ @poll_processor.stop
39
+ end
40
+
41
+ def on_disconnected
42
+
43
+ unless @client_callback.is_closing
44
+
45
+ @poll_processor.start
46
+ end
47
+ end
48
+
49
+ def on_ready
50
+
51
+ @client_callback.on_update_processor_ready()
52
+ end
53
+
54
+ def on_error
55
+
56
+ @logger.error "Error occurred"
57
+ end
58
+
59
+ def update(message)
60
+
61
+ @client_callback.update(message, false)
62
+ end
63
+ end
@@ -0,0 +1,19 @@
1
+
2
+ class MetricsCallback
3
+
4
+ def initialize
5
+ super
6
+
7
+ @tbi = "To be implemented"
8
+ end
9
+
10
+ def on_metrics_ready
11
+
12
+ raise @tbi
13
+ end
14
+
15
+ def on_metrics_error(error)
16
+
17
+ raise @tbi
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ class MetricsEvent
2
+
3
+ attr_accessor :feature_config, :target, :variation
4
+
5
+ def initialize(
6
+
7
+ feature_config,
8
+ target,
9
+ variation
10
+ )
11
+
12
+ @target = target
13
+ @variation = variation
14
+ @feature_config = feature_config
15
+ end
16
+ end