Skip to content

Commit fa600fe

Browse files
authored
feat: Add materialize and materialize-incremental rest endpoints (#3761)
* resolve #3760 Signed-off-by: snowron <snowronark@gmail.com> * format feature_server.py Signed-off-by: snowron <snowronark@gmail.com> --------- Signed-off-by: snowron <snowronark@gmail.com>
1 parent 709c709 commit fa600fe

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

sdk/python/feast/feature_server.py

+42-1
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import json
22
import traceback
33
import warnings
4+
from typing import List, Optional
45

56
import gunicorn.app.base
67
import pandas as pd
8+
from dateutil import parser
79
from fastapi import FastAPI, HTTPException, Request, Response, status
810
from fastapi.logger import logger
911
from fastapi.params import Depends
1012
from google.protobuf.json_format import MessageToDict, Parse
1113
from pydantic import BaseModel
1214

1315
import feast
14-
from feast import proto_json
16+
from feast import proto_json, utils
1517
from feast.data_source import PushMode
1618
from feast.errors import PushSourceNotFoundException
1719
from feast.protos.feast.serving.ServingService_pb2 import GetOnlineFeaturesRequest
@@ -31,6 +33,17 @@ class PushFeaturesRequest(BaseModel):
3133
to: str = "online"
3234

3335

36+
class MaterializeRequest(BaseModel):
37+
start_ts: str
38+
end_ts: str
39+
feature_views: Optional[List[str]] = None
40+
41+
42+
class MaterializeIncrementalRequest(BaseModel):
43+
end_ts: str
44+
feature_views: Optional[List[str]] = None
45+
46+
3447
def get_app(store: "feast.FeatureStore"):
3548
proto_json.patch()
3649

@@ -134,6 +147,34 @@ def write_to_online_store(body=Depends(get_body)):
134147
def health():
135148
return Response(status_code=status.HTTP_200_OK)
136149

150+
@app.post("/materialize")
151+
def materialize(body=Depends(get_body)):
152+
try:
153+
request = MaterializeRequest(**json.loads(body))
154+
store.materialize(
155+
utils.make_tzaware(parser.parse(request.start_ts)),
156+
utils.make_tzaware(parser.parse(request.end_ts)),
157+
request.feature_views,
158+
)
159+
except Exception as e:
160+
# Print the original exception on the server side
161+
logger.exception(traceback.format_exc())
162+
# Raise HTTPException to return the error message to the client
163+
raise HTTPException(status_code=500, detail=str(e))
164+
165+
@app.post("/materialize-incremental")
166+
def materialize_incremental(body=Depends(get_body)):
167+
try:
168+
request = MaterializeIncrementalRequest(**json.loads(body))
169+
store.materialize_incremental(
170+
utils.make_tzaware(parser.parse(request.end_ts)), request.feature_views
171+
)
172+
except Exception as e:
173+
# Print the original exception on the server side
174+
logger.exception(traceback.format_exc())
175+
# Raise HTTPException to return the error message to the client
176+
raise HTTPException(status_code=500, detail=str(e))
177+
137178
return app
138179

139180

0 commit comments

Comments
 (0)