Files
gomag-vending/api/app/main.py
Claude Agent aa9e580e1b fix(scheduler): prevent auto-enable with wrong interval on page load
Root cause: GET /api/sync/schedule returned interval_minutes=null when
scheduler was stopped, causing dropdown to stay on first HTML option
(1 min). Setting .value programmatically could trigger onchange, sending
a second PUT with interval=1 right after the user's intended interval.

- GET schedule falls back to DB/default (10 min) when scheduler is off
- Add _schedulerLoading flag to block onchange during loadSchedulerStatus
- Default interval 10 min everywhere (was 5 in backend)
- Cache bust dashboard.js v=33

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 13:57:22 +00:00

96 lines
3.0 KiB
Python

import asyncio
from contextlib import asynccontextmanager
from datetime import datetime
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from pathlib import Path
import logging
import os
from .config import settings
from .database import init_oracle, close_oracle, init_sqlite
from .routers.sync import backfill_price_match
# Configure logging with both stream and file handlers
_log_level = getattr(logging, settings.LOG_LEVEL.upper(), logging.INFO)
_log_format = '%(asctime)s | %(levelname)s | %(name)s | %(message)s'
_formatter = logging.Formatter(_log_format)
_stream_handler = logging.StreamHandler()
_stream_handler.setFormatter(_formatter)
_log_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'logs')
os.makedirs(_log_dir, exist_ok=True)
_log_filename = f"sync_comenzi_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
_file_handler = logging.FileHandler(os.path.join(_log_dir, _log_filename), encoding='utf-8')
_file_handler.setFormatter(_formatter)
_root_logger = logging.getLogger()
_root_logger.setLevel(_log_level)
_root_logger.addHandler(_stream_handler)
_root_logger.addHandler(_file_handler)
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Startup and shutdown events."""
logger.info("Starting GoMag Import Manager...")
# Initialize Oracle pool
try:
init_oracle()
except Exception as e:
logger.error(f"Oracle init failed: {e}")
# Allow app to start even without Oracle for development
# Initialize SQLite
init_sqlite()
# Initialize scheduler (restore saved config)
from .services import scheduler_service, sqlite_service
scheduler_service.init_scheduler()
try:
config = await sqlite_service.get_scheduler_config()
if config.get("enabled") == "True":
interval = int(config.get("interval_minutes", "10"))
scheduler_service.start_scheduler(interval)
except Exception:
pass
asyncio.create_task(backfill_price_match())
logger.info("GoMag Import Manager started")
yield
# Shutdown
scheduler_service.shutdown_scheduler()
close_oracle()
logger.info("GoMag Import Manager stopped")
app = FastAPI(
title="GoMag Import Manager",
description="Import comenzi web GoMag → ROA Oracle",
version="1.0.0",
lifespan=lifespan
)
# Static files and templates
static_dir = Path(__file__).parent / "static"
templates_dir = Path(__file__).parent / "templates"
static_dir.mkdir(parents=True, exist_ok=True)
(static_dir / "css").mkdir(exist_ok=True)
(static_dir / "js").mkdir(exist_ok=True)
templates_dir.mkdir(parents=True, exist_ok=True)
app.mount("/static", StaticFiles(directory=str(static_dir)), name="static")
# Include routers
from .routers import health, dashboard, mappings, articles, validation, sync
app.include_router(health.router)
app.include_router(dashboard.router)
app.include_router(mappings.router)
app.include_router(articles.router)
app.include_router(validation.router)
app.include_router(sync.router)