update retention policy to a maximum of 2 days for completed archives and adjust related configurations
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from app.db import Database
|
||||
|
||||
|
||||
@@ -62,12 +64,15 @@ def test_sqlite_lease_claims_one_queued_job(tmp_path) -> None:
|
||||
"files_written": 1,
|
||||
},
|
||||
warnings=[],
|
||||
retention_days=1,
|
||||
retention_days=30,
|
||||
)
|
||||
ready = database.get_job(job["id"])
|
||||
assert ready is not None
|
||||
assert ready["state"] == "ready"
|
||||
assert ready["expires_at"] > ready["completed_at"]
|
||||
expires_at = datetime.fromisoformat(ready["expires_at"])
|
||||
completed_at = datetime.fromisoformat(ready["completed_at"])
|
||||
assert expires_at - completed_at <= timedelta(days=2)
|
||||
|
||||
|
||||
def test_worker_cannot_cancel_without_a_user_cancellation_request(tmp_path) -> None:
|
||||
|
||||
+16
-1
@@ -19,6 +19,8 @@ def test_capture_routes_are_scoped_to_the_browser_session(tmp_path, monkeypatch)
|
||||
artifacts_dir=tmp_path / "artifacts",
|
||||
reports_dir=tmp_path / "reports",
|
||||
worker_enabled=False,
|
||||
default_retention_days=2,
|
||||
max_retention_days=2,
|
||||
)
|
||||
test_settings.ensure_directories()
|
||||
test_database = Database(test_settings.database_path)
|
||||
@@ -31,7 +33,8 @@ def test_capture_routes_are_scoped_to_the_browser_session(tmp_path, monkeypatch)
|
||||
with TestClient(main.app) as client:
|
||||
homepage = client.get("/")
|
||||
assert homepage.status_code == 200
|
||||
assert "Copy the web." in homepage.text
|
||||
assert "Archive the web." in homepage.text
|
||||
assert "Website Downloader & Offline Archive Tool" in homepage.text
|
||||
assert client.get("/api/captures").status_code == 401
|
||||
|
||||
created = client.post(
|
||||
@@ -50,6 +53,18 @@ def test_capture_routes_are_scoped_to_the_browser_session(tmp_path, monkeypatch)
|
||||
assert created_job["options"]["parallel_connections"] == 2
|
||||
assert created_job["options"]["download_asset_types"] == ["styles", "images"]
|
||||
assert created_job["options"]["skip_file_types"] == ["pdf", "zip"]
|
||||
assert created_job["options"]["retention_days"] == 2
|
||||
|
||||
capabilities = client.get("/api/capabilities")
|
||||
assert capabilities.status_code == 200
|
||||
assert capabilities.json()["limits"]["max_retention_days"] == 2
|
||||
|
||||
rejected_retention = client.post(
|
||||
"/api/captures",
|
||||
headers={"X-SiteHarbor-Session": owner_a},
|
||||
json={"url": "https://example.com", "retention_days": 3},
|
||||
)
|
||||
assert rejected_retention.status_code == 422
|
||||
|
||||
assert client.get(
|
||||
f"/api/captures/{job_id}", headers={"X-SiteHarbor-Session": owner_b}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import replace
|
||||
|
||||
from app.config import settings
|
||||
from app.db import Database
|
||||
from app.scheduler import JobRunner
|
||||
|
||||
|
||||
def test_maintenance_removes_archives_after_two_days(tmp_path) -> None:
|
||||
test_settings = replace(
|
||||
settings,
|
||||
data_dir=tmp_path,
|
||||
database_path=tmp_path / "siteharbor.sqlite3",
|
||||
work_dir=tmp_path / "work",
|
||||
artifacts_dir=tmp_path / "artifacts",
|
||||
reports_dir=tmp_path / "reports",
|
||||
worker_enabled=False,
|
||||
)
|
||||
test_settings.ensure_directories()
|
||||
database = Database(test_settings.database_path)
|
||||
database.initialize()
|
||||
job = database.create_job(
|
||||
"https://example.com",
|
||||
"https://example.com/",
|
||||
{
|
||||
"include_external_assets": True,
|
||||
"max_pages": 20,
|
||||
"max_depth": 3,
|
||||
"max_bytes": 1_000_000,
|
||||
"max_duration_seconds": 60,
|
||||
"retention_days": 2,
|
||||
},
|
||||
)
|
||||
assert database.claim_next("worker-a", lease_seconds=30)
|
||||
|
||||
archive_path = test_settings.artifacts_dir / "capture.zip"
|
||||
report_path = test_settings.reports_dir / "capture.json"
|
||||
archive_path.write_bytes(b"zip contents")
|
||||
report_path.write_text("{}", encoding="utf-8")
|
||||
assert database.mark_ready(
|
||||
job["id"],
|
||||
"worker-a",
|
||||
artifact_path=str(archive_path),
|
||||
report_path=str(report_path),
|
||||
archive_size=archive_path.stat().st_size,
|
||||
entry_point="example.com/index.html",
|
||||
stats={},
|
||||
warnings=[],
|
||||
retention_days=2,
|
||||
)
|
||||
with database.connection() as connection:
|
||||
connection.execute(
|
||||
"""
|
||||
UPDATE jobs
|
||||
SET completed_at = '2000-01-01T00:00:00+00:00',
|
||||
expires_at = '2100-01-01T00:00:00+00:00'
|
||||
WHERE id = ?
|
||||
""",
|
||||
(job["id"],),
|
||||
)
|
||||
|
||||
JobRunner(database, test_settings)._expire_artifacts_if_due()
|
||||
|
||||
expired = database.get_job(job["id"])
|
||||
assert expired is not None
|
||||
assert expired["state"] == "expired"
|
||||
assert not archive_path.exists()
|
||||
assert not report_path.exists()
|
||||
Reference in New Issue
Block a user