feat: saxo connector
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user