1
1
import typing
2
2
3
3
from 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
6
6
from openfeature .provider .no_op_provider import NoOpProvider
7
7
8
8
9
9
class ProviderRegistry :
10
10
_default_provider : FeatureProvider
11
11
_providers : typing .Dict [str , FeatureProvider ]
12
+ _provider_status : typing .Dict [FeatureProvider , ProviderStatus ]
12
13
13
14
def __init__ (self ) -> None :
14
15
self ._default_provider = NoOpProvider ()
15
16
self ._providers = {}
17
+ self ._provider_status = {}
18
+ self ._set_provider_status (self ._default_provider , ProviderStatus .NOT_READY )
16
19
17
20
def set_provider (self , domain : str , provider : FeatureProvider ) -> None :
18
21
if provider is None :
@@ -22,9 +25,9 @@ def set_provider(self, domain: str, provider: FeatureProvider) -> None:
22
25
old_provider = providers [domain ]
23
26
del providers [domain ]
24
27
if old_provider not in providers .values ():
25
- old_provider . shutdown ( )
28
+ self . _shutdown_provider ( old_provider )
26
29
if provider not in providers .values ():
27
- provider . initialize ( self ._get_evaluation_context () )
30
+ self ._initialize_provider ( provider )
28
31
providers [domain ] = provider
29
32
30
33
def get_provider (self , domain : typing .Optional [str ]) -> FeatureProvider :
@@ -36,9 +39,9 @@ def set_default_provider(self, provider: FeatureProvider) -> None:
36
39
if provider is None :
37
40
raise GeneralError (error_message = "No provider" )
38
41
if self ._default_provider :
39
- self ._default_provider . shutdown ( )
42
+ self ._shutdown_provider ( self . _default_provider )
40
43
self ._default_provider = provider
41
- provider . initialize ( self ._get_evaluation_context () )
44
+ self ._initialize_provider ( provider )
42
45
43
46
def get_default_provider (self ) -> FeatureProvider :
44
47
return self ._default_provider
@@ -50,10 +53,40 @@ def clear_providers(self) -> None:
50
53
51
54
def shutdown (self ) -> None :
52
55
for provider in {self ._default_provider , * self ._providers .values ()}:
53
- provider . shutdown ( )
56
+ self . _shutdown_provider ( provider )
54
57
55
58
def _get_evaluation_context (self ) -> EvaluationContext :
56
59
# imported here to avoid circular imports
57
60
from openfeature .api import get_evaluation_context
58
61
59
62
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