feat: saxo connector

This commit is contained in:
OpenSquared
2026-07-18 21:14:37 +02:00
parent b986c8c525
commit 6db2705466
2 changed files with 19 additions and 4 deletions

View File

@@ -130,7 +130,14 @@ def get_valid_access_token() -> Optional[str]:
if datetime.now(timezone.utc) < expires_at - timedelta(seconds=60):
return stored["access_token"]
try:
refreshed = refresh_tokens()
except Exception as e:
# Refresh token rejected — clear the dead session instead of leaving a token that
# looks "connected" in /status but gets 401'd on the next real API call.
logger.error(f"[Saxo] Refresh failed on-demand, clearing dead session: {e}")
disconnect()
return None
return refreshed["access_token"] if refreshed else None

View File

@@ -44,10 +44,18 @@ def set_watchlist(symbols: list[str]):
def _refresh_loop(stop: threading.Event):
while not stop.wait(0):
try:
from .saxo_auth import get_status, refresh_tokens
from .saxo_auth import get_status, refresh_tokens, disconnect
if get_status().get("connected"):
try:
refresh_tokens()
logger.info("[Saxo Scheduler] Token refreshed proactively")
except Exception as e:
# Refresh token rejected (expired/rotated/invalid) — the stored access
# token is now dead even though its expires_at hasn't passed yet. Clear
# it so /api/saxo/status stops reporting a stale "connected" state, and
# the user gets a clear "reconnect" signal instead of silent 401s later.
logger.error(f"[Saxo Scheduler] Refresh failed, clearing dead session: {e}")
disconnect()
except Exception as e:
logger.error(f"[Saxo Scheduler] Refresh loop error: {e}")
stop.wait(timeout=REFRESH_INTERVAL_SECONDS)