81 lines
2.7 KiB
Python
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}")
|