From 126472d6f5bda3ded0f05ade0e219b9c55b2b0aa Mon Sep 17 00:00:00 2001 From: tokoko Date: Thu, 21 Mar 2024 05:04:34 +0000 Subject: [PATCH 1/4] fix: Run feature server w/o gunicorn on windows Signed-off-by: tokoko --- sdk/python/feast/feature_server.py | 57 +++++++++++++++++------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/sdk/python/feast/feature_server.py b/sdk/python/feast/feature_server.py index 618aefb2f28..becdcf851b8 100644 --- a/sdk/python/feast/feature_server.py +++ b/sdk/python/feast/feature_server.py @@ -1,10 +1,10 @@ import json +import sys import threading import traceback import warnings from typing import List, Optional -import gunicorn.app.base import pandas as pd from dateutil import parser from fastapi import FastAPI, HTTPException, Request, Response, status @@ -202,24 +202,27 @@ def materialize_incremental(body=Depends(get_body)): return app -class FeastServeApplication(gunicorn.app.base.BaseApplication): - def __init__(self, store: "feast.FeatureStore", **options): - self._app = get_app( - store=store, - registry_ttl_sec=options.get("registry_ttl_sec", 5), - ) - self._options = options - super().__init__() +if sys.platform != "win32": + import gunicorn.app.base - def load_config(self): - for key, value in self._options.items(): - if key.lower() in self.cfg.settings and value is not None: - self.cfg.set(key.lower(), value) + class FeastServeApplication(gunicorn.app.base.BaseApplication): + def __init__(self, store: "feast.FeatureStore", **options): + self._app = get_app( + store=store, + registry_ttl_sec=options.get("registry_ttl_sec", 5), + ) + self._options = options + super().__init__() - self.cfg.set("worker_class", "uvicorn.workers.UvicornWorker") + def load_config(self): + for key, value in self._options.items(): + if key.lower() in self.cfg.settings and value is not None: + self.cfg.set(key.lower(), value) - def load(self): - return self._app + self.cfg.set("worker_class", "uvicorn.workers.UvicornWorker") + + def load(self): + return self._app def start_server( @@ -231,11 +234,17 @@ def start_server( keep_alive_timeout: int, registry_ttl_sec: int = 5, ): - FeastServeApplication( - store=store, - bind=f"{host}:{port}", - accesslog=None if no_access_log else "-", - workers=workers, - keepalive=keep_alive_timeout, - registry_ttl_sec=registry_ttl_sec, - ).run() + if sys.platform != "win32": + FeastServeApplication( + store=store, + bind=f"{host}:{port}", + accesslog=None if no_access_log else "-", + workers=workers, + keepalive=keep_alive_timeout, + registry_ttl_sec=registry_ttl_sec, + ).run() + else: + import uvicorn + + app = get_app(store, registry_ttl_sec) + uvicorn.run(app, host=host, port=port, access_log=(not no_access_log)) From 96d415ad48bb51370f47e3015b640ea32a45e47d Mon Sep 17 00:00:00 2001 From: tokoko Date: Thu, 21 Mar 2024 05:47:38 +0000 Subject: [PATCH 2/4] skip gunicorn for windows in setup.py Signed-off-by: tokoko --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b32d03ed77c..455c835f83c 100644 --- a/setup.py +++ b/setup.py @@ -65,7 +65,7 @@ "typeguard>=4.0.0", "fastapi>=0.68.0", "uvicorn[standard]>=0.14.0,<1", - "gunicorn", + "gunicorn; platform_system != 'Windows'", # https://github.com/dask/dask/issues/10996 "dask>=2021.1.0,<2024.3.0", "bowler", # Needed for automatic repo upgrades From eee925cef45da4fba59e0e5a3054710ad53382f7 Mon Sep 17 00:00:00 2001 From: tokoko Date: Sat, 30 Mar 2024 10:57:15 +0000 Subject: [PATCH 3/4] pull default registry ttl to constants Signed-off-by: tokoko --- sdk/python/feast/constants.py | 3 +++ sdk/python/feast/feature_server.py | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sdk/python/feast/constants.py b/sdk/python/feast/constants.py index c022ecba557..e47da0ad6b7 100644 --- a/sdk/python/feast/constants.py +++ b/sdk/python/feast/constants.py @@ -49,3 +49,6 @@ # Environment variable for feature server docker image tag DOCKER_IMAGE_TAG_ENV_NAME: str = "FEAST_SERVER_DOCKER_IMAGE_TAG" + +# Default feature server registry ttl (seconds) +DEFAULT_FEATURE_SERVER_REGISTRY_TTL = 5 diff --git a/sdk/python/feast/feature_server.py b/sdk/python/feast/feature_server.py index becdcf851b8..2e2d4426fe1 100644 --- a/sdk/python/feast/feature_server.py +++ b/sdk/python/feast/feature_server.py @@ -15,6 +15,7 @@ import feast from feast import proto_json, utils +from feast.constants import DEFAULT_FEATURE_SERVER_REGISTRY_TTL from feast.data_source import PushMode from feast.errors import PushSourceNotFoundException from feast.protos.feast.serving.ServingService_pb2 import GetOnlineFeaturesRequest @@ -45,7 +46,10 @@ class MaterializeIncrementalRequest(BaseModel): feature_views: Optional[List[str]] = None -def get_app(store: "feast.FeatureStore", registry_ttl_sec: int = 5): +def get_app( + store: "feast.FeatureStore", + registry_ttl_sec: int = DEFAULT_FEATURE_SERVER_REGISTRY_TTL, +): proto_json.patch() app = FastAPI() @@ -209,7 +213,7 @@ class FeastServeApplication(gunicorn.app.base.BaseApplication): def __init__(self, store: "feast.FeatureStore", **options): self._app = get_app( store=store, - registry_ttl_sec=options.get("registry_ttl_sec", 5), + registry_ttl_sec=options["registry_ttl_sec"], ) self._options = options super().__init__() From e88eb656f38294ceaa81e2443c6ba29c0fbb5dff Mon Sep 17 00:00:00 2001 From: tokoko Date: Sat, 30 Mar 2024 11:21:39 +0000 Subject: [PATCH 4/4] remove default value from start_server as well Signed-off-by: tokoko --- sdk/python/feast/feature_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/python/feast/feature_server.py b/sdk/python/feast/feature_server.py index 2e2d4426fe1..4b0e50a06da 100644 --- a/sdk/python/feast/feature_server.py +++ b/sdk/python/feast/feature_server.py @@ -236,7 +236,7 @@ def start_server( no_access_log: bool, workers: int, keep_alive_timeout: int, - registry_ttl_sec: int = 5, + registry_ttl_sec: int, ): if sys.platform != "win32": FeastServeApplication(