Skip to content

Commit 84d0272

Browse files
committed
feat(provider): allow injecting custom cache to Unleash client
Signed-off-by: Kiki L Hakiem <[email protected]>
1 parent 048029b commit 84d0272

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed

providers/openfeature-provider-unleash/src/openfeature/contrib/provider/unleash/__init__.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import Any, Callable, Optional, Union
33

44
from UnleashClient import UnleashClient
5+
from UnleashClient.cache import BaseCache
56
from UnleashClient.events import BaseEvent, UnleashReadyEvent
67

78
from openfeature.evaluation_context import EvaluationContext
@@ -25,6 +26,8 @@ def __init__(
2526
app_name: str,
2627
api_token: str,
2728
environment: str = "development",
29+
fetch_toggles: bool = True,
30+
cache: Optional[BaseCache] = None,
2831
) -> None:
2932
"""Initialize the Unleash provider.
3033
@@ -33,11 +36,14 @@ def __init__(
3336
app_name: The application name
3437
api_token: The API token for authentication
3538
environment: The environment to connect to (default: "development")
39+
fetch_toggles: Whether to fetch toggles from server on initialization (default: True)
40+
cache: Optional cache implementation to use (default: UnleashClient's default)
3641
"""
3742
self.url = url
3843
self.app_name = app_name
3944
self.api_token = api_token
4045
self.environment = environment
46+
self.cache = cache
4147
self.client: Optional[UnleashClient] = None
4248
self._status = ProviderStatus.NOT_READY
4349
self._last_context: Optional[EvaluationContext] = None
@@ -50,6 +56,7 @@ def __init__(
5056
self._tracking_manager = Tracker(self)
5157
self._event_manager = EventManager(self)
5258
self._flag_evaluator = FlagEvaluator(self)
59+
self.fetch_toggles = fetch_toggles
5360

5461
def initialize(
5562
self, evaluation_context: Optional[EvaluationContext] = None
@@ -66,8 +73,9 @@ def initialize(
6673
environment=self.environment,
6774
custom_headers={"Authorization": self.api_token},
6875
event_callback=self._unleash_event_callback,
76+
cache=self.cache,
6977
)
70-
self.client.initialize_client()
78+
self.client.initialize_client(fetch_toggles=self.fetch_toggles)
7179
self._status = ProviderStatus.READY
7280
self._event_manager.emit_event(ProviderEvent.PROVIDER_READY)
7381
except Exception as e:

providers/openfeature-provider-unleash/tests/test_provider.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,32 @@
55
from openfeature.provider import ProviderStatus
66

77

8+
# Mock feature response for testing cache functionality
9+
MOCK_FEATURE_RESPONSE = {
10+
"version": 1,
11+
"features": [
12+
{
13+
"name": "testFlag",
14+
"description": "This is a test!",
15+
"enabled": True,
16+
"strategies": [{"name": "default", "parameters": {}}],
17+
"createdAt": "2018-10-04T01:27:28.477Z",
18+
"impressionData": True,
19+
},
20+
{
21+
"name": "testFlag2",
22+
"description": "Test flag 2",
23+
"enabled": False,
24+
"strategies": [
25+
{"name": "gradualRolloutRandom", "parameters": {"percentage": "50"}}
26+
],
27+
"createdAt": "2018-10-04T11:03:56.062Z",
28+
"impressionData": False,
29+
},
30+
],
31+
}
32+
33+
834
def test_unleash_provider_import():
935
"""Test that UnleashProvider can be imported."""
1036
assert UnleashProvider is not None
@@ -160,3 +186,49 @@ def test_unleash_provider_flag_metadata():
160186
assert result.flag_metadata["app_name"] == "test-app"
161187

162188
provider.shutdown()
189+
190+
191+
def test_unleash_provider_with_custom_cache():
192+
"""Test that UnleashProvider properly uses a custom cache with mocked features."""
193+
from UnleashClient.cache import FileCache
194+
195+
# Create a custom cache with mocked features
196+
custom_cache = FileCache("test-app")
197+
custom_cache.bootstrap_from_dict(MOCK_FEATURE_RESPONSE)
198+
199+
# Create provider with custom cache
200+
provider = UnleashProvider(
201+
url="http://localhost:4242",
202+
app_name="test-app",
203+
api_token="test-token",
204+
cache=custom_cache,
205+
fetch_toggles=False,
206+
)
207+
208+
# Verify cache was stored
209+
assert provider.cache is custom_cache
210+
211+
# Initialize the provider with fetch_toggles=False to prevent server connection
212+
provider.initialize()
213+
214+
# Verify the provider is ready
215+
assert provider.get_status() == ProviderStatus.READY
216+
assert provider.client is not None
217+
218+
# Test flag evaluation using the cached features
219+
# testFlag should be enabled (True in mock data)
220+
result = provider.resolve_boolean_details("testFlag", False)
221+
assert result.value is True
222+
assert result.reason.value == "TARGETING_MATCH"
223+
224+
# testFlag2 should be disabled (False in mock data)
225+
result = provider.resolve_boolean_details("testFlag2", True)
226+
assert result.value is False
227+
assert result.reason.value == "DEFAULT"
228+
229+
# Test string resolution with default value for non-existent flag
230+
result = provider.resolve_string_details("nonExistentFlag", "default_value")
231+
assert result.value == "default_value"
232+
assert result.reason.value == "DEFAULT"
233+
234+
provider.shutdown()

0 commit comments

Comments
 (0)