diff --git a/devops/Dockerfile b/devops/Dockerfile index 602ba59bd..7b56ec7be 100644 --- a/devops/Dockerfile +++ b/devops/Dockerfile @@ -3,16 +3,13 @@ WORKDIR /src COPY . /src RUN npm ci && npm run build -FROM tiangolo/meinheld-gunicorn:python3.8 +FROM tiangolo/meinheld-gunicorn:python3.7 LABEL org.opencontainers.image.source=https://github.com/cmu-delphi/delphi-epidata # use delphi's timezome RUN ln -s -f /usr/share/zoneinfo/America/New_York /etc/localtime -COPY requirements.txt /app/requirements_also.txt -RUN pip install --no-cache-dir -r /tmp/requirements.txt -r requirements_also.txt -# the file /tmp/requirements.txt is created in the parent docker definition. (see: -# https://github.com/tiangolo/meinheld-gunicorn-docker/blob/master/docker-images/python3.8.dockerfile#L5 ) -# this combined requirements installation ensures all version constrants are accounted for. +COPY requirements.txt /app +RUN pip install --no-cache-dir -r requirements.txt # disable python stdout buffering ENV PYTHONUNBUFFERED 1 diff --git a/requirements.txt b/requirements.txt index 95f103acc..f94c98dc3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,8 @@ itsdangerous<2.1 jinja2==3.0.3 -werkzeug==2.2.2 -Flask==2.2.2 -SQLAlchemy==1.4.40 +werkzeug<2.1 +Flask==1.1.2 +SQLAlchemy==1.3.22 mysqlclient==2.0.2 python-dotenv==0.15.0 orjson==3.4.7 diff --git a/src/server/_config.py b/src/server/_config.py index 8d6f3723b..f14ed3bb3 100644 --- a/src/server/_config.py +++ b/src/server/_config.py @@ -11,16 +11,7 @@ MAX_COMPATIBILITY_RESULTS = int(3650) SQLALCHEMY_DATABASE_URI = os.environ.get("SQLALCHEMY_DATABASE_URI", "sqlite:///test.db") - -# defaults -SQLALCHEMY_ENGINE_OPTIONS = { - "pool_pre_ping": True, # enable ping test for validity of recycled pool connections on connect() calls - "pool_recycle": 5 # seconds after which a recycled pool connection is considered invalid -} -# update with overrides of defaults or additions from external configs -SQLALCHEMY_ENGINE_OPTIONS.update( - json.loads(os.environ.get("SQLALCHEMY_ENGINE_OPTIONS", "{}"))) - +SQLALCHEMY_ENGINE_OPTIONS = json.loads(os.environ.get("SQLALCHEMY_ENGINE_OPTIONS", "{}")) SECRET = os.environ.get("FLASK_SECRET", "secret") URL_PREFIX = os.environ.get("FLASK_PREFIX", "/") diff --git a/src/server/_query.py b/src/server/_query.py index 1cce5d2d5..bd1b37270 100644 --- a/src/server/_query.py +++ b/src/server/_query.py @@ -14,7 +14,7 @@ ) from sqlalchemy import text -from sqlalchemy.engine import Row +from sqlalchemy.engine import RowProxy from ._common import db, app from ._db import metadata @@ -197,7 +197,7 @@ def filter_pair(pair: TimePair, i) -> str: def parse_row( - row: Row, + row: RowProxy, fields_string: Optional[Sequence[str]] = None, fields_int: Optional[Sequence[str]] = None, fields_float: Optional[Sequence[str]] = None, @@ -245,7 +245,7 @@ def run_query(p: APrinter, query_tuple: Tuple[str, Dict[str, Any]]): return db.execution_options(stream_results=True).execute(full_query, **params) -def _identity_transform(row: Dict[str, Any], _: Row) -> Dict[str, Any]: +def _identity_transform(row: Dict[str, Any], _: RowProxy) -> Dict[str, Any]: """ identity transform """ @@ -257,7 +257,7 @@ def execute_queries( fields_string: Sequence[str], fields_int: Sequence[str], fields_float: Sequence[str], - transform: Callable[[Dict[str, Any], Row], Dict[str, Any]] = _identity_transform, + transform: Callable[[Dict[str, Any], RowProxy], Dict[str, Any]] = _identity_transform, ): """ execute the given queries and return the response to send them @@ -317,7 +317,7 @@ def execute_query( fields_string: Sequence[str], fields_int: Sequence[str], fields_float: Sequence[str], - transform: Callable[[Dict[str, Any], Row], Dict[str, Any]] = _identity_transform, + transform: Callable[[Dict[str, Any], RowProxy], Dict[str, Any]] = _identity_transform, ): """ execute the given query and return the response to send it