Skip to content

Commit d78f705

Browse files
committed
Enhance project configuration by adding health check and task scheduler dependencies, remove obsolete test files, and update settings for health checks and scheduler configuration.
Also Added development compose
1 parent 5c1b7f0 commit d78f705

File tree

12 files changed

+712
-406
lines changed

12 files changed

+712
-406
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
.venv/
44
.env
55
*/migrations/
6-
*/__pycache__
6+
*/__pycache__/
77
telegram bot/
88
nginx/
99
static/admin/
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# define an alias for the specific python version used in this file.
2+
FROM docker.io/python:3.12-slim-bookworm AS python
3+
4+
# Python build stage
5+
FROM python AS python-build-stage
6+
7+
ARG BUILD_ENVIRONMENT=development
8+
9+
# Python 'run' stage
10+
FROM python AS python-run-stage
11+
12+
ARG BUILD_ENVIRONMENT=development
13+
ARG APP_HOME=/app
14+
15+
ENV PYTHONUNBUFFERED=1
16+
ENV PYTHONDONTWRITEBYTECODE=1
17+
ENV BUILD_ENV=${BUILD_ENVIRONMENT}
18+
19+
ADD . /app
20+
WORKDIR ${APP_HOME}
21+
22+
RUN addgroup --system django \
23+
&& adduser --system --ingroup django django
24+
25+
# Install apt packages
26+
RUN apt-get update && apt-get install --no-install-recommends -y \
27+
# dependencies for building Python packages
28+
build-essential \
29+
# psycopg dependencies
30+
libpq-dev \
31+
# uv dep
32+
curl \
33+
ca-certificates \
34+
gettext \
35+
locales
36+
37+
# install dep
38+
ENV UV_INSTALL_DIR="/root/.local/bin/"
39+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/
40+
ENV PATH="/root/.local/bin/:$PATH"
41+
ENV UV_PROJECT_ENVIRONMENT="/usr/local/"
42+
RUN uv sync -U --compile-bytecode --no-cache --no-editable
43+
44+
COPY --chown=django:django ./compose/production/django/entrypoint /entrypoint
45+
RUN sed -i 's/\r$//g' /entrypoint
46+
RUN chmod +x /entrypoint
47+
48+
# Don't create media and staticfiles directories - they'll be mounted as volumes
49+
50+
# Copy production startup scripts (for celery)
51+
COPY --chown=django:django ./compose/production/django/start /start
52+
RUN sed -i 's/\r$//g' /start
53+
RUN chmod +x /start
54+
55+
COPY --chown=django:django ./compose/production/django/celery/worker/start /start-celeryworker
56+
RUN sed -i 's/\r$//g' /start-celeryworker
57+
RUN chmod +x /start-celeryworker
58+
59+
COPY --chown=django:django ./compose/production/django/celery/beat/start /start-celerybeat
60+
RUN sed -i 's/\r$//g' /start-celerybeat
61+
RUN chmod +x /start-celerybeat
62+
63+
# copy application code to WORKDIR
64+
COPY --chown=django:django . ${APP_HOME}
65+
66+
# Copy development startup script (after app code is copied)
67+
COPY --chown=django:django ./compose/development/django/start-dev /start-dev
68+
RUN sed -i 's/\r$//g' /start-dev
69+
RUN chmod +x /start-dev
70+
71+
# make django owner of the WORKDIR directory as well.
72+
RUN chown -R django:django ${APP_HOME}
73+
74+
USER django
75+
76+
ENTRYPOINT ["/entrypoint"]
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o pipefail
5+
set -o nounset
6+
7+
# Wait for PostgreSQL
8+
python << END
9+
import sys
10+
import time
11+
12+
import psycopg
13+
14+
suggest_unrecoverable_after = 30
15+
start = time.time()
16+
17+
while True:
18+
try:
19+
psycopg.connect(
20+
dbname="${POSTGRES_DB}",
21+
user="${POSTGRES_USER}",
22+
password="${POSTGRES_PASSWORD}",
23+
host="${POSTGRES_HOST}",
24+
port="${POSTGRES_PORT}",
25+
)
26+
break
27+
except psycopg.OperationalError as error:
28+
sys.stderr.write("Waiting for PostgreSQL to become available...\n")
29+
30+
if time.time() - start > suggest_unrecoverable_after:
31+
sys.stderr.write(" This is taking longer than expected. The following exception may be indicative of an unrecoverable error: '{}'\n".format(error))
32+
33+
time.sleep(1)
34+
END
35+
36+
>&2 echo 'PostgreSQL is available'
37+
38+
# Run Django development server with auto-reload
39+
exec python /app/manage.py runserver 0.0.0.0:8000

