11import typing
22
33from openfeature .evaluation_context import EvaluationContext
4- from openfeature .exception import GeneralError
5- from openfeature .provider import FeatureProvider
4+ from openfeature .exception import ErrorCode , GeneralError , OpenFeatureError
5+ from openfeature .provider import FeatureProvider , ProviderStatus
66from openfeature .provider .no_op_provider import NoOpProvider
77
88
99class ProviderRegistry :
1010 _default_provider : FeatureProvider
1111 _providers : typing .Dict [str , FeatureProvider ]
12+ _provider_status : typing .Dict [FeatureProvider , ProviderStatus ]
1213
1314 def __init__ (self ) -> None :
1415 self ._default_provider = NoOpProvider ()
1516 self ._providers = {}
17+ self ._provider_status = {}
18+ self ._set_provider_status (self ._default_provider , ProviderStatus .NOT_READY )
1619
1720 def set_provider (self , domain : str , provider : FeatureProvider ) -> None :
1821 if provider is None :
@@ -22,9 +25,9 @@ def set_provider(self, domain: str, provider: FeatureProvider) -> None:
2225 old_provider = providers [domain ]
2326 del providers [domain ]
2427 if old_provider not in providers .values ():
25- old_provider . shutdown ( )
28+ self . _shutdown_provider ( old_provider )
2629 if provider not in providers .values ():
27- provider . initialize ( self ._get_evaluation_context () )
30+ self ._initialize_provider ( provider )
2831 providers [domain ] = provider
2932
3033 def get_provider (self , domain : typing .Optional [str ]) -> FeatureProvider :
@@ -36,9 +39,9 @@ def set_default_provider(self, provider: FeatureProvider) -> None:
3639 if provider is None :
3740 raise GeneralError (error_message = "No provider" )
3841 if self ._default_provider :
39- self ._default_provider . shutdown ( )
42+ self ._shutdown_provider ( self . _default_provider )
4043 self ._default_provider = provider
41- provider . initialize ( self ._get_evaluation_context () )
44+ self ._initialize_provider ( provider )
4245
4346 def get_default_provider (self ) -> FeatureProvider :
4447 return self ._default_provider
@@ -50,10 +53,40 @@ def clear_providers(self) -> None:
5053
5154 def shutdown (self ) -> None :
5255 for provider in {self ._default_provider , * self ._providers .values ()}:
53- provider . shutdown ( )
56+ self . _shutdown_provider ( provider )
5457
5558 def _get_evaluation_context (self ) -> EvaluationContext :
5659 # imported here to avoid circular imports
5760 from openfeature .api import get_evaluation_context
5861
5962 return get_evaluation_context ()
63+
64+ def _initialize_provider (self , provider : FeatureProvider ) -> None :
65+ try :
66+ if hasattr (provider , "initialize" ):
67+ provider .initialize (self ._get_evaluation_context ())
68+ self ._set_provider_status (provider , ProviderStatus .READY )
69+ except Exception as err :
70+ if (
71+ isinstance (err , OpenFeatureError )
72+ and err .error_code == ErrorCode .PROVIDER_FATAL
73+ ):
74+ self ._set_provider_status (provider , ProviderStatus .FATAL )
75+ else :
76+ self ._set_provider_status (provider , ProviderStatus .ERROR )
77+
78+ def _shutdown_provider (self , provider : FeatureProvider ) -> None :
79+ try :
80+ if hasattr (provider , "shutdown" ):
81+ provider .shutdown ()
82+ self ._set_provider_status (provider , ProviderStatus .NOT_READY )
83+ except Exception :
84+ self ._set_provider_status (provider , ProviderStatus .FATAL )
85+
86+ def get_provider_status (self , provider : FeatureProvider ) -> ProviderStatus :
87+ return self ._provider_status .get (provider , ProviderStatus .NOT_READY )
88+
89+ def _set_provider_status (
90+ self , provider : FeatureProvider , status : ProviderStatus
91+ ) -> None :
92+ self ._provider_status [provider ] = status
0 commit comments