Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion providers/openfeature-provider-flagd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ The default options can be defined in the FlagdProvider constructor.
|--------------------------|--------------------------------|----------------------------|-------------------------------|---------------------|
| resolver_type | FLAGD_RESOLVER | enum - `rpc`, `in-process` | rpc | |
| host | FLAGD_HOST | str | localhost | rpc & in-process |
| port | FLAGD_PORT | int | 8013 (rpc), 8015 (in-process) | rpc & in-process |
| port | FLAGD_SYNC_PORT (in-process), FLAGD_PORT (rpc or fallback) | int | 8013 (rpc), 8015 (in-process) | rpc & in-process |
| tls | FLAGD_TLS | bool | false | rpc & in-process |
| cert_path | FLAGD_SERVER_CERT_PATH | String | null | rpc & in-process |
| deadline | FLAGD_DEADLINE_MS | int | 500 | rpc & in-process |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class CacheType(Enum):
ENV_VAR_OFFLINE_FLAG_SOURCE_PATH = "FLAGD_OFFLINE_FLAG_SOURCE_PATH"
ENV_VAR_OFFLINE_POLL_MS = "FLAGD_OFFLINE_POLL_MS"
ENV_VAR_PORT = "FLAGD_PORT"
ENV_VAR_SYNC_PORT = "FLAGD_SYNC_PORT"
ENV_VAR_RESOLVER_TYPE = "FLAGD_RESOLVER"
ENV_VAR_RETRY_BACKOFF_MS = "FLAGD_RETRY_BACKOFF_MS"
ENV_VAR_RETRY_BACKOFF_MAX_MS = "FLAGD_RETRY_BACKOFF_MAX_MS"
Expand Down Expand Up @@ -79,7 +80,7 @@ def env_or_default(

@dataclasses.dataclass
class Config:
def __init__( # noqa: PLR0913
def __init__( # noqa: PLR0913, PLR0915
self,
host: typing.Optional[str] = None,
port: typing.Optional[int] = None,
Expand Down Expand Up @@ -149,17 +150,27 @@ def __init__( # noqa: PLR0913
else resolver
)

default_port = (
DEFAULT_PORT_RPC
if self.resolver is ResolverType.RPC
else DEFAULT_PORT_IN_PROCESS
)

self.port: int = (
int(env_or_default(ENV_VAR_PORT, default_port, cast=int))
if port is None
else port
)
# Port configuration with FLAGD_SYNC_PORT support for in-process mode
if port is None:
if self.resolver is ResolverType.IN_PROCESS:
# For in-process: try FLAGD_SYNC_PORT first, then FLAGD_PORT (backwards compatibility), then default
sync_port_env = os.environ.get(ENV_VAR_SYNC_PORT)
if sync_port_env is not None:
self.port = int(sync_port_env)
else:
port_env = os.environ.get(ENV_VAR_PORT)
self.port = (
int(port_env)
if port_env is not None
else DEFAULT_PORT_IN_PROCESS
)
Comment on lines +155 to +166
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This logic for determining the port for the in-process resolver can be simplified. Using os.environ.get(...) or os.environ.get(...) can make the code more concise and easier to read by reducing nesting.

            if self.resolver is ResolverType.IN_PROCESS:
                # For in-process: try FLAGD_SYNC_PORT, then FLAGD_PORT (backwards compatibility), then default
                port_from_env = os.environ.get(ENV_VAR_SYNC_PORT) or os.environ.get(
                    ENV_VAR_PORT
                )
                self.port = (
                    int(port_from_env)
                    if port_from_env is not None
                    else DEFAULT_PORT_IN_PROCESS
                )

else:
# For RPC: use FLAGD_PORT only
self.port = int(
env_or_default(ENV_VAR_PORT, DEFAULT_PORT_RPC, cast=int)
)
else:
self.port = port

self.offline_flag_source_path = (
env_or_default(
Expand Down
54 changes: 54 additions & 0 deletions providers/openfeature-provider-flagd/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
ENV_VAR_PORT,
ENV_VAR_RETRY_BACKOFF_MS,
ENV_VAR_STREAM_DEADLINE_MS,
ENV_VAR_SYNC_PORT,
ENV_VAR_TLS,
CacheType,
Config,
Expand Down Expand Up @@ -147,3 +148,56 @@ def test_uses_arguments_over_environments_and_defaults(monkeypatch, resolver_typ
assert config.retry_backoff_ms == retry_backoff
assert config.stream_deadline_ms == stream_deadline
assert config.tls is tls


def test_in_process_uses_sync_port(monkeypatch):
"""Test that FLAGD_SYNC_PORT is used for in-process mode when set."""
sync_port = 9999
monkeypatch.setenv(ENV_VAR_SYNC_PORT, str(sync_port))

config = Config(resolver=ResolverType.IN_PROCESS)
assert config.port == sync_port
assert config.resolver == ResolverType.IN_PROCESS


def test_in_process_fallback_to_port(monkeypatch):
"""Test that FLAGD_PORT is used as fallback when FLAGD_SYNC_PORT is not set."""
port = 7777
monkeypatch.setenv(ENV_VAR_PORT, str(port))

config = Config(resolver=ResolverType.IN_PROCESS)
assert config.port == port
assert config.resolver == ResolverType.IN_PROCESS


def test_in_process_sync_port_priority(monkeypatch):
"""Test that FLAGD_SYNC_PORT takes priority over FLAGD_PORT when both are set."""
sync_port = 9999
port = 7777
monkeypatch.setenv(ENV_VAR_SYNC_PORT, str(sync_port))
monkeypatch.setenv(ENV_VAR_PORT, str(port))

config = Config(resolver=ResolverType.IN_PROCESS)
assert config.port == sync_port # FLAGD_SYNC_PORT should win
assert config.resolver == ResolverType.IN_PROCESS


def test_rpc_ignores_sync_port(monkeypatch):
"""Test that RPC mode uses FLAGD_PORT and ignores FLAGD_SYNC_PORT."""
sync_port = 9999
port = 7777
monkeypatch.setenv(ENV_VAR_SYNC_PORT, str(sync_port))
monkeypatch.setenv(ENV_VAR_PORT, str(port))

config = Config(resolver=ResolverType.RPC)
assert config.port == port # RPC should use FLAGD_PORT
assert config.resolver == ResolverType.RPC


def test_in_process_default_port_when_no_env_var(monkeypatch):
"""Test that in-process mode uses default port when neither env var is set."""
monkeypatch.delenv(ENV_VAR_SYNC_PORT, raising=False)
monkeypatch.delenv(ENV_VAR_PORT, raising=False)
config = Config(resolver=ResolverType.IN_PROCESS)
assert config.port == DEFAULT_PORT_IN_PROCESS
assert config.resolver == ResolverType.IN_PROCESS