perf: eliminate source health N plus one queries
This commit is contained in:
@@ -4,6 +4,7 @@ from collections.abc import Iterable
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
from django.db.models import Prefetch
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from apps.sources.models import Source, SourcePolicyReview, SourceRun
|
from apps.sources.models import Source, SourcePolicyReview, SourceRun
|
||||||
@@ -214,12 +215,17 @@ def _determine_health_action(runs: list[SourceRun]) -> tuple[str | None, str | N
|
|||||||
def collect_source_health(
|
def collect_source_health(
|
||||||
*, runs_to_consider: int = SOURCE_HEALTH_RUN_WINDOW
|
*, runs_to_consider: int = SOURCE_HEALTH_RUN_WINDOW
|
||||||
) -> list[SourceHealth]:
|
) -> list[SourceHealth]:
|
||||||
sources = Source.objects.order_by("name").all()
|
sources = Source.objects.prefetch_related(
|
||||||
|
Prefetch(
|
||||||
|
"runs",
|
||||||
|
queryset=SourceRun.objects.order_by("-started_at")[:runs_to_consider],
|
||||||
|
to_attr="health_runs",
|
||||||
|
)
|
||||||
|
).order_by("name")
|
||||||
rows: list[SourceHealth] = []
|
rows: list[SourceHealth] = []
|
||||||
|
|
||||||
for source in sources:
|
for source in sources:
|
||||||
run_queryset = SourceRun.objects.filter(source=source).order_by("-started_at")
|
runs = source.health_runs
|
||||||
runs = list(run_queryset[:runs_to_consider])
|
|
||||||
monitored_runs = len(runs)
|
monitored_runs = len(runs)
|
||||||
success_runs = [run for run in runs if run.status == SourceRun.Status.SUCCESS]
|
success_runs = [run for run in runs if run.status == SourceRun.Status.SUCCESS]
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,25 @@ def test_collect_source_health_exposes_parser_and_counts(source):
|
|||||||
assert row.updated_count == 1
|
assert row.updated_count == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_collect_source_health_prefetches_runs_for_all_sources(source, django_assert_num_queries):
|
||||||
|
second_source = Source.objects.create(
|
||||||
|
name="Second jobs",
|
||||||
|
source_type=Source.Type.EMPLOYER,
|
||||||
|
base_url="https://second.example.org/jobs/",
|
||||||
|
domain="second.example.org",
|
||||||
|
status=Source.Status.ACTIVE,
|
||||||
|
policy=Source.Policy.ALLOW,
|
||||||
|
)
|
||||||
|
_create_run(source, status=SourceRun.Status.SUCCESS)
|
||||||
|
_create_run(second_source, status=SourceRun.Status.SUCCESS)
|
||||||
|
|
||||||
|
with django_assert_num_queries(2):
|
||||||
|
rows = collect_source_health()
|
||||||
|
|
||||||
|
assert [row.source_name for row in rows] == ["Example jobs", "Second jobs"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_recover_source_health_starts_canary_once(source, monkeypatch):
|
def test_recover_source_health_starts_canary_once(source, monkeypatch):
|
||||||
source.status = Source.Status.QUARANTINED
|
source.status = Source.Status.QUARANTINED
|
||||||
|
|||||||
Reference in New Issue
Block a user