Optimise performance with caching

This commit is contained in:
Mark Veidemanis 2023-02-11 14:00:09 +00:00
parent 1f43a00c7a
commit 57078c10c1
Signed by: m
GPG Key ID: 5ACFCEED46C0904F
5 changed files with 337 additions and 293 deletions

View File

@ -54,6 +54,24 @@ INSTALLED_APPS = [
# "otp_yubikey", # "otp_yubikey",
"mixins", "mixins",
] ]
# Performance optimisations
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.redis.RedisCache",
"LOCATION": "unix:///var/run/socks/redis.sock",
"OPTIONS": {
"db": "10",
"parser_class": "redis.connection.PythonParser",
"pool_class": "redis.BlockingConnectionPool",
},
}
}
# CACHE_MIDDLEWARE_ALIAS
# CACHE_MIDDLEWARE_SECONDS
# CACHE_MIDDLEWARE_KEY_PREFIX
CRISPY_TEMPLATE_PACK = "bulma" CRISPY_TEMPLATE_PACK = "bulma"
CRISPY_ALLOWED_TEMPLATE_PACKS = ("bulma",) CRISPY_ALLOWED_TEMPLATE_PACKS = ("bulma",)
DJANGO_TABLES2_TEMPLATE = "django-tables2/bulma.html" DJANGO_TABLES2_TEMPLATE = "django-tables2/bulma.html"
@ -69,6 +87,9 @@ MIDDLEWARE = [
"django.contrib.messages.middleware.MessageMiddleware", "django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware",
"django_htmx.middleware.HtmxMiddleware", "django_htmx.middleware.HtmxMiddleware",
# 'django.middleware.cache.UpdateCacheMiddleware',
# 'django.middleware.common.CommonMiddleware',
# 'django.middleware.cache.FetchFromCacheMiddleware',
] ]
ROOT_URLCONF = "app.urls" ROOT_URLCONF = "app.urls"

View File

