feat: expose safe source health status
This commit is contained in:
@@ -16,6 +16,15 @@ from .logging_config import configure_logging
|
||||
from .models import CommunityImportRun, DataSource
|
||||
|
||||
logger = logging.getLogger("rf4.community_scheduler")
|
||||
MAX_BACKOFF_SECONDS = 24 * 60 * 60
|
||||
|
||||
def retry_delay(statuses: list[str]) -> int:
|
||||
failures = 0
|
||||
for status in statuses:
|
||||
if status != "failed":
|
||||
break
|
||||
failures += 1
|
||||
return min(settings.community_import_interval_seconds * (2 ** max(0, failures - 1)), MAX_BACKOFF_SECONDS)
|
||||
|
||||
def configured_sources():
|
||||
return {
|
||||
@@ -33,8 +42,10 @@ def run_source(source_system: str, *, now: datetime | None = None) -> bool:
|
||||
source = session.get(DataSource, source_system)
|
||||
if source is None or not source.enabled:
|
||||
return False
|
||||
latest = session.scalar(select(CommunityImportRun.started_at).where(CommunityImportRun.source_system == source_system).order_by(CommunityImportRun.started_at.desc()).limit(1))
|
||||
if latest and (latest if latest.tzinfo else latest.replace(tzinfo=timezone.utc)) > current - timedelta(seconds=settings.community_import_interval_seconds):
|
||||
recent = list(session.scalars(select(CommunityImportRun).where(CommunityImportRun.source_system == source_system).order_by(CommunityImportRun.started_at.desc()).limit(8)))
|
||||
latest = recent[0].started_at if recent else None
|
||||
delay = retry_delay([run.status for run in recent])
|
||||
if latest and (latest if latest.tzinfo else latest.replace(tzinfo=timezone.utc)) > current - timedelta(seconds=delay):
|
||||
return False
|
||||
if session.bind and session.bind.dialect.name == "postgresql" and not session.scalar(text("select pg_try_advisory_xact_lock(hashtext(:key))"), {"key": f"community:{source_system}"}):
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user