fix: bound orphaned snapshot recovery
Some checks are pending
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Waiting to run
Build Debian package / build (amd64) (push) Waiting to run
Build Debian package / build (arm64) (push) Waiting to run
Build Debian package / test (amd64, ubuntu-24.04) (push) Blocked by required conditions
Build Debian package / test (arm64, ubuntu-24.04-arm) (push) Blocked by required conditions
Build Debian package / release (push) Blocked by required conditions
Build Docker image / buildx (push) Waiting to run
Run linters / lint (push) Waiting to run
Build Pip package / build (push) Waiting to run
Release State / release-state (push) Waiting to run
Parallel Tests / Discover test files (push) Waiting to run
Parallel Tests / ${{ matrix.test.name }} (push) Blocked by required conditions
Parallel Tests / ${{ matrix.plugin.name }} (push) Blocked by required conditions
Run tests / python_tests (ubuntu-22.04, 3.13) (push) Waiting to run
Run tests / docker_tests (push) Waiting to run

This commit is contained in:
Nick Sweeting 2026-05-27 20:38:42 -07:00
parent 539fa0cb4d
commit 6d7593be53
No known key found for this signature in database

View File

@ -11,6 +11,7 @@ import sys
import time
from collections.abc import Mapping
from contextlib import nullcontext
from datetime import timedelta
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Any
@ -1104,14 +1105,17 @@ def recover_orphaned_crawls() -> int:
retry_at__isnull=True,
).prefetch_related("snapshot_set"),
)
running_processes = Process.objects.filter(
status=Process.StatusChoices.RUNNING,
process_type__in=[
Process.TypeChoices.WORKER,
Process.TypeChoices.HOOK,
Process.TypeChoices.BINARY,
],
).only("pwd")
running_processes = (
Process.get_running()
.filter(
process_type__in=[
Process.TypeChoices.WORKER,
Process.TypeChoices.HOOK,
Process.TypeChoices.BINARY,
],
)
.only("pwd")
)
for proc in running_processes:
if not proc.pwd:
@ -1161,8 +1165,10 @@ def recover_orphaned_snapshots() -> int:
from archivebox.crawls.models import Crawl
from archivebox.core.models import ArchiveResult, Snapshot
from archivebox.machine.models import Process
from django.db.models import Exists, OuterRef
active_snapshot_ids: set[str] = set()
now = timezone.now()
orphaned_snapshots = list(
Snapshot.objects.filter(status=Snapshot.StatusChoices.STARTED, retry_at__isnull=True)
.select_related("crawl")
@ -1180,28 +1186,39 @@ def recover_orphaned_snapshots() -> int:
.prefetch_related("archiveresult_set")
if snapshot.status == Snapshot.StatusChoices.SEALED
)
empty_active_snapshot_ids = list(
Snapshot.objects.filter(
crawl__status__in=[Crawl.StatusChoices.STARTED, Crawl.StatusChoices.SEALED],
status=Snapshot.StatusChoices.SEALED,
downloaded_at__isnull=False,
archiveresult__isnull=True,
recent_active_crawl_ids = list(
Crawl.objects.filter(
status__in=[Crawl.StatusChoices.STARTED, Crawl.StatusChoices.SEALED],
modified_at__gte=now - timedelta(days=1),
)
.values_list("id", flat=True)
.distinct(),
.order_by("-modified_at")
.values_list("id", flat=True)[:1000],
)
if empty_active_snapshot_ids:
if recent_active_crawl_ids:
orphaned_snapshots.extend(
Snapshot.objects.filter(id__in=empty_active_snapshot_ids).select_related("crawl").prefetch_related("archiveresult_set"),
Snapshot.objects.filter(
crawl_id__in=recent_active_crawl_ids,
status=Snapshot.StatusChoices.SEALED,
downloaded_at__isnull=False,
)
.annotate(has_results=Exists(ArchiveResult.objects.filter(snapshot_id=OuterRef("pk"))))
.filter(has_results=False)
.select_related("crawl")
.prefetch_related("archiveresult_set")
.order_by("-modified_at")[:1000],
)
running_processes = Process.objects.filter(
status=Process.StatusChoices.RUNNING,
process_type__in=[
Process.TypeChoices.WORKER,
Process.TypeChoices.HOOK,
Process.TypeChoices.BINARY,
],
).only("pwd")
running_processes = (
Process.get_running()
.filter(
process_type__in=[
Process.TypeChoices.WORKER,
Process.TypeChoices.HOOK,
Process.TypeChoices.BINARY,
],
)
.only("pwd")
)
for proc in running_processes:
if not proc.pwd:
@ -1216,7 +1233,6 @@ def recover_orphaned_snapshots() -> int:
continue
recovered = 0
now = timezone.now()
for snapshot in orphaned_snapshots:
if str(snapshot.id) in active_snapshot_ids:
continue