Compare commits

...

2 Commits

Author SHA1 Message Date
8455d64e31
Reformat 2023-02-11 14:00:19 +00:00
57078c10c1
Optimise performance with caching 2023-02-11 14:00:09 +00:00
8 changed files with 361 additions and 302 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

@ -4,19 +4,19 @@ from django.contrib.auth.admin import UserAdmin
from .forms import CustomUserCreationForm from .forms import CustomUserCreationForm
from .models import ( from .models import (
Account, Account,
AssetGroup,
AssetRestriction,
Callback, Callback,
Hook, Hook,
NotificationSettings,
Plan, Plan,
RiskModel,
Session, Session,
Signal, Signal,
Strategy, Strategy,
Trade, Trade,
TradingTime, TradingTime,
User, User,
NotificationSettings,
RiskModel,
AssetGroup,
AssetRestriction,
) )
# admin.site.__class__ = OTPAdminSite # admin.site.__class__ = OTPAdminSite
@ -80,15 +80,27 @@ class StrategyAdmin(admin.ModelAdmin):
class NotificationSettingsAdmin(admin.ModelAdmin): class NotificationSettingsAdmin(admin.ModelAdmin):
list_display = ("user", "ntfy_topic", "ntfy_url") list_display = ("user", "ntfy_topic", "ntfy_url")
class RiskModelAdmin(admin.ModelAdmin): class RiskModelAdmin(admin.ModelAdmin):
list_display = ("user", "name", "description", "max_loss_percent", "max_risk_percent", "max_open_trades", "max_open_trades_per_symbol") list_display = (
"user",
"name",
"description",
"max_loss_percent",
"max_risk_percent",
"max_open_trades",
"max_open_trades_per_symbol",
)
class AssetGroupAdmin(admin.ModelAdmin): class AssetGroupAdmin(admin.ModelAdmin):
list_display = ("user", "name", "description", "account") list_display = ("user", "name", "description", "account")
class AssetRestrictionAdmin(admin.ModelAdmin): class AssetRestrictionAdmin(admin.ModelAdmin):
list_display = ("user", "name", "description", "webhook_id", "group") list_display = ("user", "name", "description", "webhook_id", "group")
admin.site.register(User, CustomUserAdmin) admin.site.register(User, CustomUserAdmin)
admin.site.register(Plan) admin.site.register(Plan)
admin.site.register(Session) admin.site.register(Session)
@ -103,4 +115,4 @@ admin.site.register(Strategy, StrategyAdmin)
admin.site.register(NotificationSettings, NotificationSettingsAdmin) admin.site.register(NotificationSettings, NotificationSettingsAdmin)
admin.site.register(RiskModel, RiskModelAdmin) admin.site.register(RiskModel, RiskModelAdmin)
admin.site.register(AssetGroup, AssetGroupAdmin) admin.site.register(AssetGroup, AssetGroupAdmin)
admin.site.register(AssetRestriction, AssetRestrictionAdmin) admin.site.register(AssetRestriction, AssetRestrictionAdmin)

View File

@ -1,7 +1,7 @@
# Generated by Django 4.1.6 on 2023-02-10 22:57 # Generated by Django 4.1.6 on 2023-02-10 22:57
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):

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

@ -1,3 +1,5 @@
import json
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse from django.http import HttpResponse
from mixins.views import AbortSave, ObjectCreate, ObjectDelete, ObjectList, ObjectUpdate from mixins.views import AbortSave, ObjectCreate, ObjectDelete, ObjectList, ObjectUpdate
@ -8,7 +10,6 @@ from rest_framework.views import APIView
from core.forms import AssetGroupForm, AssetRestrictionForm from core.forms import AssetGroupForm, AssetRestrictionForm
from core.models import AssetGroup, AssetRestriction from core.models import AssetGroup, AssetRestriction
from core.util import logs from core.util import logs
import json
log = logs.get_logger(__name__) log = logs.get_logger(__name__)
@ -65,7 +66,9 @@ class AssetRestrictionList(
list_template = "partials/assetrestriction-list.html" list_template = "partials/assetrestriction-list.html"
model = AssetRestriction model = AssetRestriction
page_title = "List of asset restrictions. Linked to asset groups." page_title = "List of asset restrictions. Linked to asset groups."
page_subtitle = "Allows API calls to permit or prohibit trading on defined currency pairs." page_subtitle = (
"Allows API calls to permit or prohibit trading on defined currency pairs."
)
list_url_name = "assetrestrictions" list_url_name = "assetrestrictions"
list_url_args = ["type", "group"] list_url_args = ["type", "group"]

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