Skip to content

Commit e714b16

Browse files
pyalexadchia
authored andcommitted
fix: Random port allocation for python server in tests (#2710)
Signed-off-by: Oleksii Moskalenko <[email protected]>
1 parent d3028e5 commit e714b16

File tree

3 files changed

+31
-31
lines changed

3 files changed

+31
-31
lines changed

sdk/python/tests/conftest.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,19 @@ def pytest_generate_tests(metafunc: pytest.Metafunc):
273273

274274

275275
@pytest.fixture(scope="session")
276-
def python_server(environment):
277-
assert not _check_port_open("localhost", environment.get_local_server_port())
276+
def feature_server_endpoint(environment):
277+
if (
278+
not environment.python_feature_server
279+
or environment.test_repo_config.provider != "local"
280+
):
281+
yield environment.feature_store.get_feature_server_endpoint()
282+
return
283+
284+
port = _free_port()
278285

279286
proc = Process(
280287
target=start_test_local_server,
281-
args=(environment.feature_store.repo_path, environment.get_local_server_port()),
288+
args=(environment.feature_store.repo_path, port),
282289
)
283290
if (
284291
environment.python_feature_server
@@ -287,14 +294,10 @@ def python_server(environment):
287294
proc.start()
288295
# Wait for server to start
289296
wait_retry_backoff(
290-
lambda: (
291-
None,
292-
_check_port_open("localhost", environment.get_local_server_port()),
293-
),
294-
timeout_secs=10,
297+
lambda: (None, _check_port_open("localhost", port)), timeout_secs=10,
295298
)
296299

297-
yield
300+
yield f"http://localhost:{port}"
298301

299302
if proc.is_alive():
300303
proc.kill()
@@ -314,6 +317,12 @@ def _check_port_open(host, port) -> bool:
314317
return sock.connect_ex((host, port)) == 0
315318

316319

320+
def _free_port():
321+
sock = socket.socket()
322+
sock.bind(("", 0))
323+
return sock.getsockname()[1]
324+
325+
317326
@pytest.fixture(scope="session")
318327
def universal_data_sources(environment) -> TestData:
319328
return construct_universal_test_data(environment)

sdk/python/tests/integration/feature_repos/repo_configuration.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import importlib
33
import json
44
import os
5-
import re
65
import tempfile
76
import uuid
87
from dataclasses import dataclass
@@ -328,29 +327,10 @@ class Environment:
328327
worker_id: str
329328
online_store_creator: Optional[OnlineStoreCreator] = None
330329

331-
next_id = 0
332-
333330
def __post_init__(self):
334331
self.end_date = datetime.utcnow().replace(microsecond=0, second=0, minute=0)
335332
self.start_date: datetime = self.end_date - timedelta(days=3)
336333

337-
Environment.next_id += 1
338-
self.id = Environment.next_id
339-
340-
def get_feature_server_endpoint(self) -> str:
341-
if self.python_feature_server and self.test_repo_config.provider == "local":
342-
return f"http://localhost:{self.get_local_server_port()}"
343-
return self.feature_store.get_feature_server_endpoint()
344-
345-
def get_local_server_port(self) -> int:
346-
# Heuristic when running with xdist to extract unique ports for each worker
347-
parsed_worker_id = re.findall("gw(\\d+)", self.worker_id)
348-
if len(parsed_worker_id) != 0:
349-
worker_id_num = int(parsed_worker_id[0])
350-
else:
351-
worker_id_num = 0
352-
return 6000 + 100 * worker_id_num + self.id
353-
354334

355335
def table_name_from_data_source(ds: DataSource) -> Optional[str]:
356336
if hasattr(ds, "table_ref"):

sdk/python/tests/integration/online_store/test_universal_online.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ def _get_online_features_dict_remotely(
288288

289289
def get_online_features_dict(
290290
environment: Environment,
291+
endpoint: str,
291292
features: Union[List[str], FeatureService],
292293
entity_rows: List[Dict[str, Any]],
293294
full_feature_names: bool = False,
@@ -305,7 +306,6 @@ def get_online_features_dict(
305306
assertpy.assert_that(online_features).is_not_none()
306307
dict1 = online_features.to_dict()
307308

308-
endpoint = environment.get_feature_server_endpoint()
309309
# If endpoint is None, it means that a local / remote feature server aren't configured
310310
if endpoint is not None:
311311
dict2 = _get_online_features_dict_remotely(
@@ -447,7 +447,7 @@ def test_online_retrieval_with_event_timestamps(
447447
@pytest.mark.goserver
448448
@pytest.mark.parametrize("full_feature_names", [True, False], ids=lambda v: str(v))
449449
def test_online_retrieval(
450-
environment, universal_data_sources, python_server, full_feature_names
450+
environment, universal_data_sources, feature_server_endpoint, full_feature_names
451451
):
452452
fs = environment.feature_store
453453
entities, datasets, data_sources = universal_data_sources
@@ -547,6 +547,7 @@ def test_online_retrieval(
547547

548548
online_features_dict = get_online_features_dict(
549549
environment=environment,
550+
endpoint=feature_server_endpoint,
550551
features=feature_refs,
551552
entity_rows=entity_rows,
552553
full_feature_names=full_feature_names,
@@ -556,6 +557,7 @@ def test_online_retrieval(
556557
# feature isn't requested.
557558
online_features_no_conv_rate = get_online_features_dict(
558559
environment=environment,
560+
endpoint=feature_server_endpoint,
559561
features=[ref for ref in feature_refs if ref != "driver_stats:conv_rate"],
560562
entity_rows=entity_rows,
561563
full_feature_names=full_feature_names,
@@ -616,6 +618,7 @@ def test_online_retrieval(
616618
# Check what happens for missing values
617619
missing_responses_dict = get_online_features_dict(
618620
environment=environment,
621+
endpoint=feature_server_endpoint,
619622
features=feature_refs,
620623
entity_rows=[{"driver_id": 0, "customer_id": 0, "val_to_add": 100}],
621624
full_feature_names=full_feature_names,
@@ -635,13 +638,15 @@ def test_online_retrieval(
635638
with pytest.raises(RequestDataNotFoundInEntityRowsException):
636639
get_online_features_dict(
637640
environment=environment,
641+
endpoint=feature_server_endpoint,
638642
features=feature_refs,
639643
entity_rows=[{"driver_id": 0, "customer_id": 0}],
640644
full_feature_names=full_feature_names,
641645
)
642646

643647
assert_feature_service_correctness(
644648
environment,
649+
feature_server_endpoint,
645650
feature_service,
646651
entity_rows,
647652
full_feature_names,
@@ -659,6 +664,7 @@ def test_online_retrieval(
659664
]
660665
assert_feature_service_entity_mapping_correctness(
661666
environment,
667+
feature_server_endpoint,
662668
feature_service_entity_mapping,
663669
entity_rows,
664670
full_feature_names,
@@ -856,6 +862,7 @@ def get_latest_feature_values_for_location_df(entity_row, origin_df, destination
856862

857863
def assert_feature_service_correctness(
858864
environment,
865+
endpoint,
859866
feature_service,
860867
entity_rows,
861868
full_feature_names,
@@ -866,6 +873,7 @@ def assert_feature_service_correctness(
866873
):
867874
feature_service_online_features_dict = get_online_features_dict(
868875
environment=environment,
876+
endpoint=endpoint,
869877
features=feature_service,
870878
entity_rows=entity_rows,
871879
full_feature_names=full_feature_names,
@@ -905,6 +913,7 @@ def assert_feature_service_correctness(
905913

906914
def assert_feature_service_entity_mapping_correctness(
907915
environment,
916+
endpoint,
908917
feature_service,
909918
entity_rows,
910919
full_feature_names,
@@ -914,6 +923,7 @@ def assert_feature_service_entity_mapping_correctness(
914923
if full_feature_names:
915924
feature_service_online_features_dict = get_online_features_dict(
916925
environment=environment,
926+
endpoint=endpoint,
917927
features=feature_service,
918928
entity_rows=entity_rows,
919929
full_feature_names=full_feature_names,
@@ -948,6 +958,7 @@ def assert_feature_service_entity_mapping_correctness(
948958
with pytest.raises(FeatureNameCollisionError):
949959
get_online_features_dict(
950960
environment=environment,
961+
endpoint=endpoint,
951962
features=feature_service,
952963
entity_rows=entity_rows,
953964
full_feature_names=full_feature_names,

0 commit comments

Comments
 (0)