fix: VPS fresh-DB bootstrap — sync OPENAI_API_KEY from env to DB at startup + show countdown before first cycle
- main.py startup: if DB has no openai_api_key but OPENAI_API_KEY env var is set, auto-save it so cycle trigger returns 200 instead of 400 - Config.tsx: move NextRunCountdown outside cs?.last_cycle block so it renders even when no cycle has run yet Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -22,15 +22,25 @@ app.add_middleware(
|
|||||||
|
|
||||||
@app.on_event("startup")
|
@app.on_event("startup")
|
||||||
def startup():
|
def startup():
|
||||||
|
import logging
|
||||||
|
_log = logging.getLogger(__name__)
|
||||||
|
|
||||||
init_db()
|
init_db()
|
||||||
|
|
||||||
# Clean up cycles that were left in 'running' state by a previous crashed process
|
# Clean up cycles that were left in 'running' state by a previous crashed process
|
||||||
stale = cleanup_stale_running_cycles()
|
stale = cleanup_stale_running_cycles()
|
||||||
if stale:
|
if stale:
|
||||||
import logging
|
_log.warning(f"[Startup] Cleaned up {stale} stale 'running' cycle(s) — server likely reloaded mid-cycle")
|
||||||
logging.getLogger(__name__).warning(
|
|
||||||
f"[Startup] Cleaned up {stale} stale 'running' cycle(s) — server likely reloaded mid-cycle"
|
# Sync OpenAI key: env var → DB (useful on fresh VPS deployments)
|
||||||
)
|
|
||||||
key = get_config("openai_api_key") or ""
|
key = get_config("openai_api_key") or ""
|
||||||
|
if not key:
|
||||||
|
env_key = os.environ.get("OPENAI_API_KEY", "")
|
||||||
|
if env_key:
|
||||||
|
from services.database import save_config
|
||||||
|
save_config("openai_api_key", env_key)
|
||||||
|
key = env_key
|
||||||
|
_log.info("[Startup] OPENAI_API_KEY synced from environment to DB config")
|
||||||
if key:
|
if key:
|
||||||
os.environ["OPENAI_API_KEY"] = key
|
os.environ["OPENAI_API_KEY"] = key
|
||||||
# Seed built-in patterns into DB (idempotent)
|
# Seed built-in patterns into DB (idempotent)
|
||||||
|
|||||||
@@ -720,7 +720,7 @@ export default function Config() {
|
|||||||
<RiskProfilesCard />
|
<RiskProfilesCard />
|
||||||
|
|
||||||
{cs?.last_cycle && (
|
{cs?.last_cycle && (
|
||||||
<div className="card bg-dark-700/50 mb-4 text-xs space-y-2">
|
<div className="card bg-dark-700/50 mb-2 text-xs space-y-2">
|
||||||
<div className="flex items-center gap-4 flex-wrap">
|
<div className="flex items-center gap-4 flex-wrap">
|
||||||
<span className="text-slate-500">Dernier cycle :</span>
|
<span className="text-slate-500">Dernier cycle :</span>
|
||||||
<span className="text-slate-300">{cs.last_cycle.started_at?.slice(0, 16)} UTC</span>
|
<span className="text-slate-300">{cs.last_cycle.started_at?.slice(0, 16)} UTC</span>
|
||||||
@@ -732,9 +732,11 @@ export default function Config() {
|
|||||||
<span className="text-slate-500">Géo: {cs.last_cycle.geo_score}</span>
|
<span className="text-slate-500">Géo: {cs.last_cycle.geo_score}</span>
|
||||||
<span className="text-slate-500 capitalize">{cs.last_cycle.dominant_regime}</span>
|
<span className="text-slate-500 capitalize">{cs.last_cycle.dominant_regime}</span>
|
||||||
</div>
|
</div>
|
||||||
{cs.enabled && cs.next_run_at && !cs.running && (
|
</div>
|
||||||
<NextRunCountdown nextRunAt={cs.next_run_at} />
|
)}
|
||||||
)}
|
{cs?.enabled && cs?.next_run_at && !cs?.running && (
|
||||||
|
<div className="card bg-dark-700/50 mb-4 text-xs">
|
||||||
|
<NextRunCountdown nextRunAt={cs.next_run_at} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user