Skip to content

Commit 3327f26

Browse files
committed
Add offline mode to flagsmith.rb
1 parent 5906c22 commit 3327f26

File tree

1 file changed

+75
-22
lines changed

1 file changed

+75
-22
lines changed

lib/flagsmith.rb

Lines changed: 75 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# frozen_string_literal: true
2+
require "pry"
3+
require "pry-byebug"
24

35
require 'faraday'
46
require 'faraday/retry'
@@ -16,6 +18,7 @@
1618
require 'flagsmith/sdk/pooling_manager'
1719
require 'flagsmith/sdk/models/flags'
1820
require 'flagsmith/sdk/models/segments'
21+
require 'flagsmith/sdk/offline_handlers'
1922

2023
require 'flagsmith/engine/core'
2124

@@ -44,7 +47,9 @@ class Client # rubocop:disable Metrics/ClassLength
4447
# Available Configs.
4548
#
4649
# :environment_key, :api_url, :custom_headers, :request_timeout_seconds, :enable_local_evaluation,
47-
# :environment_refresh_interval_seconds, :retries, :enable_analytics, :default_flag_handler
50+
# :environment_refresh_interval_seconds, :retries, :enable_analytics, :default_flag_handler,
51+
# :offline_mode, :offline_handler
52+
#
4853
# You can see full description in the Flagsmith::Config
4954

5055
attr_reader :config, :environment
@@ -55,10 +60,24 @@ def initialize(config)
5560
@_mutex = Mutex.new
5661
@config = Flagsmith::Config.new(config)
5762

63+
validate_offline_mode!
64+
5865
api_client
5966
analytics_processor
6067
environment_data_polling_manager
6168
engine
69+
load_offline_handler
70+
end
71+
72+
def validate_offline_mode!
73+
if @config.offline_mode? and not @config.offline_handler
74+
raise Flagsmith::ClientError,
75+
'The offline_mode config param requires a matching offline_handler.'
76+
end
77+
if @config.offline_handler and @config.default_flag_handler
78+
raise Flagsmith::ClientError,
79+
'Cannot use offline_handler and default_flag_handler at the same time.'
80+
end
6281
end
6382

6483
def api_client
@@ -79,6 +98,10 @@ def analytics_processor
7998
)
8099
end
81100

101+
def load_offline_handler
102+
@environment = offline_handler.environment if offline_handler
103+
end
104+
82105
def environment_data_polling_manager
83106
return nil unless @config.local_evaluation?
84107

@@ -103,7 +126,9 @@ def environment_from_api
103126
# Get all the default for flags for the current environment.
104127
# @returns Flags object holding all the flags for the current environment.
105128
def get_environment_flags # rubocop:disable Naming/AccessorMethodName
106-
return environment_flags_from_document if @config.local_evaluation?
129+
if @config.local_evaluation? or @config.offline_mode
130+
return environment_flags_from_document
131+
end
107132

108133
environment_flags_from_api
109134
end
@@ -154,7 +179,7 @@ def get_value_for_identity(feature_name, user_id = nil, default: nil)
154179
def get_identity_segments(identifier, traits = {})
155180
unless environment
156181
raise Flagsmith::ClientError,
157-
'Local evaluation required to obtain identity segments.'
182+
'Local evaluation or offline handler is required to obtain identity segments.'
158183
end
159184

160185
identity_model = build_identity_model(identifier, traits)
@@ -168,7 +193,8 @@ def environment_flags_from_document
168193
Flagsmith::Flags::Collection.from_feature_state_models(
169194
engine.get_environment_feature_states(environment),
170195
analytics_processor: analytics_processor,
171-
default_flag_handler: default_flag_handler
196+
default_flag_handler: default_flag_handler,
197+
offline_handler: offline_handler,
172198
)
173199
end
174200

@@ -178,35 +204,62 @@ def get_identity_flags_from_document(identifier, traits = {})
178204
Flagsmith::Flags::Collection.from_feature_state_models(
179205
engine.get_identity_feature_states(environment, identity_model),
180206
analytics_processor: analytics_processor,
181-
default_flag_handler: default_flag_handler
207+
default_flag_handler: default_flag_handler,
208+
offline_handler: offline_handler,
182209
)
183210
end
184211

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+
return _environment_flags_from_api
216+
rescue
217+
return environment_flags_from_document
218+
end
219+
else
220+
rescue_with_default_handler do
221+
return _environment_flags_from_api
222+
end
194223
end
195224
end
196225

197-
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
226+
def _environment_flags_from_api
227+
api_flags = api_client.get(@config.environment_flags_url).body
228+
api_flags = api_flags.select { |flag| flag[:feature_segment].nil? }
229+
Flagsmith::Flags::Collection.from_api(
230+
api_flags,
231+
analytics_processor: analytics_processor,
232+
default_flag_handler: default_flag_handler,
233+
offline_handler: offline_handler
234+
)
235+
end
201236

202-
Flagsmith::Flags::Collection.from_api(
203-
json_response[:flags],
204-
analytics_processor: analytics_processor,
205-
default_flag_handler: default_flag_handler
206-
)
237+
def get_identity_flags_from_api(identifier, traits = {})
238+
if offline_handler
239+
begin
240+
return _get_identity_flags_from_api(identifier, traits)
241+
rescue
242+
return get_identity_flags_from_document(identifier, traits)
243+
end
244+
else
245+
rescue_with_default_handler do
246+
return _get_identity_flags_from_api(identifier, traits)
247+
end
207248
end
208249
end
209250

251+
def _get_identity_flags_from_api(identifier, traits = {})
252+
data = generate_identities_data(identifier, traits)
253+
json_response = api_client.post(@config.identities_url, data.to_json).body
254+
255+
Flagsmith::Flags::Collection.from_api(
256+
json_response[:flags],
257+
analytics_processor: analytics_processor,
258+
default_flag_handler: default_flag_handler,
259+
offline_handler: offline_handler
260+
)
261+
end
262+
210263
def rescue_with_default_handler
211264
yield
212265
rescue StandardError

0 commit comments

Comments
 (0)