Skip to content

Commit 296311f

Browse files
feat: warn that payload filtering has no effect with FDv2 (#518)
Documents and warns that `payload_filter_key` has no effect when the FDv2 data system is used. Closes [SDK-2973](https://launchdarkly.atlassian.net/browse/SDK-2973). - `Config.payload_filter_key` / `AsyncConfig.payload_filter_key` docs now state payload filtering is unsupported with FDv2 - FDv2 data system logs a warning at construction when a filter key is configured - FDv1 behavior is unchanged; the shared option is not deprecated, since FDv1 still supports it **Requirements** - [x] I have added test coverage for new or changed functionality - [x] I have followed the repository's [pull request submission guidelines](../blob/main/CONTRIBUTING.md#submitting-pull-requests) - [x] I have validated my changes against all supported platform versions **Related issues** [SDK-2973](https://launchdarkly.atlassian.net/browse/SDK-2973), part of [SDK-2575](https://launchdarkly.atlassian.net/browse/SDK-2575). Same change as java-core#209 and go-server-sdk#440, adapted for the shared option. <details> <summary>Implementation details</summary> Unlike Go and Java, Python has no FDv2-specific filter setter — `payload_filter_key` is a top-level option shared by FDv1 and FDv2 — so it cannot be deprecated at the language level without also deprecating supported FDv1 usage. Instead the docstrings call out the FDv2 limitation and `FDv2.__init__` warns once when the option is set. The FDv2 data sources still append `?filter=` to `/sdk/poll` and `/sdk/stream` requests. That is intentional for now: on the delivery side, FDv2 (`internal/fdcore` in `streamer`) reads the `filter` query param only for observability (`fdrequest.Info.HasPayloadFilter`, surfaced as a dogfood context attribute) and never uses it to select a payload, so the parameter is inert rather than harmful. Dropping it would also break the `environment_filter_key` contract-test scenarios that the pinned harness (`v3.0.0-alpha.6`) still runs, requiring suppressions until the harness pin is bumped past sdk-test-harness#431. Removing the parameter belongs with that bump in the removal phase. Testing: `make lint`, `make test` (1420 passed). </details> Link to Devin session: https://app.devin.ai/sessions/ed604c6db94d452ea9f2dc35d6acc398 Open in Devin Desktop: https://app.devin.ai/desktop/session/ed604c6db94d452ea9f2dc35d6acc398?variant=devin Requested by: @beekld [SDK-2973]: https://launchdarkly.atlassian.net/browse/SDK-2973?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [SDK-2973]: https://launchdarkly.atlassian.net/browse/SDK-2973?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [SDK-2575]: https://launchdarkly.atlassian.net/browse/SDK-2575?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Overview** > Clarifies that **`payload_filter_key`** still applies to default FDv1 streaming/polling, but **does not filter FDv2** payloads. > > **`Config`** and **`AsyncConfig`** docstrings (constructor param and `payload_filter_key` property) now state that filtering is unsupported with the FDv2 data system. **`FDv2`** and **`AsyncFDv2`** emit a one-time **warning at construction** when a filter key is set, without changing runtime behavior or deprecating the shared option for FDv1. > > Tests assert the warning appears when a filter key is configured and is absent when it is not, for both sync and async FDv2. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit eaa3d72. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent 514c467 commit 296311f

6 files changed

Lines changed: 46 additions & 2 deletions

File tree

‎ldclient/async_config.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ def __init__(
245245
:param plugins: A list of plugins to be used with the SDK. Plugin support is currently experimental and subject to change.
246246
:param enable_event_compression: Whether or not to enable GZIP compression for outgoing events.
247247
:param omit_anonymous_contexts: Sets whether anonymous contexts should be omitted from index and identify events.
248-
:param payload_filter_key: The payload filter is used to selectively limited the flags and segments delivered in the data source payload.
248+
:param payload_filter_key: The payload filter is used to selectively limited the flags and segments delivered in the data source payload. Payload filtering is not supported with the FDv2 data system, so this has no effect on FDv2 requests.
249249
:param datasystem_config: Configuration for the upcoming enhanced data system design. This is experimental and should not be set without direction from LaunchDarkly support.
250250
"""
251251
self.__sdk_key = validate_sdk_key_format(sdk_key, log)
@@ -476,6 +476,9 @@ def payload_filter_key(self) -> Optional[str]:
476476
polling data sources. It will not affect TestData or FileData data
477477
sources, nor will it be applied to any data source provided through the
478478
{#data_source} config property.
479+
480+
Payload filtering is not supported with the FDv2 data system, so this
481+
key has no effect on requests made by FDv2 data sources.
479482
"""
480483
return self.__payload_filter_key
481484

‎ldclient/config.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ def __init__(
391391
:param plugins: A list of plugins to be used with the SDK. Plugin support is currently experimental and subject to change.
392392
:param enable_event_compression: Whether or not to enable GZIP compression for outgoing events.
393393
:param omit_anonymous_contexts: Sets whether anonymous contexts should be omitted from index and identify events.
394-
:param payload_filter_key: The payload filter is used to selectively limited the flags and segments delivered in the data source payload.
394+
:param payload_filter_key: The payload filter is used to selectively limited the flags and segments delivered in the data source payload. Payload filtering is not supported with the FDv2 data system, so this has no effect on FDv2 requests.
395395
:param datasystem_config: Configuration for the upcoming enhanced data system design. This is experimental and should not be set without direction from LaunchDarkly support.
396396
"""
397397
self.__sdk_key = validate_sdk_key_format(sdk_key, log)
@@ -681,6 +681,9 @@ def payload_filter_key(self) -> Optional[str]:
681681
polling data sources. It will not affect TestData or FileData data
682682
sources, nor will it be applied to any data source provided through the
683683
{#data_source} config property.
684+
685+
Payload filtering is not supported with the FDv2 data system, so this
686+
key has no effect on requests made by FDv2 data sources.
684687
"""
685688
return self.__payload_filter_key
686689

‎ldclient/impl/datasystem/async_fdv2.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ def __init__(
247247

248248
self._config = config
249249
self._data_system_config = data_system_config
250+
251+
if config.payload_filter_key is not None:
252+
log.warning("Payload filtering is not supported with the FDv2 data system; the configured payload filter has no effect on FDv2 requests")
253+
250254
self._synchronizers: List[DataSourceBuilder[AsyncSynchronizer]] = list(data_system_config.synchronizers) if data_system_config.synchronizers else []
251255
self._fdv1_fallback_synchronizer_builder = data_system_config.fdv1_fallback_synchronizer
252256
self._disabled = config.offline

‎ldclient/impl/datasystem/fdv2.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@ def __init__(
230230

231231
self._config = config
232232
self._data_system_config = data_system_config
233+
234+
if config.payload_filter_key is not None:
235+
log.warning("Payload filtering is not supported with the FDv2 data system; the configured payload filter has no effect on FDv2 requests")
236+
233237
self._synchronizers: List[DataSourceBuilder[Synchronizer]] = list(data_system_config.synchronizers) if data_system_config.synchronizers else []
234238
self._fdv1_fallback_synchronizer_builder = data_system_config.fdv1_fallback_synchronizer
235239
self._disabled = config.offline

‎ldclient/testing/impl/datasystem/test_async_fdv2.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# pylint: disable=missing-docstring
22

33
import asyncio
4+
import logging
45
from typing import Any, AsyncGenerator, Dict, List, Mapping, Optional
56

67
import pytest
@@ -778,3 +779,17 @@ async def test_successful_ops_pass_through():
778779
assert got is not None and got["key"] == "flag-a"
779780
allf = await wrapper.all(FEATURES)
780781
assert "flag-a" in allf
782+
783+
784+
def test_warns_when_payload_filter_key_is_configured(caplog):
785+
caplog.set_level(logging.WARNING, logger="ldclient.util")
786+
AsyncFDv2(AsyncConfig(sdk_key="dummy", payload_filter_key="microservice-1"), DataSystemConfig(initializers=None, synchronizers=None))
787+
788+
assert any("Payload filtering is not supported with the FDv2 data system" in record.message for record in caplog.records)
789+
790+
791+
def test_does_not_warn_when_payload_filter_key_is_not_configured(caplog):
792+
caplog.set_level(logging.WARNING, logger="ldclient.util")
793+
AsyncFDv2(AsyncConfig(sdk_key="dummy"), DataSystemConfig(initializers=None, synchronizers=None))
794+
795+
assert not any("Payload filtering" in record.message for record in caplog.records)

‎ldclient/testing/impl/datasystem/test_fdv2_datasystem.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# pylint: disable=missing-docstring
22

3+
import logging
34
import os
45
import tempfile
56
from threading import Event
@@ -846,3 +847,17 @@ def test_environment_id_is_not_recorded_from_non_valid_updates():
846847

847848
assert fdv2.environment_id == "env-from-sync"
848849
fdv2.stop()
850+
851+
852+
def test_warns_when_payload_filter_key_is_configured(caplog):
853+
caplog.set_level(logging.WARNING, logger="ldclient.util")
854+
FDv2(Config(sdk_key="dummy", payload_filter_key="microservice-1"), DataSystemConfig(initializers=None, synchronizers=None))
855+
856+
assert any("Payload filtering is not supported with the FDv2 data system" in record.message for record in caplog.records)
857+
858+
859+
def test_does_not_warn_when_payload_filter_key_is_not_configured(caplog):
860+
caplog.set_level(logging.WARNING, logger="ldclient.util")
861+
FDv2(Config(sdk_key="dummy"), DataSystemConfig(initializers=None, synchronizers=None))
862+
863+
assert not any("Payload filtering" in record.message for record in caplog.records)

0 commit comments

Comments
 (0)