107 行
2.9 KiB
Python
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}")
|