Serve a download from the built book, and delete stale uploads

A download built the book again each time. It now sends the kept build,
and builds only if the book changed after it. Stop tracking deletes the
built book. A cancelled import deletes its uploaded file, and the start
deletes the uploads that no job needs.
This commit is contained in:
tim
2026-10-02 23:37:33 +02:00
parent ff2fa0bf90
commit 679c1ede9f
4 changed files with 130 additions and 17 deletions
+76
View File
@@ -203,3 +203,79 @@ def test_the_first_check_after_an_upgrade_sends_nothing(builds, monkeypatch):
site(monkeypatch, ONE)
assert update(story_id).startswith("No changes")
assert builds.call_count == 0 and ingest_files() == []
# Downloads in the browser
def download(client, story_id):
response = client.get(f"/api/stories/{story_id}/epub")
assert response.status_code == 200 and response.data.startswith(b"PK")
assert response.content_length == len(response.data)
response.close()
return response.data
def test_a_download_uses_the_built_book(builds, client, monkeypatch):
story_id = linked_story(ONE)
site(monkeypatch, ONE)
update(story_id)
(built,) = config.TMP_DIR.iterdir()
assert download(client, story_id) == download(client, story_id) == built.read_bytes()
assert builds.call_count == 1
def test_a_download_builds_a_book_that_has_no_file_or_that_changed(builds, client, monkeypatch):
story_id = add_story()
first = download(client, story_id)
download(client, story_id)
assert builds.call_count == 1
orchestrator.save_rules(story_id, [{"pattern": "Zorian", "replacement": "Zach"}])
assert download(client, story_id) != first
assert builds.call_count == 2
assert len(list(config.TMP_DIR.iterdir())) == 1
# The build of a download is not the build of a job. The job sends the book, and marks the change.
assert orchestrator.store.get_setting(story_id, "built_key") is None
job = Job(mode=DownloadMode.REBUILD, story_id=story_id)
assert "library book 1" in orchestrator._run_rebuild(job)
assert builds.call_count == 2
assert story(story_id)["last_changed"]
def test_stop_tracking_deletes_the_built_book(builds, client):
story_id, other = add_story(), orchestrator.store.create_story("https://other", "s", "Other", "W", [])
download(client, story_id)
kept = config.TMP_DIR / f"story-{other}-0123456789abcdef.epub"
kept.write_bytes(b"other")
orchestrator.delete_story(story_id)
assert list(config.TMP_DIR.iterdir()) == [kept]
# Uploaded files
@pytest.fixture
def uploads(monkeypatch, tmp_path):
monkeypatch.setattr(config, "UPLOAD_DIR", tmp_path / "uploads")
config.UPLOAD_DIR.mkdir()
return config.UPLOAD_DIR
def test_a_cancelled_import_deletes_its_uploaded_file(builds, jobs, uploads, story_epub):
path = uploads / "one.epub"
path.write_bytes(story_epub)
queued = orchestrator.queue_epub_file(path, "story.epub")
assert "path" not in queued["options"]
assert orchestrator.cancel_job(queued["id"]) is True
assert not path.exists()
assert orchestrator.cancel_job(queued["id"]) is False
assert orchestrator.cancel_job("no-such-job") is False
def test_the_start_deletes_uploads_that_no_job_needs(builds, jobs, uploads, story_epub):
waiting, stale = uploads / "waiting.epub", uploads / "stale.epub"
for path in (waiting, stale):
path.write_bytes(story_epub)
orchestrator.queue_epub_file(waiting, "story.epub")
orchestrator.remove_stale_uploads()
assert list(uploads.iterdir()) == [waiting]