87 lines
3.0 KiB
Python
87 lines
3.0 KiB
Python
from datetime import datetime, timedelta, timezone
|
|
|
|
import pytest
|
|
|
|
from app.api.v1 import datasources as datasources_api
|
|
from app.models.datasource import DataSource
|
|
|
|
|
|
def make_datasource(
|
|
datasource_id: int,
|
|
source: str,
|
|
*,
|
|
name: str | None = None,
|
|
module: str = "L4",
|
|
is_active: bool = True,
|
|
last_status: str | None = None,
|
|
last_run_at: datetime | None = None,
|
|
frequency_minutes: int = 60,
|
|
) -> DataSource:
|
|
return DataSource(
|
|
id=datasource_id,
|
|
name=name or source,
|
|
source=source,
|
|
module=module,
|
|
priority="P1",
|
|
frequency_minutes=frequency_minutes,
|
|
collector_class=source,
|
|
is_active=is_active,
|
|
last_status=last_status,
|
|
last_run_at=last_run_at,
|
|
)
|
|
|
|
|
|
def test_datasource_product_key_groups_domain_specific_sources():
|
|
assert datasources_api.datasource_product_key(make_datasource(1, "aisstream_vessels")) == "vessels"
|
|
assert datasources_api.datasource_product_key(make_datasource(2, "telegeography_cables")) == "cables"
|
|
assert datasources_api.datasource_product_key(make_datasource(3, "celestrak_tle")) == "satellites"
|
|
assert datasources_api.datasource_product_key(make_datasource(4, "ris_live_bgp")) == "bgp"
|
|
|
|
|
|
def test_filter_datasources_by_product_status_and_collected_state():
|
|
vessels = make_datasource(1, "aisstream_vessels", last_status="success")
|
|
cables = make_datasource(2, "telegeography_cables", last_status="failed")
|
|
filtered = datasources_api._filter_datasources_in_memory(
|
|
[vessels, cables],
|
|
running_tasks={},
|
|
record_counts={"aisstream_vessels": 12, "telegeography_cables": 0},
|
|
product="vessels",
|
|
run_status="success",
|
|
collected=True,
|
|
)
|
|
|
|
assert filtered == [vessels]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_trigger_datasource_batch_skips_disabled_and_frequency_window(monkeypatch):
|
|
now = datetime.now(timezone.utc)
|
|
disabled = make_datasource(1, "aisstream_vessels", is_active=False)
|
|
not_due = make_datasource(2, "telegeography_cables", last_run_at=now, frequency_minutes=120)
|
|
due = make_datasource(3, "ris_live_bgp", last_run_at=now - timedelta(hours=2))
|
|
triggered_sources: list[str] = []
|
|
|
|
async def fake_running_tasks(_db, _ids):
|
|
return {}
|
|
|
|
async def fake_latest_task_ids(_db, _ids):
|
|
return {}
|
|
|
|
monkeypatch.setattr(datasources_api, "_load_latest_running_tasks", fake_running_tasks)
|
|
monkeypatch.setattr(datasources_api, "_load_latest_task_ids", fake_latest_task_ids)
|
|
monkeypatch.setattr(
|
|
datasources_api,
|
|
"run_collector_now",
|
|
lambda source: triggered_sources.append(source) or True,
|
|
)
|
|
|
|
result = await datasources_api._trigger_datasource_batch(
|
|
object(),
|
|
[disabled, not_due, due],
|
|
force=False,
|
|
)
|
|
|
|
assert [item["source"] for item in result["triggered"]] == ["ris_live_bgp"]
|
|
assert {item["reason"] for item in result["skipped"]} == {"disabled", "within_frequency_window"}
|
|
assert triggered_sources == ["ris_live_bgp"]
|