12
12
# limitations under the License.
13
13
14
14
import abc
15
+ import numbers
15
16
import requests
16
17
import threading
17
18
import time
@@ -95,6 +96,7 @@ def __init__(self,
95
96
notification_center = notification_center )
96
97
self ._config = None
97
98
self .validate_schema = not skip_json_validation
99
+ self ._config_ready_event = threading .Event ()
98
100
self ._set_config (datafile )
99
101
100
102
def _set_config (self , datafile ):
@@ -133,6 +135,7 @@ def _set_config(self, datafile):
133
135
return
134
136
135
137
self ._config = config
138
+ self ._config_ready_event .set ()
136
139
self .notification_center .send_notifications (enums .NotificationTypes .OPTIMIZELY_CONFIG_UPDATE )
137
140
self .logger .debug (
138
141
'Received new datafile and updated config. '
@@ -145,6 +148,7 @@ def get_config(self):
145
148
Returns:
146
149
ProjectConfig. None if not set.
147
150
"""
151
+
148
152
return self ._config
149
153
150
154
@@ -155,6 +159,7 @@ def __init__(self,
155
159
sdk_key = None ,
156
160
datafile = None ,
157
161
update_interval = None ,
162
+ blocking_timeout = None ,
158
163
url = None ,
159
164
url_template = None ,
160
165
logger = None ,
@@ -168,6 +173,8 @@ def __init__(self,
168
173
datafile: Optional JSON string representing the project.
169
174
update_interval: Optional floating point number representing time interval in seconds
170
175
at which to request datafile and set ProjectConfig.
176
+ blocking_timeout: Optional Time in seconds to block the get_config call until config object
177
+ has been initialized.
171
178
url: Optional string representing URL from where to fetch the datafile. If set it supersedes the sdk_key.
172
179
url_template: Optional string template which in conjunction with sdk_key
173
180
determines URL from where to fetch the datafile.
@@ -187,6 +194,7 @@ def __init__(self,
187
194
self .datafile_url = self .get_datafile_url (sdk_key , url ,
188
195
url_template or enums .ConfigManager .DATAFILE_URL_TEMPLATE )
189
196
self .set_update_interval (update_interval )
197
+ self .set_blocking_timeout (blocking_timeout )
190
198
self .last_modified = None
191
199
self ._polling_thread = threading .Thread (target = self ._run )
192
200
self ._polling_thread .setDaemon (True )
@@ -224,15 +232,26 @@ def get_datafile_url(sdk_key, url, url_template):
224
232
225
233
return url
226
234
235
+ def get_config (self ):
236
+ """ Returns instance of ProjectConfig. Returns immediately if project config is ready otherwise
237
+ blocks maximum for value of blocking_timeout in seconds.
238
+
239
+ Returns:
240
+ ProjectConfig. None if not set.
241
+ """
242
+
243
+ self ._config_ready_event .wait (self .blocking_timeout )
244
+ return self ._config
245
+
227
246
def set_update_interval (self , update_interval ):
228
247
""" Helper method to set frequency at which datafile has to be polled and ProjectConfig updated.
229
248
230
249
Args:
231
250
update_interval: Time in seconds after which to update datafile.
232
251
"""
233
- if not update_interval :
252
+ if update_interval is None :
234
253
update_interval = enums .ConfigManager .DEFAULT_UPDATE_INTERVAL
235
- self .logger .debug ('Set config update interval to default value {}.' .format (update_interval ))
254
+ self .logger .debug ('Setting config update interval to default value {}.' .format (update_interval ))
236
255
237
256
if not isinstance (update_interval , (int , float )):
238
257
raise optimizely_exceptions .InvalidInputException (
@@ -249,6 +268,31 @@ def set_update_interval(self, update_interval):
249
268
250
269
self .update_interval = update_interval
251
270
271
+ def set_blocking_timeout (self , blocking_timeout ):
272
+ """ Helper method to set time in seconds to block the config call until config has been initialized.
273
+
274
+ Args:
275
+ blocking_timeout: Time in seconds to block the config call.
276
+ """
277
+ if blocking_timeout is None :
278
+ blocking_timeout = enums .ConfigManager .DEFAULT_BLOCKING_TIMEOUT
279
+ self .logger .debug ('Setting config blocking timeout to default value {}.' .format (blocking_timeout ))
280
+
281
+ if not isinstance (blocking_timeout , (numbers .Integral , float )):
282
+ raise optimizely_exceptions .InvalidInputException (
283
+ 'Invalid blocking timeout "{}" provided.' .format (blocking_timeout )
284
+ )
285
+
286
+ # If blocking timeout is less than 0 then set it to default blocking timeout.
287
+ if blocking_timeout < 0 :
288
+ self .logger .debug ('blocking timeout value {} too small. Defaulting to {}' .format (
289
+ blocking_timeout ,
290
+ enums .ConfigManager .DEFAULT_BLOCKING_TIMEOUT )
291
+ )
292
+ blocking_timeout = enums .ConfigManager .DEFAULT_BLOCKING_TIMEOUT
293
+
294
+ self .blocking_timeout = blocking_timeout
295
+
252
296
def set_last_modified (self , response_headers ):
253
297
""" Looks up and sets last modified time based on Last-Modified header in the response.
254
298
0 commit comments