Skip to content

Commit 6f6d595

Browse files
authored
fix: Offline handler not used as fallback for local evaluation mode during init (#100)
1 parent b179c83 commit 6f6d595

File tree

5 files changed

+46
-51
lines changed

5 files changed

+46
-51
lines changed

flagsmith/flagsmith.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,10 @@ def __init__(
159159
)
160160

161161
def _initialise_local_evaluation(self) -> None:
162+
# To ensure that the environment is set before allowing subsequent
163+
# method calls, update the environment manually.
164+
self.update_environment()
162165
if self.enable_realtime_updates:
163-
self.update_environment()
164166
if not self._environment:
165167
raise ValueError("Unable to get environment from API key")
166168

@@ -175,9 +177,6 @@ def _initialise_local_evaluation(self) -> None:
175177
self.event_stream_thread.start()
176178

177179
else:
178-
# To ensure that the environment is set before allowing subsequent
179-
# method calls, update the environment manually.
180-
self.update_environment()
181180
self.environment_data_polling_manager_thread = (
182181
EnvironmentDataPollingManager(
183182
main=self,
@@ -281,7 +280,10 @@ def get_identity_segments(
281280
return [Segment(id=sm.id, name=sm.name) for sm in segment_models]
282281

283282
def update_environment(self) -> None:
284-
self._environment = self._get_environment_from_api()
283+
try:
284+
self._environment = self._get_environment_from_api()
285+
except (FlagsmithAPIError, requests.RequestException):
286+
logger.exception("Error updating environment")
285287
self._update_overrides()
286288

287289
def _update_overrides(self) -> None:

flagsmith/polling_manager.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55
import time
66
import typing
77

8-
import requests
9-
10-
from flagsmith.exceptions import FlagsmithAPIError
11-
128
if typing.TYPE_CHECKING:
139
from flagsmith import Flagsmith
1410

@@ -30,10 +26,7 @@ def __init__(
3026

3127
def run(self) -> None:
3228
while not self._stop_event.is_set():
33-
try:
34-
self.main.update_environment()
35-
except (FlagsmithAPIError, requests.RequestException):
36-
logger.exception("Failed to update environment")
29+
self.main.update_environment()
3730
time.sleep(self.refresh_interval_seconds)
3831

3932
def stop(self) -> None:

flagsmith/streaming_manager.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
1-
import logging
21
import threading
32
import typing
43
from typing import Callable, Generator, Optional, Protocol, cast
54

65
import requests
76
import sseclient
87

9-
from flagsmith.exceptions import FlagsmithAPIError
10-
11-
logger = logging.getLogger(__name__)
12-
138

149
class StreamEvent(Protocol):
1510
data: str
@@ -48,9 +43,6 @@ def run(self) -> None:
4843
except requests.exceptions.ReadTimeout:
4944
pass
5045

51-
except (FlagsmithAPIError, requests.RequestException):
52-
logger.exception("Error handling event stream")
53-
5446
def stop(self) -> None:
5547
self._stop_event.set()
5648

tests/test_flagsmith.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,44 @@ def test_flagsmith_uses_offline_handler_if_set_and_no_api_response(
526526
assert identity_flags.get_feature_value("some_feature") == "some-value"
527527

528528

529+
@responses.activate()
530+
def test_offline_mode__local_evaluation__correct_fallback(
531+
mocker: MockerFixture,
532+
environment_model: EnvironmentModel,
533+
caplog: pytest.LogCaptureFixture,
534+
) -> None:
535+
# Given
536+
api_url = "http://some.flagsmith.com/api/v1/"
537+
mock_offline_handler = mocker.MagicMock(spec=BaseOfflineHandler)
538+
mock_offline_handler.get_environment.return_value = environment_model
539+
540+
flagsmith = Flagsmith(
541+
environment_key="ser.some-key",
542+
api_url=api_url,
543+
enable_local_evaluation=True,
544+
offline_handler=mock_offline_handler,
545+
)
546+
547+
responses.get(flagsmith.environment_url, status=500)
548+
549+
# When
550+
environment_flags = flagsmith.get_environment_flags()
551+
identity_flags = flagsmith.get_identity_flags("identity", traits={})
552+
553+
# Then
554+
mock_offline_handler.get_environment.assert_called_once_with()
555+
556+
assert environment_flags.is_feature_enabled("some_feature") is True
557+
assert environment_flags.get_feature_value("some_feature") == "some-value"
558+
559+
assert identity_flags.is_feature_enabled("some_feature") is True
560+
assert identity_flags.get_feature_value("some_feature") == "some-value"
561+
562+
[error_log_record] = caplog.records
563+
assert error_log_record.levelname == "ERROR"
564+
assert error_log_record.message == "Error updating environment"
565+
566+
529567
def test_cannot_use_offline_mode_without_offline_handler() -> None:
530568
with pytest.raises(ValueError) as e:
531569
# When

tests/test_streaming_manager.py

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -36,36 +36,6 @@ def test_stream_manager_handles_timeout(
3636
streaming_manager.stop()
3737

3838

39-
def test_stream_manager_handles_request_exception(
40-
mocked_responses: responses.RequestsMock,
41-
caplog: pytest.LogCaptureFixture,
42-
) -> None:
43-
stream_url = (
44-
"https://realtime.flagsmith.com/sse/environments/B62qaMZNwfiqT76p38ggrQ/stream"
45-
)
46-
47-
mocked_responses.get(stream_url, body=requests.RequestException())
48-
mocked_responses.get(stream_url, body=FlagsmithAPIError())
49-
50-
streaming_manager = EventStreamManager(
51-
stream_url=stream_url,
52-
on_event=MagicMock(),
53-
daemon=True,
54-
)
55-
56-
streaming_manager.start()
57-
58-
time.sleep(0.01)
59-
60-
assert streaming_manager.is_alive()
61-
62-
streaming_manager.stop()
63-
64-
for record in caplog.records:
65-
assert record.levelname == "ERROR"
66-
assert record.message == "Error handling event stream"
67-
68-
6939
def test_environment_updates_on_recent_event(
7040
server_api_key: str, mocker: MockerFixture
7141
) -> None:

0 commit comments

Comments
 (0)