Skip to content

Commit

Permalink
add nginx + cache
Browse files Browse the repository at this point in the history
  • Loading branch information
fabienheureux committed Jan 23, 2025
1 parent 1e9d79f commit bc561f8
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 14 deletions.
3 changes: 2 additions & 1 deletion .buildpacks
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
https://github.com/Scalingo/apt-buildpack
https://github.com/Scalingo/nodejs-buildpack
https://github.com/Scalingo/python-buildpack
https://github.com/Scalingo/python-buildpack
https://github.com/Scalingo/nginx-buildpack.git
4 changes: 2 additions & 2 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
"filename": "core/settings.py",
"hashed_secret": "1ee34e26aeaf89c64ecc2c85efe6a961b75a50e9",
"is_verified": false,
"line_number": 220
"line_number": 219
}
],
"docker-compose.yml": [
Expand Down Expand Up @@ -207,5 +207,5 @@
}
]
},
"generated_at": "2025-01-14T12:14:14Z"
"generated_at": "2025-01-22T18:36:09Z"
}
2 changes: 1 addition & 1 deletion Aptfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
gdal-bin
libgdal-dev
libgdal-dev
1 change: 0 additions & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
web: bash bin/start
postdeploy: bash bin/post_deploy
4 changes: 2 additions & 2 deletions bin/post_compile
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ export PROJ_LIB=/build/${REQUEST_ID}/.apt/usr/share/proj
python manage.py collectstatic --noinput

# iframe.js file should be collected without hashing
cp static/compiled/iframe.js staticfiles/
cp static/compiled/carte.js staticfiles/
# cp static/compiled/iframe.js staticfiles/
# cp static/compiled/carte.js staticfiles/
11 changes: 9 additions & 2 deletions bin/start
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#!/bin/bash

#gunicorn --timeout 300 --workers 20 --chdir core core.wsgi --log-file -
#gunicorn core.asgi --worker-class=uvicorn.workers.UvicornWorker --max-requests 10000 --max-requests-jitter 20 --workers 5 --log-file -
gunicorn core.asgi --timeout 300 --worker-class=core.custom_uvicorn_worker.CustomUvicornWorker --max-requests 2000 --max-requests-jitter 200 --workers 3 --log-file -
bin/run & # nginx as a reverse proxy

# if the current shell is killed, also terminate all its children
trap "pkill SIGTERM -P $$" SIGTERM

# wait for a single child to finish,
wait -n
# then kill all the other tasks
pkill -P $$
14 changes: 10 additions & 4 deletions core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
DEBUG = decouple.config("DEBUG", default=False, cast=bool)
STIMULUS_DEBUG = decouple.config("STIMULUS_DEBUG", default=False, cast=bool)
POSTHOG_DEBUG = decouple.config("POSTHOG_DEBUG", default=False, cast=bool)

ALLOWED_HOSTS = decouple.config("ALLOWED_HOSTS", default="localhost", cast=str).split(
","
)
Expand Down Expand Up @@ -330,13 +329,16 @@ def context_processors():

SHELL_PLUS_PRINT_SQL = True

# Object storage with Scaleway
AWS_ACCESS_KEY_ID = decouple.config("AWS_ACCESS_KEY_ID", default="")
AWS_SECRET_ACCESS_KEY = decouple.config("AWS_SECRET_ACCESS_KEY", default="")
AWS_STORAGE_BUCKET_NAME = decouple.config("AWS_STORAGE_BUCKET_NAME", default="")
AWS_S3_REGION_NAME = decouple.config("AWS_S3_REGION_NAME", default="")
AWS_S3_ENDPOINT_URL = decouple.config("AWS_S3_ENDPOINT_URL", default="")

USE_S3_FOR_STATIC = (
decouple.config("USE_S3_FOR_STATIC", cast=bool, default=False) and AWS_ACCESS_KEY_ID
)
AWS_DEFAULT_ACL = "public-read"
AWS_QUERYSTRING_AUTH = False

STORAGES = {
"default": {
Expand All @@ -347,7 +349,11 @@ def context_processors():
),
},
"staticfiles": {
"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
"BACKEND": (
"storages.backends.s3.S3Storage"
if USE_S3_FOR_STATIC
else "whitenoise.storage.CompressedManifestStaticFilesStorage"
),
},
}

