11# frozen_string_literal: true
22
3+ require 'pry'
4+ require 'pry-byebug'
5+
36require 'faraday'
47require 'faraday/retry'
58require 'faraday_middleware'
1619require 'flagsmith/sdk/pooling_manager'
1720require 'flagsmith/sdk/models/flags'
1821require 'flagsmith/sdk/models/segments'
22+ require 'flagsmith/sdk/offline_handlers'
1923
2024require 'flagsmith/engine/core'
2125
@@ -44,7 +48,9 @@ class Client # rubocop:disable Metrics/ClassLength
4448 # Available Configs.
4549 #
4650 # :environment_key, :api_url, :custom_headers, :request_timeout_seconds, :enable_local_evaluation,
47- # :environment_refresh_interval_seconds, :retries, :enable_analytics, :default_flag_handler
51+ # :environment_refresh_interval_seconds, :retries, :enable_analytics, :default_flag_handler,
52+ # :offline_mode, :offline_handler
53+ #
4854 # You can see full description in the Flagsmith::Config
4955
5056 attr_reader :config , :environment
@@ -55,10 +61,24 @@ def initialize(config)
5561 @_mutex = Mutex . new
5662 @config = Flagsmith ::Config . new ( config )
5763
64+ validate_offline_mode!
65+
5866 api_client
5967 analytics_processor
6068 environment_data_polling_manager
6169 engine
70+ load_offline_handler
71+ end
72+
73+ def validate_offline_mode!
74+ if @config . offline_mode? && !@config . offline_handler
75+ raise Flagsmith ::ClientError ,
76+ 'The offline_mode config param requires a matching offline_handler.'
77+ end
78+ return unless @config . offline_handler && @config . default_flag_handler
79+
80+ raise Flagsmith ::ClientError ,
81+ 'Cannot use offline_handler and default_flag_handler at the same time.'
6282 end
6383
6484 def api_client
@@ -79,6 +99,10 @@ def analytics_processor
7999 )
80100 end
81101
102+ def load_offline_handler
103+ @environment = offline_handler . environment if offline_handler
104+ end
105+
82106 def environment_data_polling_manager
83107 return nil unless @config . local_evaluation?
84108
@@ -103,7 +127,7 @@ def environment_from_api
103127 # Get all the default for flags for the current environment.
104128 # @returns Flags object holding all the flags for the current environment.
105129 def get_environment_flags # rubocop:disable Naming/AccessorMethodName
106- return environment_flags_from_document if @config . local_evaluation?
130+ return environment_flags_from_document if @config . local_evaluation? || @config . offline_mode
107131
108132 environment_flags_from_api
109133 end
@@ -154,7 +178,7 @@ def get_value_for_identity(feature_name, user_id = nil, default: nil)
154178 def get_identity_segments ( identifier , traits = { } )
155179 unless environment
156180 raise Flagsmith ::ClientError ,
157- 'Local evaluation required to obtain identity segments.'
181+ 'Local evaluation or offline handler is required to obtain identity segments.'
158182 end
159183
160184 identity_model = build_identity_model ( identifier , traits )
@@ -168,7 +192,8 @@ def environment_flags_from_document
168192 Flagsmith ::Flags ::Collection . from_feature_state_models (
169193 engine . get_environment_feature_states ( environment ) ,
170194 analytics_processor : analytics_processor ,
171- default_flag_handler : default_flag_handler
195+ default_flag_handler : default_flag_handler ,
196+ offline_handler : offline_handler
172197 )
173198 end
174199
@@ -178,45 +203,80 @@ def get_identity_flags_from_document(identifier, traits = {})
178203 Flagsmith ::Flags ::Collection . from_feature_state_models (
179204 engine . get_identity_feature_states ( environment , identity_model ) ,
180205 analytics_processor : analytics_processor ,
181- default_flag_handler : default_flag_handler
206+ default_flag_handler : default_flag_handler ,
207+ offline_handler : offline_handler
182208 )
183209 end
184210
211+ # rubocop:disable Metrics/MethodLength
185212 def environment_flags_from_api
186- rescue_with_default_handler do
187- api_flags = api_client . get ( @config . environment_flags_url ) . body
188- api_flags = api_flags . select { |flag | flag [ :feature_segment ] . nil? }
189- Flagsmith ::Flags ::Collection . from_api (
190- api_flags ,
191- analytics_processor : analytics_processor ,
192- default_flag_handler : default_flag_handler
193- )
213+ if offline_handler
214+ begin
215+ process_environment_flags_from_api
216+ rescue StandardError
217+ environment_flags_from_document
218+ end
219+ else
220+ begin
221+ process_environment_flags_from_api
222+ rescue StandardError
223+ if default_flag_handler
224+ return Flagsmith ::Flags ::Collection . new (
225+ { } ,
226+ default_flag_handler : default_flag_handler
227+ )
228+ end
229+ raise
230+ end
194231 end
195232 end
233+ # rubocop:enable Metrics/MethodLength
196234
235+ def process_environment_flags_from_api
236+ api_flags = api_client . get ( @config . environment_flags_url ) . body
237+ api_flags = api_flags . select { |flag | flag [ :feature_segment ] . nil? }
238+ Flagsmith ::Flags ::Collection . from_api (
239+ api_flags ,
240+ analytics_processor : analytics_processor ,
241+ default_flag_handler : default_flag_handler ,
242+ offline_handler : offline_handler
243+ )
244+ end
245+
246+ # rubocop:disable Metrics/MethodLength
197247 def get_identity_flags_from_api ( identifier , traits = { } )
198- rescue_with_default_handler do
199- data = generate_identities_data ( identifier , traits )
200- json_response = api_client . post ( @config . identities_url , data . to_json ) . body
201-
202- Flagsmith ::Flags ::Collection . from_api (
203- json_response [ :flags ] ,
204- analytics_processor : analytics_processor ,
205- default_flag_handler : default_flag_handler
206- )
248+ if offline_handler
249+ begin
250+ process_identity_flags_from_api ( identifier , traits )
251+ rescue StandardError
252+ get_identity_flags_from_document ( identifier , traits )
253+ end
254+ else
255+ begin
256+ process_identity_flags_from_api ( identifier , traits )
257+ rescue StandardError
258+ if default_flag_handler
259+ return Flagsmith ::Flags ::Collection . new (
260+ { } ,
261+ default_flag_handler : default_flag_handler
262+ )
263+ end
264+ raise
265+ end
207266 end
208267 end
268+ # rubocop:enable Metrics/MethodLength
209269
210- def rescue_with_default_handler
211- yield
212- rescue StandardError
213- if default_flag_handler
214- return Flagsmith ::Flags ::Collection . new (
215- { } ,
216- default_flag_handler : default_flag_handler
217- )
218- end
219- raise
270+ def process_identity_flags_from_api ( identifier , traits = { } )
271+ data = generate_identities_data ( identifier , traits )
272+ json_response = api_client . post ( @config . identities_url , data . to_json ) . body
273+
274+ Flagsmith ::Flags ::Collection . from_api (
275+ json_response [ :flags ] ,
276+ analytics_processor : analytics_processor ,
277+ default_flag_handler : default_flag_handler ,
278+ offline_handler : offline_handler
279+ )
220280 end
221281
222282 def build_identity_model ( identifier , traits = { } )
0 commit comments