11import json
2+ import sys
23import threading
34import traceback
45import warnings
56from typing import List , Optional
67
7- import gunicorn .app .base
88import pandas as pd
99from dateutil import parser
1010from fastapi import FastAPI , HTTPException , Request , Response , status
1515
1616import feast
1717from feast import proto_json , utils
18+ from feast .constants import DEFAULT_FEATURE_SERVER_REGISTRY_TTL
1819from feast .data_source import PushMode
1920from feast .errors import PushSourceNotFoundException
2021from feast .protos .feast .serving .ServingService_pb2 import GetOnlineFeaturesRequest
@@ -45,7 +46,10 @@ class MaterializeIncrementalRequest(BaseModel):
4546 feature_views : Optional [List [str ]] = None
4647
4748
48- def get_app (store : "feast.FeatureStore" , registry_ttl_sec : int = 5 ):
49+ def get_app (
50+ store : "feast.FeatureStore" ,
51+ registry_ttl_sec : int = DEFAULT_FEATURE_SERVER_REGISTRY_TTL ,
52+ ):
4953 proto_json .patch ()
5054
5155 app = FastAPI ()
@@ -202,24 +206,27 @@ def materialize_incremental(body=Depends(get_body)):
202206 return app
203207
204208
205- class FeastServeApplication (gunicorn .app .base .BaseApplication ):
206- def __init__ (self , store : "feast.FeatureStore" , ** options ):
207- self ._app = get_app (
208- store = store ,
209- registry_ttl_sec = options .get ("registry_ttl_sec" , 5 ),
210- )
211- self ._options = options
212- super ().__init__ ()
209+ if sys .platform != "win32" :
210+ import gunicorn .app .base
213211
214- def load_config (self ):
215- for key , value in self ._options .items ():
216- if key .lower () in self .cfg .settings and value is not None :
217- self .cfg .set (key .lower (), value )
212+ class FeastServeApplication (gunicorn .app .base .BaseApplication ):
213+ def __init__ (self , store : "feast.FeatureStore" , ** options ):
214+ self ._app = get_app (
215+ store = store ,
216+ registry_ttl_sec = options ["registry_ttl_sec" ],
217+ )
218+ self ._options = options
219+ super ().__init__ ()
220+
221+ def load_config (self ):
222+ for key , value in self ._options .items ():
223+ if key .lower () in self .cfg .settings and value is not None :
224+ self .cfg .set (key .lower (), value )
218225
219- self .cfg .set ("worker_class" , "uvicorn.workers.UvicornWorker" )
226+ self .cfg .set ("worker_class" , "uvicorn.workers.UvicornWorker" )
220227
221- def load (self ):
222- return self ._app
228+ def load (self ):
229+ return self ._app
223230
224231
225232def start_server (
@@ -229,13 +236,19 @@ def start_server(
229236 no_access_log : bool ,
230237 workers : int ,
231238 keep_alive_timeout : int ,
232- registry_ttl_sec : int = 5 ,
239+ registry_ttl_sec : int ,
233240):
234- FeastServeApplication (
235- store = store ,
236- bind = f"{ host } :{ port } " ,
237- accesslog = None if no_access_log else "-" ,
238- workers = workers ,
239- keepalive = keep_alive_timeout ,
240- registry_ttl_sec = registry_ttl_sec ,
241- ).run ()
241+ if sys .platform != "win32" :
242+ FeastServeApplication (
243+ store = store ,
244+ bind = f"{ host } :{ port } " ,
245+ accesslog = None if no_access_log else "-" ,
246+ workers = workers ,
247+ keepalive = keep_alive_timeout ,
248+ registry_ttl_sec = registry_ttl_sec ,
249+ ).run ()
250+ else :
251+ import uvicorn
252+
253+ app = get_app (store , registry_ttl_sec )
254+ uvicorn .run (app , host = host , port = port , access_log = (not no_access_log ))
0 commit comments