diff --git a/polling_stations/db_routers.py b/polling_stations/db_routers.py index d48be011a..33174652d 100644 --- a/polling_stations/db_routers.py +++ b/polling_stations/db_routers.py @@ -2,21 +2,46 @@ from django.conf import settings from django.db import DEFAULT_DB_ALIAS +from django_middleware_global_request import get_request + + +PRINCIPAL = settings.PRINCIPAL_DB_NAME +REPLICA = DEFAULT_DB_ALIAS class ReplicationRouter(object): def db_for_read(self, model, **hints): + # In CI, there is only one DB connection + if os.environ.get("CIRCLECI"): + return DEFAULT_DB_ALIAS + + # We don't need to scale requests touching these models + # but we do want to prevent race conditions + # when reading a record we just wrote if model._meta.label in ( "file_uploads.Upload", "file_uploads.File", - ) and not os.environ.get("CIRCLECI"): - return settings.PRINCIPAL_DB_NAME - return DEFAULT_DB_ALIAS + ): + return PRINCIPAL + + # We only care about trying to scale + # by serving traffic from a replica + # when we are serving HTTP traffic + request = get_request() + if request: + if request.path.startswith("/admin"): + return PRINCIPAL + return REPLICA + + # in all other cases (e.g: management commands, shell) + # perform reads from the principal to prevent race conditions + return PRINCIPAL def db_for_write(self, model, **hints): if os.environ.get("CIRCLECI"): return DEFAULT_DB_ALIAS - return settings.PRINCIPAL_DB_NAME + + return PRINCIPAL def allow_relation(self, obj1, obj2, **hints): return True @@ -26,6 +51,6 @@ def allow_migrate(self, db, app_label, model_name=None, **hints): def get_principal_db_name(): - if settings.PRINCIPAL_DB_NAME in settings.DATABASES: - return settings.PRINCIPAL_DB_NAME - return DEFAULT_DB_ALIAS + if PRINCIPAL in settings.DATABASES: + return PRINCIPAL + return REPLICA diff --git a/polling_stations/settings/base.py b/polling_stations/settings/base.py index 537ade11c..621cbe631 100644 --- a/polling_stations/settings/base.py +++ b/polling_stations/settings/base.py @@ -124,6 +124,7 @@ def get_ec2_ip(): MIDDLEWARE = ( "whitenoise.middleware.WhiteNoiseMiddleware", "corsheaders.middleware.CorsMiddleware", + "django_middleware_global_request.middleware.GlobalRequestMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.locale.LocaleMiddleware", @@ -197,6 +198,7 @@ def get_ec2_ip(): "dc_design_system", "dc_utils", "drf_spectacular", + "django_middleware_global_request", ) PROJECT_APPS = ( diff --git a/requirements/base.in b/requirements/base.in index 5d9b21cec..a57a33ebd 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -11,6 +11,7 @@ django-dotenv django-extensions django-filter django-localflavor +django-middleware-global-request django-sesame djangorestframework djangorestframework-csv diff --git a/requirements/base.txt b/requirements/base.txt index 33d982b0c..a01361534 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -198,6 +198,7 @@ django==4.2.13 \ # django-extensions # django-filter # django-localflavor + # django-middleware-global-request # django-sesame # djangorestframework # drf-spectacular @@ -233,6 +234,12 @@ django-localflavor==4.0 \ # -c requirements/constraints.txt # -r requirements/base.in # dc-django-utils +django-middleware-global-request==0.3.5 \ + --hash=sha256:37c79c9cd80e73751ae2821696e20af13ba7628a0915ff1818d124e0e72980b1 \ + --hash=sha256:7beb2c8ca9106aac641692cda2bac290bd7083a315446a12db06fa91b73903d6 + # via + # -c requirements/constraints.txt + # -r requirements/base.in django-pipeline==3.0.0 \ --hash=sha256:49a8bee298668100bb6e8a2144dff8c607baa5297820a2503793c38693f34103 \ --hash=sha256:e9e08b084ef3ebf599795510519a8d44f2240b487782bebf4a8fcaf6302c31d1 diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 6813c0b57..152c5ac9a 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -381,6 +381,7 @@ django==4.2.13 \ # django-extensions # django-filter # django-localflavor + # django-middleware-global-request # django-sesame # djangorestframework # drf-spectacular @@ -415,6 +416,10 @@ django-localflavor==4.0 \ # via # -r requirements/base.in # dc-django-utils +django-middleware-global-request==0.3.5 \ + --hash=sha256:37c79c9cd80e73751ae2821696e20af13ba7628a0915ff1818d124e0e72980b1 \ + --hash=sha256:7beb2c8ca9106aac641692cda2bac290bd7083a315446a12db06fa91b73903d6 + # via -r requirements/base.in django-pipeline==3.0.0 \ --hash=sha256:49a8bee298668100bb6e8a2144dff8c607baa5297820a2503793c38693f34103 \ --hash=sha256:e9e08b084ef3ebf599795510519a8d44f2240b487782bebf4a8fcaf6302c31d1