docker-compose.dev.yml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
volumes:
2+
production_postgres_data: {}
3+
production_postgres_data_backups: {}
4+
production_django_media: {}
5+
production_django_static: {}
6+
production_redis_data: {}
7+
8+
9+
services:
10+
django: &django
11+
build:
12+
context: .
13+
dockerfile: ./compose/development/django/Dockerfile
14+
command: /start-dev
15+
volumes:
16+
- .:/app:ro # Mount entire project for live development
17+
user: "django"
18+
env_file:
19+
- ./.env
20+
environment:
21+
- DEBUG=True
22+
- PYTHONPATH=/app
23+
- DJANGO_SETTINGS_MODULE=pastebinir.settings_dev
24+
depends_on:
25+
- redis
26+
- postgres
27+
28+
postgres:
29+
build:
30+
context: .
31+
dockerfile: ./compose/production/postgres/Dockerfile
32+
image: printir_production_postgres
33+
volumes:
34+
- production_postgres_data:/var/lib/postgresql/data
35+
- production_postgres_data_backups:/backups
36+
env_file:
37+
- ./.env
38+
39+
40+
nginx:
41+
image: nginx:alpine
42+
ports:
43+
- "80:80"
44+
volumes:
45+
- ./compose/development/nginx/default.conf:/etc/nginx/conf.d/default.conf
46+
depends_on:
47+
- django
48+
49+
redis:
50+
image: redis:latest
51+
ports:
52+
- "6379:6379"
53+
volumes:
54+
- production_redis_data:/data
55+
56+
57+
celeryworker:
58+
<<: *django
59+
build:
60+
context: .
61+
dockerfile: ./compose/development/django/Dockerfile
62+
command: /start-celeryworker
63+
volumes:
64+
- .:/app:ro # Mount entire project for live development
65+
environment:
66+
- DEBUG=True
67+
- PYTHONPATH=/app
68+
69+
scheduler:
70+
<<: *django
71+
build:
72+
context: .
73+
dockerfile: ./compose/development/django/Dockerfile
74+
command: python manage.py run_scheduler
75+
volumes:
76+
- .:/app:ro # Mount entire project for live development
77+
environment:
78+
- DEBUG=True
79+
- PYTHONPATH=/app
80+
depends_on:
81+
- redis
82+
- postgres
83+

pastebinir/settings.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import os
1313
from pathlib import Path
1414
from dotenv import load_dotenv
15+
from typing import Dict
16+
from scheduler.types import SchedulerConfiguration, Broker, QueueConfiguration
1517

1618
load_dotenv()
1719

@@ -45,6 +47,15 @@
4547
'rest_framework',
4648
'rest_framework.authtoken',
4749
'dj_rest_auth',
50+
'health_check', # required
51+
'health_check.db', # stock Django health checkers
52+
'health_check.cache',
53+
'health_check.storage',
54+
'health_check.contrib.migrations',
55+
'health_check.contrib.celery', # requires celery
56+
'health_check.contrib.celery_ping', # requires celery
57+
'health_check.contrib.redis', # requires Redis broker
58+
'scheduler', # django-tasks-scheduler
4859
]
4960

