Files
ESP-Home-Git-Synchroniser/gunicorn_config.py

81 lines
2.7 KiB
Python

"""Gunicorn configuration file for ESPHome Gitea Sync Service"""
import logging
from threading import Thread
# Gunicorn configuration
bind = "0.0.0.0:5000"
workers = 2
timeout = 600
loglevel = "info"
logger = logging.getLogger(__name__)
# Track which worker has the file watcher (using a file-based flag)
import os
import tempfile
WATCHER_LOCK_FILE = os.path.join(tempfile.gettempdir(), 'esphome_watcher.lock')
def on_starting(server):
"""
Called just before the master process is initialized.
Perfect for one-time setup like git initialization.
"""
logger.info("Gunicorn master process starting - initializing git repository")
# Clean up any stale lock file from previous runs
if os.path.exists(WATCHER_LOCK_FILE):
try:
os.remove(WATCHER_LOCK_FILE)
logger.info("Removed stale watcher lock file")
except Exception as e:
logger.warning(f"Could not remove stale lock file: {e}")
# Import here to avoid circular imports
from app import initialize_git_repo
try:
initialize_git_repo()
logger.info("Git repository initialized successfully")
except Exception as e:
logger.error(f"Failed to initialize git repository: {e}")
def post_fork(server, worker):
"""
Called after a worker has been forked.
Start the file watcher only in the first worker to avoid duplicates.
"""
# Use a file-based lock to ensure only one worker starts the watcher
# This works across process boundaries unlike global variables
try:
# Try to create the lock file (exclusive creation)
fd = os.open(WATCHER_LOCK_FILE, os.O_CREAT | os.O_EXCL | os.O_WRONLY)
os.write(fd, str(worker.pid).encode())
os.close(fd)
# This worker won the race, start the file watcher
logger.info(f"Starting file watcher in worker {worker.pid}")
# Import here to avoid circular imports
from app import start_file_watcher
try:
# Start file watcher in a daemon thread
watcher_thread = Thread(target=start_file_watcher, daemon=True)
watcher_thread.start()
logger.info("File watcher started successfully")
except Exception as e:
logger.error(f"Failed to start file watcher: {e}")
# Clean up lock file on failure
try:
os.remove(WATCHER_LOCK_FILE)
except:
pass
except FileExistsError:
# Another worker already started the watcher
logger.info(f"Worker {worker.pid} started (file watcher already running in another worker)")
except Exception as e:
logger.error(f"Error in post_fork for worker {worker.pid}: {e}")