feat(service-storage-harness): slice 4 — cascade-delete wiring + integration test

Wire ServiceDataHarness.cascade_delete into SettingsStore.delete_service
(best-effort try/except, logs on failure). Fix migration runner to also
catch 'no such table' on fresh DBs (ALTER TABLE before init_schema).
Integration test proves end-to-end cascade across both concerns (qBit
samples + media items) with multi-instance preservation.

Backend: 322 pytest pass, ruff clean.
This commit is contained in:
Developer
2026-07-09 09:11:42 +00:00
parent c87f398e37
commit 75c949ad25
4 changed files with 99 additions and 22 deletions
+15 -19
View File
@@ -228,16 +228,20 @@ class TestMediaIndexQuery:
class TestMediaIndexReplace:
def test_replace_clears_old(self, index):
index.replace_items([
{"id": "x", "title": "Old", "type": "Movie", "library_id": "l1", "library_name": "L1"},
])
index.replace_items(
[
{"id": "x", "title": "Old", "type": "Movie", "library_id": "l1", "library_name": "L1"},
]
)
status = index.status()
assert status.item_count == 1
index.replace_items([
{"id": "y", "title": "New1", "type": "Movie", "library_id": "l1", "library_name": "L1"},
{"id": "z", "title": "New2", "type": "Movie", "library_id": "l1", "library_name": "L1"},
])
index.replace_items(
[
{"id": "y", "title": "New1", "type": "Movie", "library_id": "l1", "library_name": "L1"},
{"id": "z", "title": "New2", "type": "Movie", "library_id": "l1", "library_name": "L1"},
]
)
status = index.status()
assert status.item_count == 2
@@ -335,15 +339,11 @@ class TestMediaIndexBuildPaths:
self.calls.append(kwargs.get("start_index", 0))
if kwargs.get("start_index", 0) == 0:
return {
"Items": [
{"Id": "m1", "Name": "Movie One", "Type": "Movie", "Path": "/media/a.mkv"}
],
"Items": [{"Id": "m1", "Name": "Movie One", "Type": "Movie", "Path": "/media/a.mkv"}],
"TotalRecordCount": 2,
}
return {
"Items": [
{"Id": "m2", "Name": "Movie Two", "Type": "Movie", "Path": "/media/b.mkv"}
],
"Items": [{"Id": "m2", "Name": "Movie Two", "Type": "Movie", "Path": "/media/b.mkv"}],
"TotalRecordCount": 2,
}
@@ -379,15 +379,11 @@ class TestMediaIndexBuildPaths:
self.calls.append(kwargs.get("start_index", 0))
if kwargs.get("start_index", 0) == 0:
return {
"Items": [
{"Id": "m1", "Name": "Movie One", "Type": "Movie", "Path": "/media/a.mkv"}
],
"Items": [{"Id": "m1", "Name": "Movie One", "Type": "Movie", "Path": "/media/a.mkv"}],
"TotalRecordCount": 2,
}
return {
"Items": [
{"Id": "m2", "Name": "Movie Two", "Type": "Movie", "Path": "/media/b.mkv"}
],
"Items": [{"Id": "m2", "Name": "Movie Two", "Type": "Movie", "Path": "/media/b.mkv"}],
"TotalRecordCount": 2,
}