Skip to content

Commit ee9c31c

Browse files
committed
feat: update provider status when provider emits events
Signed-off-by: Federico Bond <[email protected]>
1 parent b28ccb4 commit ee9c31c

File tree

3 files changed

+89
-15
lines changed

3 files changed

+89
-15
lines changed

openfeature/provider/_registry.py

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,34 +74,78 @@ def _initialize_provider(self, provider: FeatureProvider) -> None:
7474
try:
7575
if hasattr(provider, "initialize"):
7676
provider.initialize(self._get_evaluation_context())
77-
self._set_provider_status(provider, ProviderStatus.READY)
77+
self.dispatch_event(
78+
provider, ProviderEvent.PROVIDER_READY, ProviderEventDetails()
79+
)
7880
except Exception as err:
7981
if (
8082
isinstance(err, OpenFeatureError)
8183
and err.error_code == ErrorCode.PROVIDER_FATAL
8284
):
83-
self._set_provider_status(provider, ProviderStatus.FATAL)
85+
self.dispatch_event(
86+
provider,
87+
ProviderEvent.PROVIDER_ERROR,
88+
ProviderEventDetails(
89+
message=f"Provider initialization failed: {err}",
90+
error_code=ErrorCode.PROVIDER_FATAL,
91+
),
92+
)
8493
else:
85-
self._set_provider_status(provider, ProviderStatus.ERROR)
94+
self.dispatch_event(
95+
provider,
96+
ProviderEvent.PROVIDER_ERROR,
97+
ProviderEventDetails(
98+
message=f"Provider initialization failed: {err}",
99+
error_code=ErrorCode.GENERAL,
100+
),
101+
)
86102

87103
def _shutdown_provider(self, provider: FeatureProvider) -> None:
88104
try:
89105
if hasattr(provider, "shutdown"):
90106
provider.shutdown()
91-
self._set_provider_status(provider, ProviderStatus.NOT_READY)
92-
except Exception:
93-
self._set_provider_status(provider, ProviderStatus.FATAL)
107+
self.dispatch_event(
108+
provider, ProviderEvent.PROVIDER_READY, ProviderEventDetails()
109+
)
110+
except Exception as err:
111+
self.dispatch_event(
112+
provider,
113+
ProviderEvent.PROVIDER_ERROR,
114+
ProviderEventDetails(
115+
message=f"Provider shutdown failed: {err}",
116+
error_code=ErrorCode.PROVIDER_FATAL,
117+
),
118+
)
94119

95120
def get_provider_status(self, provider: FeatureProvider) -> ProviderStatus:
96121
return self._provider_status.get(provider, ProviderStatus.NOT_READY)
97122

98-
def _set_provider_status(
99-
self, provider: FeatureProvider, status: ProviderStatus
123+
def dispatch_event(
124+
self,
125+
provider: FeatureProvider,
126+
event: ProviderEvent,
127+
details: ProviderEventDetails,
100128
) -> None:
101-
self._provider_status[provider] = status
102-
103-
if event := ProviderEvent.from_provider_status(status):
104-
run_handlers_for_provider(provider, event, ProviderEventDetails())
129+
self._update_provider_status(provider, event, details)
130+
run_handlers_for_provider(provider, event, details)
131+
132+
def _update_provider_status(
133+
self,
134+
provider: FeatureProvider,
135+
event: ProviderEvent,
136+
details: ProviderEventDetails,
137+
) -> None:
138+
if event == ProviderEvent.PROVIDER_READY:
139+
self._provider_status[provider] = ProviderStatus.READY
140+
elif event == ProviderEvent.PROVIDER_STALE:
141+
self._provider_status[provider] = ProviderStatus.STALE
142+
elif event == ProviderEvent.PROVIDER_ERROR:
143+
status = (
144+
ProviderStatus.FATAL
145+
if details.error_code == ErrorCode.PROVIDER_FATAL
146+
else ProviderStatus.ERROR
147+
)
148+
self._provider_status[provider] = status
105149

106150

107151
default_registry = ProviderRegistry()

openfeature/provider/provider.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import typing
22
from abc import abstractmethod
33

4-
from openfeature._event_support import run_handlers_for_provider
54
from openfeature.evaluation_context import EvaluationContext
65
from openfeature.event import ProviderEvent, ProviderEventDetails
76
from openfeature.flag_evaluation import FlagResolutionDetails
@@ -84,4 +83,6 @@ def emit_provider_stale(self, details: ProviderEventDetails) -> None:
8483
self.emit(ProviderEvent.PROVIDER_STALE, details)
8584

8685
def emit(self, event: ProviderEvent, details: ProviderEventDetails) -> None:
87-
run_handlers_for_provider(self, event, details)
86+
from openfeature.provider._registry import default_registry
87+
88+
default_registry.dispatch_event(self, event, details)

tests/test_api.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from openfeature.event import EventDetails, ProviderEvent, ProviderEventDetails
2121
from openfeature.exception import ErrorCode, GeneralError
2222
from openfeature.hook import Hook
23-
from openfeature.provider import FeatureProvider, Metadata
23+
from openfeature.provider import FeatureProvider, Metadata, ProviderStatus
2424
from openfeature.provider.no_op_provider import NoOpProvider
2525

2626

@@ -313,3 +313,32 @@ def test_provider_ready_handlers_run_if_provider_initialize_function_terminates_
313313

314314
# Then
315315
spy.provider_ready.assert_called_once()
316+
317+
318+
def test_provider_status_is_updated_after_provider_emits_event():
319+
# Given
320+
provider = NoOpProvider()
321+
set_provider(provider)
322+
client = get_client()
323+
324+
# When
325+
provider.emit_provider_error(ProviderEventDetails(error_code=ErrorCode.GENERAL))
326+
# Then
327+
assert client.get_provider_status() == ProviderStatus.ERROR
328+
329+
# When
330+
provider.emit_provider_error(
331+
ProviderEventDetails(error_code=ErrorCode.PROVIDER_FATAL)
332+
)
333+
# Then
334+
assert client.get_provider_status() == ProviderStatus.FATAL
335+
336+
# When
337+
provider.emit_provider_stale(ProviderEventDetails())
338+
# Then
339+
assert client.get_provider_status() == ProviderStatus.STALE
340+
341+
# When
342+
provider.emit_provider_ready(ProviderEventDetails())
343+
# Then
344+
assert client.get_provider_status() == ProviderStatus.READY

0 commit comments

Comments
 (0)