5061
MIDDLEWARE = [
@@ -243,3 +254,39 @@
243254
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
244255

245256
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
257+
258+
# Health Check Configuration
259+
HEALTH_CHECK = {
260+
'DISK_USAGE_MAX': 90, # percent
261+
'MEMORY_MIN': 100, # in MB
262+
'SUBSETS': {
263+
'startup-probe': ['MigrationsHealthCheck', 'DatabaseBackend'],
264+
'liveness-probe': ['DatabaseBackend', 'CacheBackend', 'CeleryHealthCheck'],
265+
'readiness-probe': ['DatabaseBackend', 'CacheBackend', 'CeleryHealthCheck', 'RedisHealthCheck'],
266+
},
267+
}
268+
269+
# Health Check Cache Key
270+
HEALTHCHECK_CACHE_KEY = 'pastedir_healthcheck'
271+
272+
# Scheduler Configuration
273+
SCHEDULER_CONFIG = SchedulerConfiguration(
274+
EXECUTIONS_IN_PAGE=20,
275+
SCHEDULER_INTERVAL=10,
276+
BROKER=Broker.REDIS,
277+
CALLBACK_TIMEOUT=60, # Callback timeout in seconds (success/failure/stopped)
278+
# Default values, can be overriden per task/job
279+
DEFAULT_SUCCESS_TTL=10 * 60, # Time To Live (TTL) in seconds to keep successful job results
280+
DEFAULT_FAILURE_TTL=365 * 24 * 60 * 60, # Time To Live (TTL) in seconds to keep job failure information
281+
DEFAULT_JOB_TTL=10 * 60, # Time To Live (TTL) in seconds to keep job information
282+
DEFAULT_JOB_TIMEOUT=5 * 60, # timeout (seconds) for a job
283+
# General configuration values
284+
DEFAULT_WORKER_TTL=10 * 60, # Time To Live (TTL) in seconds to keep worker information after last heartbeat
285+
DEFAULT_MAINTENANCE_TASK_INTERVAL=10 * 60, # The interval to run maintenance tasks in seconds. 10 minutes.
286+
DEFAULT_JOB_MONITORING_INTERVAL=30, # The interval to monitor jobs in seconds.
287+
SCHEDULER_FALLBACK_PERIOD_SECS=120, # Period (secs) to wait before requiring to reacquire locks
288+
)
289+
290+
SCHEDULER_QUEUES: Dict[str, QueueConfiguration] = {
291+
'default': QueueConfiguration(URL='redis://redis:6379/0'),
292+
}

pastebinir/settings_dev.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""
2+
Development settings for pastebinir project.
3+
"""
4+
from .settings import *
5+
6+
# Development-specific settings
7+
DEBUG = True
8+
9+
# Enable auto-reload for development
10+
USE_TZ = True
11+
12+
# Disable HTTPS requirements for development
13+
SESSION_COOKIE_SECURE = False
14+
CSRF_COOKIE_SECURE = False
15+
16+
# Allow all hosts for development
17+
ALLOWED_HOSTS = ['*']
18+
19+
# Disable security headers for development
20+
SECURE_BROWSER_XSS_FILTER = False
21+
SECURE_CONTENT_TYPE_NOSNIFF = False
22+
SECURE_HSTS_SECONDS = 0
23+
SECURE_HSTS_INCLUDE_SUBDOMAINS = False
24+
SECURE_HSTS_PRELOAD = False
25+
26+
# Enable debug toolbar if available
27+
try:
28+
import debug_toolbar
29+
INSTALLED_APPS += ['debug_toolbar']
30+
MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']
31+
INTERNAL_IPS = ['127.0.0.1', '::1']
32+
except ImportError:
33+
pass
34+
35+
# Development logging
36+
LOGGING = {
37+
'version': 1,
38+
'disable_existing_loggers': False,
39+
'handlers': {
40+
'console': {
41+
'class': 'logging.StreamHandler',
42+
},
43+
},
44+
'root': {
45+
'handlers': ['console'],
46+
'level': 'INFO',
47+
},
48+
'loggers': {
49+
'django': {
50+
'handlers': ['console'],
51+
'level': 'INFO',
52+
'propagate': False,
53+
},
54+
},
55+
}
56+
57+
# Serve static files in development
58+
STATICFILES_DIRS = [
59+
BASE_DIR / 'static',
60+
]
61+
62+
# Disable static files collection in development
63+
STATIC_ROOT = None

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ dependencies = [
1010
"cryptography>=45.0.5",
1111
"dj-rest-auth>=7.0.1",
1212
"django>=5.2.4",
13+
"django-health-check>=3.20.0",
1314
"django-redis>=6.0.0",
1415
"djangorestframework>=3.16.0",
1516
"drf-spectacular>=0.28.0",
17+
"django-tasks-scheduler>=4.0.5",
1618
"gunicorn>=23.0.0",
1719
"psycopg[binary,pool]>=3.2.9 ; sys_platform == 'win32'",
1820
"psycopg[c,pool]>=3.2.9 ; sys_platform != 'win32'",

templates/base.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,14 @@ <h1 class="text-2xl font-bold">
443443
<footer class="text-white py-4">
444444
<div class="container mx-auto text-center">
445445
<p>&copy; 2025 Pasted IR. All rights reserved.</p>
446+
<div class="mt-2">
447+
<a href="https://github.com/yourusername/PastedIR" target="_blank" rel="noopener noreferrer" class="text-blue-200 hover:text-white transition-colors inline-flex items-center space-x-1">
448+
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
449+
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
450+
</svg>
451+
<span>View on GitHub</span>
452+
</a>
453+
</div>
446454
</div>
447455
</footer>
448456

test_celery.py

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)