Expand Down
2 changes: 1 addition & 1 deletion qfdmd/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def get_assistant_script(request):
urlpatterns = [
path("dechet/", HomeView.as_view(), name="home"),
path("assistant/recherche", search_view, name="search"),
path("<slug:slug>/", SynonymeDetailView.as_view(), name="synonyme-detail"),
path("dechet/<slug:slug>/", SynonymeDetailView.as_view(), name="synonyme-detail"),
path("assistant/nous-contacter", ContactFormView.as_view(), name="nous-contacter"),
path(
"assistant/nous-contacter/confirmation",
Expand Down
22 changes: 22 additions & 0 deletions qfdmd/views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import logging
from functools import wraps
from typing import Any

from django.conf import settings
from django.http import HttpResponse
from django.shortcuts import render
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from django.views.generic import DetailView, FormView, ListView

from core.notion import create_new_row_in_notion_table
Expand Down Expand Up @@ -82,6 +85,23 @@ def setup(self, request, *args, **kwargs):
super().setup(request, *args, **kwargs)


def cache_page_for_guests(*cache_args, **cache_kwargs):
def inner_decorator(func):
@wraps(func)
def inner_function(request, *args, **kwargs):
if not request.user.is_authenticated and "nocache" not in request.GET:
print("🤙 CACHE HIT")
return cache_page(*cache_args, **cache_kwargs)(func)(
request, *args, **kwargs
)
return func(request, *args, **kwargs)

return inner_function

return inner_decorator


@method_decorator(cache_page_for_guests(60 * 15), name="dispatch")
class HomeView(BaseView, ListView):
template_name = "qfdmd/home.html"
model = Suggestion
Expand All @@ -105,9 +125,11 @@ def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
return context


@method_decorator(cache_page_for_guests(60 * 15), name="dispatch")
class SynonymeDetailView(BaseView, DetailView):
model = Synonyme


@method_decorator(cache_page_for_guests(60 * 15), name="dispatch")
class CMSPageDetailView(BaseView, DetailView):
model = CMSPage
45 changes: 45 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// k6 configuration file to simulate user behavior
import http from "k6/http"
import { sleep } from "k6"

export const options = {
stages: [
{ duration: "30s", target: 40 }, // Ramp-up to 19,110 concurrent users
{ duration: "10s", target: 40 }, // Maintain 19,110 users
{ duration: "5s", target: 0 }, // Ramp-down to 0 users
],
}

export default function () {
// Step 1: Visit the homepage
http.get("https://quefairedemesobjets-preprod.osc-fr1.scalingo.io/dechet/")
console.log("Visited homepage")
sleep(0.568) // Time spent on the page in seconds

// Step 2: Navigate to the first detailed page
http.get("https://quefairedemesobjets-preprod.osc-fr1.scalingo.io/papier-et-carton")
console.log("Visited page: Papier et Carton")
sleep(0.59) // Time spent on the page in seconds

// Step 3: Navigate to another detailed page
http.get("https://quefairedemesobjets-preprod.osc-fr1.scalingo.io/plastique")
console.log("Visited page: Plastique")
sleep(0.797) // Time spent on the page in seconds

// Step 4: Return to homepage with a theme parameter
http.get("https://quefairedemesobjets-preprod.osc-fr1.scalingo.io/?theme=dechets")
console.log("Visited homepage with theme parameter")
sleep(1.903) // Time spent on the page in seconds

// Step 5: Visit a different detailed page
http.get("https://quefairedemesobjets-preprod.osc-fr1.scalingo.io/verre")
console.log("Visited page: Verre")
sleep(1.5) // Time spent on the page in seconds

// Simulate user leaving the page
http.get("https://quefairedemesobjets-preprod.osc-fr1.scalingo.io/batteries")
console.log("Visited page: Batteries")
sleep(3.0) // Time spent on the page in seconds

// End of scenario
}
23 changes: 23 additions & 0 deletions servers.conf.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
server {
listen <%= ENV['PORT'] %>;
server_name _;

location /static/ {
alias /app/staticfiles/;
add_header Cache-Control "public, max-age=31536000, immutable";

# Prevent access to hidden files
location ~ /\. {
deny all;
}
}

location / {
proxy_pass http://localhost:<%= ENV['PORT'] %>;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://unix:/tmp/gunicorn.sock;
}
}
1 change: 1 addition & 0 deletions templates/components/sidebar/email/action.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
{% block modal_content %}
<turbo-frame id="contact-form"
src="{% url 'qfdmd:nous-contacter' %}"
loading="lazy"
>
</turbo-frame>
{% endblock modal_content %}
Expand Down

0 comments on commit bc561f8

Please sign in to comment.