refactor: bind providers explicitly to a registry with attach/detach (#324)

* test: make sure provider is registered in events test

Signed-off-by: Federico Bond <federicobond@gmail.com>

* refactor: bind providers explicitly to a registry with attach/detach

Signed-off-by: Federico Bond <federicobond@gmail.com>

---------

Signed-off-by: Federico Bond <federicobond@gmail.com>
This commit is contained in:
Federico Bond 2024-05-02 09:13:30 +10:00 committed by GitHub
parent f352045055
commit c3ad697a80
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 27 additions and 5 deletions

View File

@ -23,6 +23,15 @@ class ProviderStatus(Enum):
class FeatureProvider(typing.Protocol): # pragma: no cover
def attach(
self,
on_emit: typing.Callable[
[FeatureProvider, ProviderEvent, ProviderEventDetails], None
],
) -> None: ...
def detach(self) -> None: ...
def initialize(self, evaluation_context: EvaluationContext) -> None: ...
def shutdown(self) -> None: ...
@ -68,6 +77,18 @@ class FeatureProvider(typing.Protocol): # pragma: no cover
class AbstractProvider(FeatureProvider):
def attach(
self,
on_emit: typing.Callable[
[FeatureProvider, ProviderEvent, ProviderEventDetails], None
],
) -> None:
self._on_emit = on_emit
def detach(self) -> None:
if hasattr(self, "_on_emit"):
del self._on_emit
def initialize(self, evaluation_context: EvaluationContext) -> None:
pass
@ -141,6 +162,5 @@ class AbstractProvider(FeatureProvider):
self.emit(ProviderEvent.PROVIDER_STALE, details)
def emit(self, event: ProviderEvent, details: ProviderEventDetails) -> None:
from openfeature.provider._registry import provider_registry
provider_registry.dispatch_event(self, event, details)
if hasattr(self, "_on_emit"):
self._on_emit(self, event, details)

View File

@ -71,6 +71,7 @@ class ProviderRegistry:
return get_evaluation_context()
def _initialize_provider(self, provider: FeatureProvider) -> None:
provider.attach(self.dispatch_event)
try:
if hasattr(provider, "initialize"):
provider.initialize(self._get_evaluation_context())
@ -106,6 +107,7 @@ class ProviderRegistry:
error_code=ErrorCode.PROVIDER_FATAL,
),
)
provider.detach()
def get_provider_status(self, provider: FeatureProvider) -> ProviderStatus:
return self._provider_status.get(provider, ProviderStatus.NOT_READY)

View File

@ -235,6 +235,8 @@ def test_clear_providers_shutdowns_every_provider_and_resets_default_provider():
def test_provider_events():
# Given
spy = MagicMock()
provider = NoOpProvider()
set_provider(provider)
add_handler(ProviderEvent.PROVIDER_READY, spy.provider_ready)
add_handler(
@ -243,8 +245,6 @@ def test_provider_events():
add_handler(ProviderEvent.PROVIDER_ERROR, spy.provider_error)
add_handler(ProviderEvent.PROVIDER_STALE, spy.provider_stale)
provider = NoOpProvider()
provider_details = ProviderEventDetails(message="message")
details = EventDetails.from_provider_event_details(
provider.get_metadata().name, provider_details