Skip to content

Commit 8abbcd9

Browse files
robhowleyRob Howley
authored andcommitted
fix: Return 422 on bad push source name (#3214)
* return 422 on bad push source name Signed-off-by: Rob Howley <rhowley@seatgeek.com> * fix: cant send empty df Signed-off-by: Rob Howley <rhowley@seatgeek.com> * return 422 on bad push source name Signed-off-by: Rob Howley <rhowley@seatgeek.com> * fix: cant send empty df Signed-off-by: Rob Howley <rhowley@seatgeek.com> * fix: json.dumps the body in the post 🤦 Signed-off-by: Rob Howley <rhowley@seatgeek.com> Signed-off-by: Rob Howley <rhowley@seatgeek.com> Co-authored-by: Rob Howley <rhowley@seatgeek.com>
1 parent fdc8d67 commit 8abbcd9

File tree

4 files changed

+38
-0
lines changed

4 files changed

+38
-0
lines changed

sdk/python/feast/errors.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,3 +398,8 @@ def __init__(self):
398398
super().__init__(
399399
"The entity dataframe specified does not have the timestamp field as a datetime."
400400
)
401+
402+
403+
class PushSourceNotFoundException(Exception):
404+
def __init__(self, push_source_name: str):
405+
super().__init__(f"Unable to find push source '{push_source_name}'.")

sdk/python/feast/feature_server.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import feast
1414
from feast import proto_json
1515
from feast.data_source import PushMode
16+
from feast.errors import PushSourceNotFoundException
1617
from feast.protos.feast.serving.ServingService_pb2 import GetOnlineFeaturesRequest
1718

1819

@@ -98,6 +99,11 @@ def push(body=Depends(get_body)):
9899
allow_registry_cache=request.allow_registry_cache,
99100
to=to,
100101
)
102+
except PushSourceNotFoundException as e:
103+
# Print the original exception on the server side
104+
logger.exception(traceback.format_exc())
105+
# Raise HTTPException to return the error message to the client
106+
raise HTTPException(status_code=422, detail=str(e))
101107
except Exception as e:
102108
# Print the original exception on the server side
103109
logger.exception(traceback.format_exc())

sdk/python/feast/feature_store.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
EntityNotFoundException,
6060
FeatureNameCollisionError,
6161
FeatureViewNotFoundException,
62+
PushSourceNotFoundException,
6263
RequestDataNotFoundInEntityDfException,
6364
RequestDataNotFoundInEntityRowsException,
6465
)
@@ -1445,6 +1446,9 @@ def push(
14451446
)
14461447
}
14471448

1449+
if not fvs_with_push_sources:
1450+
raise PushSourceNotFoundException(push_source_name)
1451+
14481452
for fv in fvs_with_push_sources:
14491453
if to == PushMode.ONLINE or to == PushMode.ONLINE_AND_OFFLINE:
14501454
self.write_to_online_store(

sdk/python/tests/integration/e2e/test_python_feature_server.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,29 @@ def test_push(python_fs_client):
8484
) == [initial_temp * 100]
8585

8686

87+
@pytest.mark.integration
88+
@pytest.mark.universal_online_stores
89+
def test_push_source_does_not_exist(python_fs_client):
90+
initial_temp = _get_temperatures_from_feature_server(
91+
python_fs_client, location_ids=[1]
92+
)[0]
93+
response = python_fs_client.post(
94+
"/push",
95+
data=json.dumps(
96+
{
97+
"push_source_name": "push_source_does_not_exist",
98+
"df": {
99+
"location_id": [1],
100+
"temperature": [initial_temp * 100],
101+
"event_timestamp": [str(datetime.utcnow())],
102+
"created": [str(datetime.utcnow())],
103+
},
104+
}
105+
),
106+
)
107+
assert response.status_code == 422
108+
109+
87110
def _get_temperatures_from_feature_server(client, location_ids: List[int]):
88111
get_request_data = {
89112
"features": ["pushable_location_stats:temperature"],

0 commit comments

Comments
 (0)