@ -1,315 +1,320 @@
{% load static %} {% load static %}
{% load has_plan %} {% load has_plan %}
{% load cache %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en-GB"> <html lang="en-GB">
<head> {% cache 600 head %}
<meta charset="utf-8"> <head>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="utf-8">
<title>XF - {{ request.path_info }}</title> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="{% static 'favicon.ico' %}"> <title>XF - {{ request.path_info }}</title>
<link rel="manifest" href="{% static 'manifest.webmanifest' %}"> <link rel="shortcut icon" href="{% static 'favicon.ico' %}">
<link rel="stylesheet" href="{% static 'css/bulma.min.css' %}"> <link rel="manifest" href="{% static 'manifest.webmanifest' %}">
<link rel="stylesheet" href="{% static 'css/bulma-tooltip.min.css' %}"> <link rel="stylesheet" href="{% static 'css/bulma.min.css' %}">
<link rel="stylesheet" href="https://site-assets.fontawesome.com/releases/v6.1.1/css/all.css"> <link rel="stylesheet" href="{% static 'css/bulma-tooltip.min.css' %}">
<link rel="stylesheet" href="{% static 'css/gridstack.min.css' %}"> <link rel="stylesheet" href="https://site-assets.fontawesome.com/releases/v6.1.1/css/all.css">
<script src="{% static 'js/htmx.min.js' %}" integrity="sha384-cZuAZ+ZbwkNRnrKi05G/fjBX+azI9DNOkNYysZ0I/X5ZFgsmMiBXgDZof30F5ofc" crossorigin="anonymous"></script> <link rel="stylesheet" href="{% static 'css/gridstack.min.css' %}">
<script defer src="{% static 'js/hyperscript.min.js' %}" integrity="sha384-6GYN8BDHOJkkru6zcpGOUa//1mn+5iZ/MyT6mq34WFIpuOeLF52kSi721q0SsYF9" crossorigin="anonymous"></script> <script src="{% static 'js/htmx.min.js' %}" integrity="sha384-cZuAZ+ZbwkNRnrKi05G/fjBX+azI9DNOkNYysZ0I/X5ZFgsmMiBXgDZof30F5ofc" crossorigin="anonymous"></script>
<script defer src="{% static 'js/remove-me.js' %}" integrity="sha384-6fHcFNoQ8QEI3ZDgw9Z/A6Brk64gF7AnFbLgdrumo8/kBbsKQ/wo7wPegj5WkzuG" crossorigin="anonymous"></script> <script defer src="{% static 'js/hyperscript.min.js' %}" integrity="sha384-6GYN8BDHOJkkru6zcpGOUa//1mn+5iZ/MyT6mq34WFIpuOeLF52kSi721q0SsYF9" crossorigin="anonymous"></script>
<script src="{% static 'js/gridstack-all.js' %}"></script> <script defer src="{% static 'js/remove-me.js' %}" integrity="sha384-6fHcFNoQ8QEI3ZDgw9Z/A6Brk64gF7AnFbLgdrumo8/kBbsKQ/wo7wPegj5WkzuG" crossorigin="anonymous"></script>
<script defer src="{% static 'js/magnet.min.js' %}"></script> <script src="{% static 'js/gridstack-all.js' %}"></script>
<script> <script defer src="{% static 'js/magnet.min.js' %}"></script>
document.addEventListener("restore-scroll", function(event) { <script>
var scrollpos = localStorage.getItem('scrollpos'); document.addEventListener("restore-scroll", function(event) {
if (scrollpos) { var scrollpos = localStorage.getItem('scrollpos');
window.scrollTo(0, scrollpos) if (scrollpos) {
}; window.scrollTo(0, scrollpos)
}); };
document.addEventListener("htmx:beforeSwap", function(event) {
localStorage.setItem('scrollpos', window.scrollY);
});
</script>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Get all "navbar-burger" elements
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
// Add a click event on each of them
$navbarBurgers.forEach( el => {
el.addEventListener('click', () => {
// Get the target from the "data-target" attribute
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle('is-active');
$target.classList.toggle('is-active');
});
}); });
}); document.addEventListener("htmx:beforeSwap", function(event) {
</script> localStorage.setItem('scrollpos', window.scrollY);
<style>
.icon { border-bottom: 0px !important;}
.wrap {
word-wrap: break-word;
}
.nowrap-parent {
white-space: nowrap;
}
.nowrap-child {
display: inline-block;
}
.htmx-indicator{
opacity:0;
transition: opacity 500ms ease-in;
}
.htmx-request .htmx-indicator{
opacity:1
}
.htmx-request.htmx-indicator{
opacity:1
}
.tooltiptext { });
visibility: hidden; </script>
background-color: black; <script>
color: #fff; document.addEventListener('DOMContentLoaded', () => {
text-align: center;
padding: 5px 0;
border-radius: 6px;
position: absolute;
z-index: 1;
}
.rounded-tooltip:hover .tooltiptext { // Get all "navbar-burger" elements
visibility: visible; const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
}
.table { // Add a click event on each of them
background: transparent !important; $navbarBurgers.forEach( el => {
} el.addEventListener('click', () => {
tr { // Get the target from the "data-target" attribute
transition: all 0.2s ease-in-out; const target = el.dataset.target;
} const $target = document.getElementById(target);
tr:hover { // Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
cursor:pointer; el.classList.toggle('is-active');
background-color:rgba(221, 224, 255, 0.3) !important; $target.classList.toggle('is-active');
}
a.panel-block { });
transition: all 0.2s ease-in-out; });
}
a.panel-block:hover { });
cursor:pointer; </script>
background-color:rgba(221, 224, 255, 0.3) !important; <style>
} .icon { border-bottom: 0px !important;}
.wrap {
word-wrap: break-word;
}
.nowrap-parent {
white-space: nowrap;
}
.nowrap-child {
display: inline-block;
}
.htmx-indicator{
opacity:0;
transition: opacity 500ms ease-in;
}
.htmx-request .htmx-indicator{
opacity:1
}
.htmx-request.htmx-indicator{
opacity:1
}
.panel, .box, .modal { .tooltiptext {
background-color:rgba(250, 250, 250, 0.5) !important; visibility: hidden;
} background-color: black;
.modal, .modal.box{ color: #fff;
background-color:rgba(210, 210, 210, 0.9) !important; text-align: center;
} padding: 5px 0;
.modal-background{ border-radius: 6px;
background-color:rgba(255, 255, 255, 0.3) !important; position: absolute;
} z-index: 1;
}
.has-background-grey-lighter{ .rounded-tooltip:hover .tooltiptext {
background-color:rgba(219, 219, 219, 0.5) !important; visibility: visible;
} }
.navbar {
background-color:rgba(0, 0, 0, 0.03) !important;
}
.grid-stack-item-content { .table {
display: flex !important; background: transparent !important;
flex-direction: column !important; }
overflow-x: hidden !important;
overflow-y: hidden !important;
}
.panel { tr {
display: flex !important; transition: all 0.2s ease-in-out;
flex-direction: column !important; }
overflow: hidden;
}
.panel-block { tr:hover {
overflow-y:auto; cursor:pointer;
overflow-x:auto; background-color:rgba(221, 224, 255, 0.3) !important;
min-height: 90%; }
display: block;
}
.floating-window { a.panel-block {
/* background-color:rgba(210, 210, 210, 0.6) !important; */ transition: all 0.2s ease-in-out;
display: flex !important; }
flex-direction: column !important;
overflow-x: hidden !important;
overflow-y: hidden !important;
max-height: 300px;
z-index: 9000;
position: absolute;
top: 50px;
left: 50px;
}
.floating-window .panel { a.panel-block:hover {
background-color:rgba(250, 250, 250, 0.8) !important; cursor:pointer;
} background-color:rgba(221, 224, 255, 0.3) !important;
}
.float-right { .panel, .box, .modal {
float: right; background-color:rgba(250, 250, 250, 0.5) !important;
padding-right: 5px; }
padding-left: 5px; .modal, .modal.box{
} background-color:rgba(210, 210, 210, 0.9) !important;
.grid-stack-item:hover .ui-resizable-handle { }
display: block !important; .modal-background{
} background-color:rgba(255, 255, 255, 0.3) !important;
.ui-resizable-handle { }
z-index: 39 !important;
}
</style> .has-background-grey-lighter{
<!-- Piwik --> {# Yes it's in the source, fight me #} background-color:rgba(219, 219, 219, 0.5) !important;
<script type="text/javascript"> }
var _paq = _paq || []; .navbar {
_paq.push(['trackPageView']); background-color:rgba(0, 0, 0, 0.03) !important;
_paq.push(['enableLinkTracking']); }
(function() {
_paq.push(['setTrackerUrl', 'https://api-f98632bdcf666e3217c6c1a2bafc6c09.s.zm.is']); .grid-stack-item-content {
_paq.push(['setSiteId', 5]); display: flex !important;
_paq.push(['setApiToken', 'En6AFpSwq4vx3fuXEjSUY6jhUPi_MRinYBQw1FxOqsy']); flex-direction: column !important;
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; overflow-x: hidden !important;
g.type='text/javascript'; g.async=true; g.defer=true; g.src='https://c87zpt9a74m181wto33r.s.zm.is/embed.js'; s.parentNode.insertBefore(g,s); overflow-y: hidden !important;
})(); }
</script>
<!-- End Piwik Code --> .panel {
</head> display: flex !important;
flex-direction: column !important;
overflow: hidden;
}
.panel-block {
overflow-y:auto;
overflow-x:auto;
min-height: 90%;
display: block;
}
.floating-window {
/* background-color:rgba(210, 210, 210, 0.6) !important; */
display: flex !important;
flex-direction: column !important;
overflow-x: hidden !important;
overflow-y: hidden !important;
max-height: 300px;
z-index: 9000;
position: absolute;
top: 50px;
left: 50px;
}
.floating-window .panel {
background-color:rgba(250, 250, 250, 0.8) !important;
}
.float-right {
float: right;
padding-right: 5px;
padding-left: 5px;
}
.grid-stack-item:hover .ui-resizable-handle {
display: block !important;
}
.ui-resizable-handle {
z-index: 39 !important;
}
</style>
<!-- Piwik --> {# Yes it's in the source, fight me #}
<script type="text/javascript">
var _paq = _paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
_paq.push(['setTrackerUrl', 'https://api-f98632bdcf666e3217c6c1a2bafc6c09.s.zm.is']);
_paq.push(['setSiteId', 5]);
_paq.push(['setApiToken', 'En6AFpSwq4vx3fuXEjSUY6jhUPi_MRinYBQw1FxOqsy']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src='https://c87zpt9a74m181wto33r.s.zm.is/embed.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Piwik Code -->
</head>
{% endcache %}
<body> <body>
<nav class="navbar" role="navigation" aria-label="main navigation"> {% cache 600 nav request.user.id %}
<div class="navbar-brand"> <nav class="navbar" role="navigation" aria-label="main navigation">
<a class="navbar-item" href="{% url 'home' %}"> <div class="navbar-brand">
<img src="{% static 'logo.svg' %}" width="112" height="28" alt="logo">
</a>
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="bar">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="bar" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item" href="{% url 'home' %}"> <a class="navbar-item" href="{% url 'home' %}">
Home <img src="{% static 'logo.svg' %}" width="112" height="28" alt="logo">
</a> </a>
{% if user.is_authenticated %}
<div class="navbar-item has-dropdown is-hoverable"> <a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="bar">
<a class="navbar-link"> <span aria-hidden="true"></span>
Exchange <span aria-hidden="true"></span>
</a> <span aria-hidden="true"></span>
<div class="navbar-dropdown">
<a class="navbar-item" href="{% url 'profit' type='page' %}">
Profit
</a>
<a class="navbar-item" href="{% url 'positions' type='page' %}">
Positions
</a>
<a class="navbar-item" href="{% url 'trades' type='page' %}">
Trades
</a>
<a class="navbar-item" href="{% url 'accounts' type='page' %}">
Accounts
</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
Setup
</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="{% url 'strategies' type='page' %}">
Strategies
</a>
<a class="navbar-item" href="{% url 'signals' type='page' %}">
Signals
</a>
<a class="navbar-item" href="{% url 'hooks' type='page' %}">
Hooks
</a>
<a class="navbar-item" href="{% url 'tradingtimes' type='page' %}">
Trading Times
</a>
<a class="navbar-item" href="{% url 'risks' type='page' %}">
Risk Management
</a>
<a class="navbar-item" href="{% url 'assetgroups' type='page' %}">
Asset Groups
</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
Account
</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="{% url 'two_factor:profile' %}">
Security
</a>
<a class="navbar-item" href="{% url 'notifications_update' type='page' %}">
Notifications
</a>
</div>
</div>
{% endif %}
{% if settings.STRIPE_ENABLED %}
{% if user.is_authenticated %}
<a class="navbar-item" href="{% url 'billing' %}">
Billing
</a>
{% endif %}
{% endif %}
<a class="navbar-item add-button">
Install
</a> </a>
</div> </div>
<div class="navbar-end"> <div id="bar" class="navbar-menu">
<div class="navbar-item"> <div class="navbar-start">
<div class="buttons"> <a class="navbar-item" href="{% url 'home' %}">
{% if not user.is_authenticated %} Home
<a class="button" href="{% url 'signup' %}"> </a>
<strong>Sign up</strong> {% if user.is_authenticated %}
</a>
<a class="button" href="{% url 'two_factor:login' %}">
Log in
</a>
{% endif %}
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
Exchange
</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="{% url 'profit' type='page' %}">
Profit
</a>
<a class="navbar-item" href="{% url 'positions' type='page' %}">
Positions
</a>
<a class="navbar-item" href="{% url 'trades' type='page' %}">
Trades
</a>
<a class="navbar-item" href="{% url 'accounts' type='page' %}">
Accounts
</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
Setup
</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="{% url 'strategies' type='page' %}">
Strategies
</a>
<a class="navbar-item" href="{% url 'signals' type='page' %}">
Signals
</a>
<a class="navbar-item" href="{% url 'hooks' type='page' %}">
Hooks
</a>
<a class="navbar-item" href="{% url 'tradingtimes' type='page' %}">
Trading Times
</a>
<a class="navbar-item" href="{% url 'risks' type='page' %}">
Risk Management
</a>
<a class="navbar-item" href="{% url 'assetgroups' type='page' %}">
Asset Groups
</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
Account
</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="{% url 'two_factor:profile' %}">
Security
</a>
<a class="navbar-item" href="{% url 'notifications_update' type='page' %}">
Notifications
</a>
</div>
</div>
{% endif %}
{% if settings.STRIPE_ENABLED %}
{% if user.is_authenticated %} {% if user.is_authenticated %}
<a class="button" href="{% url 'logout' %}">Logout</a> <a class="navbar-item" href="{% url 'billing' %}">
Billing
</a>
{% endif %} {% endif %}
{% endif %}
<a class="navbar-item add-button">
Install
</a>
</div>
<div class="navbar-end">
<div class="navbar-item">
<div class="buttons">
{% if not user.is_authenticated %}
<a class="button" href="{% url 'signup' %}">
<strong>Sign up</strong>
</a>
<a class="button" href="{% url 'two_factor:login' %}">
Log in
</a>
{% endif %}
{% if user.is_authenticated %}
<a class="button" href="{% url 'logout' %}">Logout</a>
{% endif %}
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </nav>
</nav> {% endcache %}
<script> <script>
let deferredPrompt; let deferredPrompt;
const addBtn = document.querySelector('.add-button'); const addBtn = document.querySelector('.add-button');

View File

@ -43,6 +43,8 @@ services:
- ${PORTAINER_GIT_DIR}:/code - ${PORTAINER_GIT_DIR}:/code
- ${APP_DATABASE_FILE}:/conf/db.sqlite3 - ${APP_DATABASE_FILE}:/conf/db.sqlite3
- fisk_static:${STATIC_ROOT} - fisk_static:${STATIC_ROOT}
volumes_from:
- tmp
env_file: env_file:
- stack.env - stack.env
@ -58,6 +60,8 @@ services:
- ${PORTAINER_GIT_DIR}:/code - ${PORTAINER_GIT_DIR}:/code
- ${APP_DATABASE_FILE}:/conf/db.sqlite3 - ${APP_DATABASE_FILE}:/conf/db.sqlite3
- fisk_static:${STATIC_ROOT} - fisk_static:${STATIC_ROOT}
volumes_from:
- tmp
env_file: env_file:
- stack.env - stack.env
@ -98,24 +102,33 @@ services:
volumes: volumes:
- /var/run/socks - /var/run/socks
# redis: # For caching
# image: redis redis:
# command: redis-server /etc/redis.conf image: redis
# ulimits: container_name: redis_fisk
# nproc: 65535 command: redis-server /etc/redis.conf
# nofile: ulimits:
# soft: 65535 nproc: 65535
# hard: 65535 nofile:
# volumes: soft: 65535
# - ${PORTAINER_GIT_DIR}/docker/redis.conf:/etc/redis.conf hard: 65535
# - redis_data:/data volumes:
# volumes_from: - ${PORTAINER_GIT_DIR}/docker/redis.conf:/etc/redis.conf
# - tmp - fisk_redis_data:/data
# healthcheck: volumes_from:
# test: "redis-cli -s /var/run/redis/redis.sock ping" - tmp
# interval: 2s healthcheck:
# timeout: 2s test: "redis-cli -s /var/run/socks/redis.sock ping"
# retries: 15 interval: 2s
timeout: 2s
retries: 15
# pyroscope:
# image: "pyroscope/pyroscope:latest"
# ports:
# - "4040:4040"
# command:
# - "server"
networks: networks:
default: default:
@ -127,3 +140,4 @@ networks:
volumes: volumes:
fisk_static: {} fisk_static: {}
fisk_redis_data: {}

View File

@ -1,2 +1,2 @@
unixsocket /var/run/redis/redis.sock unixsocket /var/run/socks/redis.sock
unixsocketperm 777 unixsocketperm 777

View File

@ -22,3 +22,7 @@ oandapyV20
glom glom
elasticsearch elasticsearch
git+https://git.zm.is/XF/django-crud-mixins git+https://git.zm.is/XF/django-crud-mixins
# pyroscope-io
# For caching
redis
hiredis