summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Doan <andy.doan@linaro.org>2016-06-17 14:41:40 -0500
committerAndy Doan <andy.doan@linaro.org>2016-07-05 19:47:05 +0000
commit3d654185bc11a834c7b0bb1a12cc76ec44f313ea (patch)
tree58b5de75e7ffbdcd6a7c1cc0bbcf1e1182e22fb7
parentf38c5548c0f7fa4ff4bf172dfbaf5b83090de889 (diff)
Add caching logic to most expensive APIs
We've recently encountered a pretty major degradation in s3 API performance. I originally skipped caching logic because things were "good enough" and I was scared to mess up cache logic. However, page loads are now routinely taking over 4s. My stats for the last 2 hours were: Average: 1.876110 (0.649776 %stddev) So the average isn't great and the standard deviation is huge which means we get really common *large* outliers. This patch is built on 2 simple ideas: #1 - caching is safe for releases.l.o. This is safe because we publish here once a month and then things are "static". #2 - find_artifact and dir_list are the most expensive calls for #1, we'll have to patch releases_us_secrets.py with: CACHES = { 'default': { 'BACKEND': django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': '/tmp/releases-django-cache', 'TIMEOUT': 5 * 60, # 5 minute cache } } Change-Id: I3effd75a5946d6f8a95dc6a626436a02987f4617 Reviewed-on: https://review.linaro.org/12768 Reviewed-by: Paul Sokolovsky <paul.sokolovsky@linaro.org> Reviewed-by: Ben Copeland <ben.copeland@linaro.org>
-rw-r--r--license_protected_downloads/common.py11
-rw-r--r--license_protected_downloads/tests/__init__.py1
-rw-r--r--license_protected_downloads/views.py5
-rw-r--r--settings.py7
4 files changed, 21 insertions, 3 deletions
diff --git a/license_protected_downloads/common.py b/license_protected_downloads/common.py
index e4755fd..0fe948a 100644
--- a/license_protected_downloads/common.py
+++ b/license_protected_downloads/common.py
@@ -4,6 +4,7 @@ import os
import boto
from django.conf import settings
+from django.core.cache import cache
from django.http import Http404
from license_protected_downloads import models
@@ -31,6 +32,16 @@ def safe_path_join(base_path, *paths):
return target_path
+def cached_call(key, func, *args, **kwargs):
+ key = func.__name__ + key
+ v = cache.get(key)
+ if v:
+ return v
+ v = func(*args, **kwargs)
+ cache.set(key, v)
+ return v
+
+
def _handle_wildcard(request, fullpath):
path, name = os.path.split(fullpath)
diff --git a/license_protected_downloads/tests/__init__.py b/license_protected_downloads/tests/__init__.py
index 307b75f..805675e 100644
--- a/license_protected_downloads/tests/__init__.py
+++ b/license_protected_downloads/tests/__init__.py
@@ -1,4 +1,3 @@
-
from license_protected_downloads.tests.test_buildinfo import *
from license_protected_downloads.tests.test_api_v1 import *
from license_protected_downloads.tests.test_api_v2 import *
diff --git a/license_protected_downloads/views.py b/license_protected_downloads/views.py
index 9ee198c..a1c670b 100644
--- a/license_protected_downloads/views.py
+++ b/license_protected_downloads/views.py
@@ -25,6 +25,7 @@ from group_auth_common import GroupAuthError
import xml.dom.minidom as dom
from license_protected_downloads.common import (
+ cached_call,
dir_list,
find_artifact,
)
@@ -219,7 +220,7 @@ def _check_file_permission(request, artifact, internal):
def file_server_get(request, path):
- artifact = find_artifact(request, path)
+ artifact = cached_call(path, find_artifact, request, path)
internal = get_client_ip(request) in config.INTERNAL_HOSTS
if not internal:
@@ -233,7 +234,7 @@ def file_server_get(request, path):
return resp
if artifact.isdir():
- return _handle_dir_list(request, artifact)
+ return cached_call(path, _handle_dir_list, request, artifact)
# prevent download of files like BUILD-INFO.txt
if artifact.hidden():
diff --git a/settings.py b/settings.py
index 02c5244..ac74584 100644
--- a/settings.py
+++ b/settings.py
@@ -185,6 +185,13 @@ LOGGING = {
}
}
+# disable caches by default for testing (enabled in production)
+CACHES = {
+ 'default': {
+ 'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
+ }
+}
+
import django
if django.VERSION < (1, 6):
# old django needs a hack to not send emails for ALLOWED_HOSTS violations