Skip to content

Commit 69119b6

Browse files
committed
feat: implement provider status
1 parent ae26217 commit 69119b6

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

openfeature/provider/__init__.py

+9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import typing
2+
from enum import Enum
23

34
from openfeature.evaluation_context import EvaluationContext
45
from openfeature.flag_evaluation import FlagResolutionDetails
@@ -7,6 +8,14 @@
78
from .metadata import Metadata
89

910

11+
class ProviderStatus(Enum):
12+
NOT_READY = "NOT_READY"
13+
READY = "READY"
14+
ERROR = "ERROR"
15+
STALE = "STALE"
16+
FATAL = "FATAL"
17+
18+
1019
class FeatureProvider(typing.Protocol): # pragma: no cover
1120
def initialize(self, evaluation_context: EvaluationContext) -> None:
1221
...

openfeature/provider/registry.py

+30-6
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,20 @@
22

33
from openfeature.evaluation_context import EvaluationContext
44
from openfeature.exception import GeneralError
5-
from openfeature.provider import FeatureProvider
5+
from openfeature.provider import FeatureProvider, ProviderStatus
66
from openfeature.provider.no_op_provider import NoOpProvider
77

88

99
class 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,31 @@ 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:
70+
self._set_provider_status(provider, ProviderStatus.ERROR)
71+
72+
def _shutdown_provider(self, provider: FeatureProvider) -> None:
73+
try:
74+
if hasattr(provider, "shutdown"):
75+
provider.shutdown()
76+
self._set_provider_status(provider, ProviderStatus.NOT_READY)
77+
except Exception:
78+
self._set_provider_status(provider, ProviderStatus.FATAL)
79+
80+
def _set_provider_status(
81+
self, provider: FeatureProvider, status: ProviderStatus
82+
) -> None:
83+
self._provider_status[provider] = status

0 commit comments

Comments
 (0)