From dce00ca76c8576542aa16700ab10d9917ef57f9e Mon Sep 17 00:00:00 2001 From: renzon Date: Fri, 31 Jul 2020 09:44:27 -0300 Subject: [PATCH] Implemented Cache with Redis close #2024 --- Pipfile | 1 + Pipfile.lock | 33 +++++++++++++++++++++------------ conftest.py | 8 ++++++++ contrib/env-sample | 7 +++++-- pythonpro/cohorts/facade.py | 7 ++++++- pythonpro/modules/facade.py | 7 ++++++- pythonpro/settings.py | 28 +++++++++++++++++++++++++++- 7 files changed, 74 insertions(+), 17 deletions(-) diff --git a/Pipfile b/Pipfile index 8765c651..3a596c1a 100644 --- a/Pipfile +++ b/Pipfile @@ -34,6 +34,7 @@ inflection = "*" django-two-factor-auth = "*" django-recaptcha = "*" django-pagarme = "*" +django-redis = "*" [dev-packages] faker = "*" diff --git a/Pipfile.lock b/Pipfile.lock index ce649181..48dd1108 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "dfd32755c9185d6853fc66b66847315efca0b4405acaea75b19bf0dffc9fdb0a" + "sha256": "4429c9549346cea601964367c3a18b43d538e4fbfe6177692c902f24680a9251" }, "pipfile-spec": 6, "requires": { @@ -69,18 +69,18 @@ }, "boto3": { "hashes": [ - "sha256:4e357963ddd36a769e9a18ffe7517fed61f2b301a6e7d3c833cb5171146a5f53", - "sha256:859e29da7cce712f8fae8666fccb424bf3b42802d622b61b5219ea8a70e6a8f8" + "sha256:3cf7c9ce187bcd3c4961c6a51eeb472b75649ef00b67d876dd94735bf64fec34", + "sha256:d494a23295b2db9920e85391dc8106dc08d91dd40eeba5c05002771fe10f8853" ], "index": "pypi", - "version": "==1.14.30" + "version": "==1.14.32" }, "botocore": { "hashes": [ - "sha256:8d5c40c2ab98223caa87cf1109d4449ee3022cb0ce9eb3b76696a231cf447888", - "sha256:d222643daa1a510f7e11e02b424689d69b49d6a88add13cbfd2a676daae6e200" + "sha256:52a80cb721160b687179bd7077e63d775130455a678bf4280fb37c524c2bd67d", + "sha256:980c71b91d48ee3378a5f00c4530fdf2213a956e3924ca37859f6b3193f779b0" ], - "version": "==1.17.30" + "version": "==1.17.32" }, "celery": { "hashes": [ @@ -263,6 +263,14 @@ "index": "pypi", "version": "==2.0.6" }, + "django-redis": { + "hashes": [ + "sha256:1133b26b75baa3664164c3f44b9d5d133d1b8de45d94d79f38d1adc5b1d502e5", + "sha256:306589c7021e6468b2656edc89f62b8ba67e8d5a1c8877e2688042263daa7a63" + ], + "index": "pypi", + "version": "==4.12.1" + }, "django-role-permissions": { "hashes": [ "sha256:ffed5ddaef1e8699366e990e7a13525217fcc0e0dda4bc12941c47df21c93079" @@ -827,9 +835,10 @@ }, "iniconfig": { "hashes": [ - "sha256:aa0b40f50a00e72323cb5d41302f9c6165728fd764ac8822aa3fff00a40d56b4" + "sha256:80cf40c597eb564e86346103f609d74efce0f6b4d4f30ec8ce9e2c26411ba437", + "sha256:e5f92f89355a67de0595932a6c6c02ab4afddc6fcdc0bfc5becd0d60884d3f69" ], - "version": "==1.0.0" + "version": "==1.0.1" }, "kombu": { "hashes": [ @@ -919,11 +928,11 @@ }, "pytest": { "hashes": [ - "sha256:869ec27f9b89964ccfe4fbdd5ccb8d3f285aaa3e9aa16a8491b9c8829148c230", - "sha256:a64d8fb4c15cdc70dae047352e980a197d855747cc885eb332cb73ddcc769168" + "sha256:85228d75db9f45e06e57ef9bf4429267f81ac7c0d742cc9ed63d09886a9fe6f4", + "sha256:8b6007800c53fdacd5a5c192203f4e531eb2a1540ad9c752e052ec0f7143dbad" ], "index": "pypi", - "version": "==6.0.0" + "version": "==6.0.1" }, "pytest-cov": { "hashes": [ diff --git a/conftest.py b/conftest.py index 0d71e85c..47622e0d 100644 --- a/conftest.py +++ b/conftest.py @@ -204,6 +204,14 @@ def turn_active_campaign_on(settings): settings.ACTIVE_CAMPAIGN_TURNED_ON = True +@pytest.fixture(autouse=True) +def turn_cache_off(settings): + """ + This way test don't depend on local .env configuration + """ + settings.CACHE_TURNED_ON = False + + @pytest.fixture(autouse=True) def turn_ssl_rediret_off_for_tests(settings): """ diff --git a/contrib/env-sample b/contrib/env-sample index 12f22002..778f083e 100644 --- a/contrib/env-sample +++ b/contrib/env-sample @@ -35,7 +35,7 @@ DISCOURSE_API_USER= ACTIVE_CAMPAIGN_URL= ACTIVE_CAMPAIGN_KEY= # Make it False on dev to avoiding sending data to ActiveCampaign -ACTIVE_CAMPAIGN_TURNED_ON=true +ACTIVE_CAMPAIGN_TURNED_ON=false # Google Tag Manager Config GOOGLE_TAG_MANAGER_ID=GTM-ABC1234 @@ -49,4 +49,7 @@ REDIS_URL=redis://localhost:6379/1 RECAPTCHA_PUBLIC_KEY= RECAPTCHA_PRIVATE_KEY= - \ No newline at end of file + + +# Make it False to disable cache. Default is True +CACHE_TURNED_ON=false diff --git a/pythonpro/cohorts/facade.py b/pythonpro/cohorts/facade.py index 02ab44d2..8a6d77de 100644 --- a/pythonpro/cohorts/facade.py +++ b/pythonpro/cohorts/facade.py @@ -1,3 +1,7 @@ +from functools import partial + +from django.conf import settings +from django.core.cache import cache from django.db.models import Prefetch as _Prefetch from django.urls import reverse @@ -15,7 +19,8 @@ def get_all_cohorts_desc(): - return tuple(_Cohort.objects.order_by('-start')) + lazy_all_cohorts = partial(tuple, _Cohort.objects.order_by('-start')) + return cache.get_or_set('ALL_COHORTS', lazy_all_cohorts, settings.CACHE_TTL) def find_cohort(slug): diff --git a/pythonpro/modules/facade.py b/pythonpro/modules/facade.py index 20740d26..9baf4dde 100644 --- a/pythonpro/modules/facade.py +++ b/pythonpro/modules/facade.py @@ -1,3 +1,7 @@ +from functools import partial + +from django.conf import settings +from django.core.cache import cache from django.db.models import Prefetch from pythonpro.modules.models import ( @@ -14,7 +18,8 @@ def get_all_modules(): Search all modules on database sorted by order :return: tuple of Module """ - return tuple(_Module.objects.order_by('order')) + lazy_all_modules = partial(tuple, _Module.objects.order_by('order')) + return cache.get_or_set('ALL_MODULES', lazy_all_modules, settings.CACHE_TTL) def get_module_with_contents(slug): diff --git a/pythonpro/settings.py b/pythonpro/settings.py index a9708ef8..e685e906 100644 --- a/pythonpro/settings.py +++ b/pythonpro/settings.py @@ -159,6 +159,32 @@ 'default': config('DATABASE_URL', default=default_db_url, cast=dburl), } +# Cache configuration +REDIS_URL = config('REDIS_URL') +CACHE_REDIS_URL = f'{REDIS_URL}/1' + +CACHE_TTL = 60 * 15 + +CACHE_TURNED_ON = config('CACHE_TURNED_ON', default=True, cast=bool) + +if CACHE_TURNED_ON: + CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": CACHE_REDIS_URL, + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient" + }, + "KEY_PREFIX": "example" + } + } +else: + CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', + } + } + # Password validation # https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators @@ -274,6 +300,6 @@ BROKER_URL = config('CLOUDAMQP_URL') -CELERY_RESULT_BACKEND = config('REDIS_URL') +CELERY_RESULT_BACKEND = f'{REDIS_URL}/0' CELERY_TASK_SERIALIZER = 'json' CELERY_TIMEZONE = TIME_ZONE