-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathentrypoint.sh
More file actions
142 lines (126 loc) · 3.87 KB
/
entrypoint.sh
File metadata and controls
142 lines (126 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/bin/bash
set -e
echo "=========================================="
echo " PyRunner - Starting up..."
echo "=========================================="
# Validate required environment variables
if [ -z "$SECRET_KEY" ]; then
echo ""
echo "ERROR: SECRET_KEY is required but not set."
echo ""
echo "Generate one with:"
echo " python -c \"from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())\""
echo ""
exit 1
fi
if [ -z "$ENCRYPTION_KEY" ]; then
echo ""
echo "ERROR: ENCRYPTION_KEY is required but not set."
echo ""
echo "Generate one with:"
echo " python -c \"from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())\""
echo ""
exit 1
fi
# Run setup (migrations + default environment)
echo "[*] Running setup..."
python manage.py setup
echo ""
echo "[*] Starting services..."
# PID file location
QCLUSTER_PID_FILE="/tmp/qcluster.pid"
# Function to start qcluster worker
start_qcluster() {
echo " - Starting django-q2 worker..."
python manage.py qcluster &
QCLUSTER_PID=$!
echo $QCLUSTER_PID > "$QCLUSTER_PID_FILE"
echo " - Worker started with PID $QCLUSTER_PID"
}
# Function to stop qcluster gracefully
stop_qcluster() {
if [ -f "$QCLUSTER_PID_FILE" ]; then
local pid=$(cat "$QCLUSTER_PID_FILE")
if kill -0 $pid 2>/dev/null; then
echo "[*] Stopping worker (PID $pid)..."
kill -TERM $pid 2>/dev/null || true
# Wait up to 30 seconds for graceful shutdown
local count=0
while kill -0 $pid 2>/dev/null && [ $count -lt 30 ]; do
sleep 1
count=$((count + 1))
done
# Force kill if still running
if kill -0 $pid 2>/dev/null; then
echo "[!] Worker did not stop gracefully, force killing..."
kill -9 $pid 2>/dev/null || true
fi
fi
rm -f "$QCLUSTER_PID_FILE"
fi
}
# Signal handler for restart request (SIGUSR1)
handle_restart() {
echo ""
echo "[*] Restart signal received, restarting workers..."
stop_qcluster
start_qcluster
echo "[*] Workers restarted successfully"
}
trap handle_restart SIGUSR1
# Handle graceful shutdown
cleanup() {
echo ""
echo "[*] Shutting down..."
stop_qcluster
# Kill monitor if running
if [ -n "$MONITOR_PID" ]; then
kill $MONITOR_PID 2>/dev/null || true
fi
exit 0
}
trap cleanup SIGTERM SIGINT
# Start workers initially
start_qcluster
# Worker monitoring loop (runs in background)
monitor_workers() {
local backoff=1
local max_backoff=60
while true; do
sleep 5
# Check if worker is still running
if [ -f "$QCLUSTER_PID_FILE" ]; then
local pid=$(cat "$QCLUSTER_PID_FILE")
if ! kill -0 $pid 2>/dev/null; then
echo "[!] Worker (PID $pid) died unexpectedly, restarting in ${backoff}s..."
sleep $backoff
start_qcluster
# Increase backoff (exponential with max)
backoff=$((backoff * 2))
if [ $backoff -gt $max_backoff ]; then
backoff=$max_backoff
fi
else
# Worker is running, reset backoff
backoff=1
fi
fi
done
}
monitor_workers &
MONITOR_PID=$!
# Start gunicorn web server
echo " - Starting web server on port ${PORT:-8000}..."
echo ""
echo "=========================================="
echo " PyRunner is ready!"
echo " Open http://localhost:${PORT:-8000}"
echo "=========================================="
echo ""
exec gunicorn pyrunner.wsgi:application \
--bind 0.0.0.0:${PORT:-8000} \
--workers ${GUNICORN_WORKERS:-2} \
--threads ${GUNICORN_THREADS:-4} \
--timeout ${GUNICORN_TIMEOUT:-120} \
--access-logfile - \
--error-logfile -