@@ -100,17 +100,6 @@ def load(
100
100
:paramtype on_refresh_error: Optional[Callable[[Exception], None]]
101
101
:keyword on_refresh_error: Optional callback to be invoked when an error occurs while refreshing settings. If not
102
102
specified, errors will be raised.
103
- :paramtype feature_flag_enabled: bool
104
- :keyword feature_flag_enabled: Optional flag to enable or disable the loading of feature flags. Default is False.
105
- :paramtype feature_flag_selectors: List[SettingSelector]
106
- :keyword feature_flag_selectors: Optional list of selectors to filter feature flags. By default will load all
107
- feature flags without a label.
108
- :paramtype feature_flag_refresh_enabled: bool
109
- :keyword feature_flag_refresh_enabled: Optional flag to enable or disable the refresh of feature flags. Default is
110
- False.
111
- :paramtype feature_flag_trim_prefixes: List[str]
112
- :keyword feature_flag_trim_prefixes: After the FEATURE_FLAG_PREFIX is trimmed, the first match in
113
- feature_flag_trim_prefixes will be trimmed, if there is one.
114
103
"""
115
104
116
105
@@ -155,17 +144,6 @@ def load(
155
144
:paramtype on_refresh_error: Optional[Callable[[Exception], None]]
156
145
:keyword on_refresh_error: Optional callback to be invoked when an error occurs while refreshing settings. If not
157
146
specified, errors will be raised.
158
- :paramtype feature_flag_enabled: bool
159
- :keyword feature_flag_enabled: Optional flag to enable or disable the loading of feature flags. Default is False.
160
- :paramtype feature_flag_selectors: List[SettingSelector]
161
- :keyword feature_flag_selectors: Optional list of selectors to filter feature flags. By default will load all
162
- feature flags without a label.
163
- :paramtype feature_flag_refresh_enabled: bool
164
- :keyword feature_flag_refresh_enabled: Optional flag to enable or disable the refresh of feature flags. Default is
165
- False.
166
- :paramtype feature_flag_trim_prefixes: List[str]
167
- :keyword feature_flag_trim_prefixes: After the FEATURE_FLAG_PREFIX is trimmed, the first match in
168
- feature_flag_trim_prefixes will be trimmed, if there is one.
169
147
"""
170
148
171
149
@@ -460,19 +438,12 @@ def __init__(self, **kwargs) -> None:
460
438
or self ._keyvault_client_configs is not None
461
439
or self ._secret_resolver is not None
462
440
)
463
- self ._feature_flag_enabled = kwargs .pop ("feature_flag_enabled" , False )
464
- self ._feature_flag_selectors = kwargs .pop ("feature_flag_selectors" , [SettingSelector (key_filter = "*" )])
465
- self ._refresh_on_feature_flags = None
466
- self ._feature_flag_refresh_timer : _RefreshTimer = _RefreshTimer (** kwargs )
467
- self ._feature_flag_refresh_enabled = kwargs .pop ("feature_flag_refresh_enabled" , False )
468
- feature_flag_trim_prefixes = kwargs .pop ("feature_flag_trim_prefixes" , [])
469
- self ._feature_flag_trim_prefixes : List [str ] = sorted (feature_flag_trim_prefixes , key = len , reverse = True )
470
441
self ._update_lock = Lock ()
471
442
self ._refresh_lock = Lock ()
472
443
473
444
def refresh (self , ** kwargs ) -> None :
474
- if not self ._refresh_on and not self . _feature_flag_refresh_enabled :
475
- logging .debug ("Refresh called but no refresh enabled ." )
445
+ if not self ._refresh_on :
446
+ logging .debug ("Refresh called but no refresh options set ." )
476
447
return
477
448
if not self ._refresh_timer .needs_refresh ():
478
449
logging .debug ("Refresh called but refresh interval not elapsed." )
@@ -532,76 +503,7 @@ def refresh(self, **kwargs) -> None:
532
503
elif need_refresh and self ._on_refresh_success :
533
504
self ._on_refresh_success ()
534
505
535
- def refresh_configuration_settings (self , configuration_settings , sentinel_keys , timer , ** kwargs ) -> None :
536
- success = False
537
- need_refresh = False
538
- updated_feature_flags = False
539
- headers = _get_headers ("Watch" , uses_key_vault = self ._uses_key_vault , ** kwargs )
540
- try :
541
- for (key , label ), etag in sentinel_keys .items ():
542
- etag , update , is_feature_flag , configuration_settings = self ._check_configuration_settings (
543
- key , label , etag , headers , configuration_settings , ** kwargs
544
- )
545
- if update and not is_feature_flag :
546
- need_refresh = True
547
- elif update and is_feature_flag :
548
- updated_feature_flags = True
549
-
550
- sentinel_keys [(key , label )] = etag
551
- # Need to only update once, no matter how many sentinels are updated
552
- if need_refresh :
553
- configuration_settings , sentinel_keys = self ._load_configuration_settings (
554
- headers = headers , sentinel_keys = sentinel_keys , ** kwargs
555
- )
556
- success = True
557
- # Even if we don't need to refresh, we should reset the timer
558
- timer .reset ()
559
- except (ServiceRequestError , ServiceResponseError , HttpResponseError ) as e :
560
- # If a call back is provided, we should call it, otherwise raise the error
561
- if not self ._on_refresh_error :
562
- raise
563
- self ._on_refresh_error (e )
564
- finally :
565
- # If we get an error we should retry sooner than the next refresh interval
566
- if not success :
567
- timer .backoff ()
568
- return configuration_settings , sentinel_keys , need_refresh or updated_feature_flags
569
-
570
- def _check_configuration_settings (self , key , label , etag , headers , configuration_settings , ** kwargs ) -> None :
571
- is_feature_flag = False
572
- try :
573
- updated_config = self ._client .get_configuration_setting (
574
- key = key , label = label , etag = etag , match_condition = MatchConditions .IfModified , headers = headers , ** kwargs
575
- )
576
- is_feature_flag = not isinstance (updated_config , FeatureFlagConfigurationSetting )
577
- if updated_config is not None :
578
- if not is_feature_flag :
579
- logging .debug ("Refresh all triggered by key: %s label %s." , key , label )
580
- elif is_feature_flag :
581
- configuration_settings [self ._process_key_name (updated_config )] = updated_config .value
582
- return updated_config .etag , True , is_feature_flag , configuration_settings
583
- except HttpResponseError as e :
584
- if e .status_code == 404 :
585
- if etag is not None and not is_feature_flag :
586
- # If the sentinel is not found, it means the key/label was deleted, so we should refresh
587
- logging .debug ("Refresh all triggered by key: %s label %s." , key , label )
588
- elif etag is not None and is_feature_flag :
589
- configuration_settings [key ] = None
590
- return None , True , is_feature_flag , configuration_settings
591
- raise e
592
- return etag , False , is_feature_flag , configuration_settings
593
-
594
506
def _load_all (self , ** kwargs ):
595
- configuration_settings , sentinel_keys = self ._load_configuration_settings (** kwargs )
596
- feature_flags , feature_flag_sentinel_keys = self ._load_feature_flags (** kwargs )
597
- if self ._feature_flag_enabled :
598
- configuration_settings [FEATURE_MANAGEMENT_KEY ] = feature_flags
599
- self ._refresh_on_feature_flags = feature_flag_sentinel_keys
600
- with self ._update_lock :
601
- self ._refresh_on = sentinel_keys
602
- self ._dict = configuration_settings
603
-
604
- def _load_configuration_settings (self , ** kwargs ):
605
507
configuration_settings = {}
606
508
sentinel_keys = kwargs .pop ("sentinel_keys" , self ._refresh_on )
607
509
for select in self ._selects :
@@ -612,51 +514,30 @@ def _load_configuration_settings(self, **kwargs):
612
514
key = self ._process_key_name (config )
613
515
value = self ._process_key_value (config )
614
516
if isinstance (config , FeatureFlagConfigurationSetting ):
615
- # Feature flags are ignored when loaded by Selects, as they are selected from
616
- # `feature_flag_selectors`
617
- pass
517
+ feature_management = configuration_settings .get (FEATURE_MANAGEMENT_KEY , {})
518
+ feature_management [key ] = value
519
+ if FEATURE_MANAGEMENT_KEY not in configuration_settings :
520
+ configuration_settings [FEATURE_MANAGEMENT_KEY ] = feature_management
618
521
else :
619
522
configuration_settings [key ] = value
620
523
# Every time we run load_all, we should update the etag of our refresh sentinels
621
524
# so they stay up-to-date.
622
525
# Sentinel keys will have unprocessed key names, so we need to use the original key.
623
526
if (config .key , config .label ) in self ._refresh_on :
624
527
sentinel_keys [(config .key , config .label )] = config .etag
625
- return configuration_settings , sentinel_keys
626
-
627
- def _load_feature_flags (self , ** kwargs ):
628
- feature_flag_sentinel_keys = {}
629
- loaded_feature_flags = {}
630
- if self ._feature_flag_enabled :
631
- for select in self ._feature_flag_selectors :
632
- feature_flags = self ._client .list_configuration_settings (
633
- key_filter = FEATURE_FLAG_PREFIX + select .key_filter , label_filter = select .label_filter , ** kwargs
634
- )
635
- for feature_flag in feature_flags :
636
- key = self ._process_key_name (feature_flag )
637
- loaded_feature_flags [key ] = feature_flag .value
638
- if self ._feature_flag_refresh_enabled :
639
- feature_flag_sentinel_keys [(feature_flag .key , feature_flag .label )] = feature_flag .etag
640
- return loaded_feature_flags , feature_flag_sentinel_keys
528
+ self ._refresh_on = sentinel_keys
529
+ with self ._update_lock :
530
+ self ._dict = configuration_settings
641
531
642
532
def _process_key_name (self , config ):
643
533
trimmed_key = config .key
644
534
# Trim the key if it starts with one of the prefixes provided
645
-
646
- # Feature Flags have there own prefix, so we need to trim that first
647
- if isinstance (config , FeatureFlagConfigurationSetting ):
648
- if trimmed_key .startswith (FEATURE_FLAG_PREFIX ):
649
- trimmed_key = trimmed_key [len (FEATURE_FLAG_PREFIX ) :]
650
- for trim in self ._feature_flag_trim_prefixes :
651
- if trimmed_key .startswith (trim ):
652
- trimmed_key = trimmed_key [len (trim ) :]
653
- break
654
- return trimmed_key
655
-
656
535
for trim in self ._trim_prefixes :
657
536
if config .key .startswith (trim ):
658
537
trimmed_key = config .key [len (trim ) :]
659
538
break
539
+ if isinstance (config , FeatureFlagConfigurationSetting ) and trimmed_key .startswith (FEATURE_FLAG_PREFIX ):
540
+ return trimmed_key [len (FEATURE_FLAG_PREFIX ) :]
660
541
return trimmed_key
661
542
662
543
def _process_key_value (self , config ):
0 commit comments