fix(bluesky): add token expiry handling to session cache
The module-level _cached_token was set once and never refreshed. AT Protocol tokens expire after ~2 hours, causing silent 401 errors in long-running watchlist cron sessions. Adds a 90-minute expiry check using time.monotonic() and logs re-authentication. Fixes #92
This commit is contained in:
+12
-3
@@ -7,6 +7,7 @@ Requires BSKY_HANDLE and BSKY_APP_PASSWORD env vars.
|
|||||||
import math
|
import math
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
@@ -23,7 +24,9 @@ DEPTH_CONFIG = {
|
|||||||
|
|
||||||
# Module-level token cache (valid for the lifetime of a single research run)
|
# Module-level token cache (valid for the lifetime of a single research run)
|
||||||
_cached_token: Optional[str] = None
|
_cached_token: Optional[str] = None
|
||||||
|
_token_created_at: float = 0.0
|
||||||
_session_error: Optional[str] = None
|
_session_error: Optional[str] = None
|
||||||
|
_TOKEN_MAX_AGE_SECONDS = 5400 # 90 minutes (conservative, tokens last ~2 hours)
|
||||||
|
|
||||||
|
|
||||||
def _log(msg: str):
|
def _log(msg: str):
|
||||||
@@ -40,9 +43,13 @@ def _create_session(handle: str, app_password: str) -> Optional[str]:
|
|||||||
Returns:
|
Returns:
|
||||||
Access JWT string, or None on failure. Sets _session_error on failure.
|
Access JWT string, or None on failure. Sets _session_error on failure.
|
||||||
"""
|
"""
|
||||||
global _cached_token, _session_error
|
global _cached_token, _token_created_at, _session_error
|
||||||
if _cached_token:
|
if _cached_token and (time.monotonic() - _token_created_at < _TOKEN_MAX_AGE_SECONDS):
|
||||||
return _cached_token
|
return _cached_token
|
||||||
|
if _cached_token:
|
||||||
|
_log("Session token expired, re-authenticating")
|
||||||
|
_cached_token = None
|
||||||
|
_token_created_at = 0.0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = http.request(
|
response = http.request(
|
||||||
@@ -54,6 +61,7 @@ def _create_session(handle: str, app_password: str) -> Optional[str]:
|
|||||||
token = response.get("accessJwt")
|
token = response.get("accessJwt")
|
||||||
if token:
|
if token:
|
||||||
_cached_token = token
|
_cached_token = token
|
||||||
|
_token_created_at = time.monotonic()
|
||||||
_session_error = None
|
_session_error = None
|
||||||
_log("Session created successfully")
|
_log("Session created successfully")
|
||||||
return token
|
return token
|
||||||
@@ -76,8 +84,9 @@ def _create_session(handle: str, app_password: str) -> Optional[str]:
|
|||||||
|
|
||||||
|
|
||||||
def _reset_session_cache() -> None:
|
def _reset_session_cache() -> None:
|
||||||
global _cached_token, _session_error
|
global _cached_token, _token_created_at, _session_error
|
||||||
_cached_token = None
|
_cached_token = None
|
||||||
|
_token_created_at = 0.0
|
||||||
_session_error = None
|
_session_error = None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user