Analysis files not removed reliably on record deletion
When analyses are removed by user action, the associated files are not reliably removed.
diff --git a/tests/api/test_analyses.py b/tests/api/test_analyses.py
index 7571563d8..1eba24d9f 100644
--- a/tests/api/test_analyses.py
+++ b/tests/api/test_analyses.py
@@ -86,10 +86,12 @@ async def test_get(ready, error, mocker, spawn_client, resp_is):
 
 
 @pytest.mark.parametrize("error", [None, "400", "403", "404", "409"])
-async def test_remove(error, spawn_client, resp_is):
+async def test_remove(mocker, error, spawn_client, resp_is):
 
     client = await spawn_client(authorize=True)
 
+    client.app["settings"]["data_path"] = "data"
+
     if error != "400":
         await client.db.samples.insert_one({
             "_id": "baz",
@@ -116,6 +118,8 @@ async def test_remove(error, spawn_client, resp_is):
             }
         })
 
+    m_remove =  mocker.patch("virtool.utils.rm")
+
     resp = await client.delete("/api/analyses/foobar")
 
     if error == "400":
@@ -138,6 +142,8 @@ async def test_remove(error, spawn_client, resp_is):
 
     assert await client.db.analyses.find_one() is None
 
+    assert m_remove.called_with("data/samples/baz/analyses/foobar", True)
+
 
 @pytest.mark.parametrize("error", [None, "400", "403", "404_analysis", "404_sequence", "409_algorithm", "409_ready"])
 async def test_blast(error, mocker, spawn_client, resp_is, static_time):
diff --git a/virtool/api/analyses.py b/virtool/api/analyses.py
index aab632321..9e8ba07f2 100644
--- a/virtool/api/analyses.py
+++ b/virtool/api/analyses.py
@@ -2,6 +2,7 @@
 Provides request handlers for managing and viewing analyses.
 
 """
+import os
 import aiojobs.aiohttp
 
 import virtool.analyses
@@ -80,6 +81,10 @@ async def remove(req):
 
     await db.analyses.delete_one({"_id": analysis_id})
 
+    path = os.path.join(req.app["settings"]["data_path"], "samples", sample_id, "analysis", analysis_id)
+
+    await req.app["run_in_thread"](virtool.utils.rm, path, True)
+
     await virtool.db.samples.recalculate_algorithm_tags(db, sample_id)
 
     return no_content()
['virtool/api/analyses.py', 'tests/api/test_analyses.py']