107 行
2.9 KiB
Python

"""
Auto-export: after admin saves content, export JSON and write a trigger file.
A cron job watches the trigger file and runs Nuxt rebuild.
"""
from __future__ import annotations
import logging
import os
import threading
from app.config import settings
from app.services.export_service import EXPORT_FUNCTIONS
logger = logging.getLogger("auto_export")
ROUTE_TO_MODULES: dict[str, list[str]] = {
"/api/brand": ["brand"],
"/api/about": ["about"],
"/api/products": ["products"],
"/api/faq": ["faq"],
"/api/reviews": ["reviews"],
"/api/contact": ["contact"],
"/api/seo": ["seo"],
"/api/navigation": ["navigation"],
"/api/versions": ["versions"],
"/api/guides": ["guides"],
"/api/site-images": ["images"],
"/api/autumn": ["autumn-products"],
"/api/winter": ["winter-products"],
"/api/winter-camp": ["winter-camp"],
"/api/destinations-detail": ["destinations-detail"],
"/api/destinations": ["destinations"],
"/api/customize": ["customize"],
"/api/blog": ["blog"],
"/api/stories": ["stories"],
"/api/news": ["news"],
"/api/pricing": ["pricing"],
"/api/qualifications": ["qualifications"],
"/api/partners": ["partners"],
"/api/gallery": ["gallery"],
"/api/selector": ["selector"],
"/api/courses": ["courses"],
}
TRIGGER_FILE = "/tmp/gw-rebuild-trigger"
_pending_modules: set[str] = set()
_pending_lock = threading.Lock()
_debounce_timer: threading.Timer | None = None
def _do_export():
"""Export pending modules and write trigger file for cron to rebuild."""
global _debounce_timer
with _pending_lock:
modules = list(_pending_modules)
_pending_modules.clear()
_debounce_timer = None
if not modules:
return
from app.database import SessionLocal
try:
db = SessionLocal()
try:
for mod in modules:
fn = EXPORT_FUNCTIONS.get(mod)
if fn:
fn(db)
logger.info(f"Auto-exported: {mod}")
finally:
db.close()
# Write trigger file for cron-based rebuild
with open(TRIGGER_FILE, "w") as f:
f.write(",".join(modules))
logger.info(f"Trigger file written, cron will rebuild")
except Exception as e:
logger.error(f"Export failed: {e}")
def schedule_export(path: str):
"""Called after a successful write. Debounces 3s to batch rapid saves."""
global _debounce_timer
modules = []
for prefix, mods in ROUTE_TO_MODULES.items():
if path.startswith(prefix):
modules = mods
break
if not modules:
return
with _pending_lock:
_pending_modules.update(modules)
if _debounce_timer:
_debounce_timer.cancel()
_debounce_timer = threading.Timer(3.0, _do_export)
_debounce_timer.daemon = True
_debounce_timer.start()
logger.info(f"Scheduled export for: {modules}")