# Path: virtool/references/tasks.py
# class UpdateRemoteReferenceTask(Task):
#     task_type = "update_remote_reference"
# 
#     def __init__(self, *args):
#         super().__init__(*args)
# 
#         self.steps = [
#             self.download_and_extract,
#             self.update_otus,
#             self.create_history,
#             self.remove_otus,
#             self.update_reference,
#         ]
# 
#     async def download_and_extract(self):
#         url = self.context["release"]["download_url"]
#         file_size = self.context["release"]["size"]
# 
#         tracker = await self.get_tracker(file_size)
# 
#         try:
#             with get_temp_dir() as tempdir:
#                 download_path = Path(tempdir) / "reference.tar.gz"
# 
#                 await download_file(self.app, url, download_path, tracker.add)
# 
#                 self.intermediate["update_data"] = await self.run_in_thread(
#                     load_reference_file, download_path
#                 )
# 
#         except (aiohttp.ClientConnectorError, virtool.errors.GitHubError):
#             return await self.error("Could not download reference data")
# 
#         await virtool.tasks.pg.update(self.pg, self.id, step="download_and_extract")
# 
#     async def update_otus(self):
#         update_data = self.intermediate["update_data"]
# 
#         tracker = await self.get_tracker(len(update_data["otus"]))
# 
#         # The remote ids in the update otus.
#         otu_ids_in_update = {otu["_id"] for otu in update_data["otus"]}
# 
#         updated_list = list()
# 
#         for otu in update_data["otus"]:
#             old_or_id = await update_joined_otu(
#                 self.db,
#                 otu,
#                 self.context["created_at"],
#                 self.context["ref_id"],
#                 self.context["user_id"],
#             )
# 
#             if old_or_id is not None:
#                 updated_list.append(old_or_id)
# 
#             await tracker.add(1)
# 
#         self.intermediate.update(
#             {"otu_ids_in_update": otu_ids_in_update, "updated_list": updated_list}
#         )
# 
#         await virtool.tasks.pg.update(self.pg, self.id, step="update_otus")
# 
#     async def create_history(self):
#         updated_list = self.intermediate["updated_list"]
# 
#         tracker = await self.get_tracker(len(updated_list))
# 
#         for old_or_id in updated_list:
#             try:
#                 otu_id = old_or_id["_id"]
#                 old = old_or_id
#             except TypeError:
#                 otu_id = old_or_id
#                 old = None
# 
#             await insert_change(
#                 self.app,
#                 otu_id,
#                 "update" if old else "remote",
#                 self.context["user_id"],
#                 old,
#             )
# 
#             await tracker.add(1)
# 
#         await virtool.tasks.pg.update(self.pg, self.id, step="create_history")
# 
#     async def remove_otus(self):
#         # Delete OTUs with remote ids that were not in the update.
#         to_delete = await self.db.otus.distinct(
#             "_id",
#             {
#                 "reference.id": self.context["ref_id"],
#                 "remote.id": {"$nin": list(self.intermediate["otu_ids_in_update"])},
#             },
#         )
# 
#         tracker = await self.get_tracker(len(to_delete))
# 
#         for otu_id in to_delete:
#             await virtool.otus.db.remove(self.app, otu_id, self.context["user_id"])
# 
#             await tracker.add(1)
# 
#         await virtool.tasks.pg.update(self.pg, self.id, step="remove_otus")
# 
#     async def update_reference(self):
#         tracker = await self.get_tracker()
#         ref_id = self.context["ref_id"]
#         release = self.context["release"]
# 
#         await self.db.references.update_one(
#             {"_id": ref_id, "updates.id": release["id"]},
#             {
#                 "$set": {
#                     "installed": create_update_subdocument(
#                         release, True, self.context["user_id"]
#                     ),
#                     "updates.$.ready": True,
#                 }
#             },
#         )
# 
#         await fetch_and_update_release(self.app, ref_id)
# 
#         await self.db.references.update_one(
#             {"_id": ref_id}, {"$set": {"updating": False}}
#         )
# 
#         await virtool.tasks.pg.update(
#             self.pg, self.id, progress=tracker.step_completed, step="update_reference"
#         )


import pytest
from aiohttp.test_utils import make_mocked_coro
from aiohttp.web import Request
from virtool.references.tasks import UpdateRemoteReferenceTask
    mocker.patch("virtool.references.tasks.UpdateRemoteReferenceTask")

    m_add_task = mocker.patch(
        "virtool.tasks.client.TasksClient.add", make_mocked_coro({"id": "task"})
    )

    mocker.patch("aiojobs.aiohttp.spawn", make_mocked_coro())

    m_update = mocker.patch(
        "virtool.references.db.update",
        make_mocked_coro(({"id": "bar"}, {"id": "update", "created_at": "time"})),
    )

    resp = await client.post("/refs/foo/updates")

    id_exists.assert_called_with(client.db.references, "foo")

    if not id_exists:
        await resp_is.not_found(resp)
        return

    if not check_ref_right:
        await resp_is.insufficient_rights(resp)
        return

    if error == "400":
        await resp_is.bad_request(resp, "Target release does not exist")
        return

    m_add_task.assert_called_with(

# Path: virtool/references/tasks.py
# class UpdateRemoteReferenceTask(Task):
#     task_type = "update_remote_reference"
# 
#     def __init__(self, *args):
#         super().__init__(*args)
# 
#         self.steps = [
#             self.download_and_extract,
#             self.update_otus,
#             self.create_history,
#             self.remove_otus,
#             self.update_reference,
#         ]
# 
#     async def download_and_extract(self):
#         url = self.context["release"]["download_url"]
#         file_size = self.context["release"]["size"]
# 
#         tracker = await self.get_tracker(file_size)
# 
#         try:
#             with get_temp_dir() as tempdir:
#                 download_path = Path(tempdir) / "reference.tar.gz"
# 
#                 await download_file(self.app, url, download_path, tracker.add)
# 
#                 self.intermediate["update_data"] = await self.run_in_thread(
#                     load_reference_file, download_path
#                 )
# 
#         except (aiohttp.ClientConnectorError, virtool.errors.GitHubError):
#             return await self.error("Could not download reference data")
# 
#         await virtool.tasks.pg.update(self.pg, self.id, step="download_and_extract")
# 
#     async def update_otus(self):
#         update_data = self.intermediate["update_data"]
# 
#         tracker = await self.get_tracker(len(update_data["otus"]))
# 
#         # The remote ids in the update otus.
#         otu_ids_in_update = {otu["_id"] for otu in update_data["otus"]}
# 
#         updated_list = list()
# 
#         for otu in update_data["otus"]:
#             old_or_id = await update_joined_otu(
#                 self.db,
#                 otu,
#                 self.context["created_at"],
#                 self.context["ref_id"],
#                 self.context["user_id"],
#             )
# 
#             if old_or_id is not None:
#                 updated_list.append(old_or_id)
# 
#             await tracker.add(1)
# 
#         self.intermediate.update(
#             {"otu_ids_in_update": otu_ids_in_update, "updated_list": updated_list}
#         )
# 
#         await virtool.tasks.pg.update(self.pg, self.id, step="update_otus")
# 
#     async def create_history(self):
#         updated_list = self.intermediate["updated_list"]
# 
#         tracker = await self.get_tracker(len(updated_list))
# 
#         for old_or_id in updated_list:
#             try:
#                 otu_id = old_or_id["_id"]
#                 old = old_or_id
#             except TypeError:
#                 otu_id = old_or_id
#                 old = None
# 
#             await insert_change(
#                 self.app,
#                 otu_id,
#                 "update" if old else "remote",
#                 self.context["user_id"],
#                 old,
#             )
# 
#             await tracker.add(1)
# 
#         await virtool.tasks.pg.update(self.pg, self.id, step="create_history")
# 
#     async def remove_otus(self):
#         # Delete OTUs with remote ids that were not in the update.
#         to_delete = await self.db.otus.distinct(
#             "_id",
#             {
#                 "reference.id": self.context["ref_id"],
#                 "remote.id": {"$nin": list(self.intermediate["otu_ids_in_update"])},
#             },
#         )
# 
#         tracker = await self.get_tracker(len(to_delete))
# 
#         for otu_id in to_delete:
#             await virtool.otus.db.remove(self.app, otu_id, self.context["user_id"])
# 
#             await tracker.add(1)
# 
#         await virtool.tasks.pg.update(self.pg, self.id, step="remove_otus")
# 
#     async def update_reference(self):
#         tracker = await self.get_tracker()
#         ref_id = self.context["ref_id"]
#         release = self.context["release"]
# 
#         await self.db.references.update_one(
#             {"_id": ref_id, "updates.id": release["id"]},
#             {
#                 "$set": {
#                     "installed": create_update_subdocument(
#                         release, True, self.context["user_id"]
#                     ),
#                     "updates.$.ready": True,
#                 }
#             },
#         )
# 
#         await fetch_and_update_release(self.app, ref_id)
# 
#         await self.db.references.update_one(
#             {"_id": ref_id}, {"$set": {"updating": False}}
#         )
# 
#         await virtool.tasks.pg.update(
#             self.pg, self.id, progress=tracker.step_completed, step="update_reference"
#         )


# Path: tests/references/test_api.py
import pytest
from aiohttp.test_utils import make_mocked_coro
from aiohttp.web import Request
from virtool.references.tasks import UpdateRemoteReferenceTask

    mocker.patch("virtool.references.tasks.UpdateRemoteReferenceTask")

    m_add_task = mocker.patch(
        "virtool.tasks.client.TasksClient.add", make_mocked_coro({"id": "task"})
    )

    mocker.patch("aiojobs.aiohttp.spawn", make_mocked_coro())

    m_update = mocker.patch(
        "virtool.references.db.update",
        make_mocked_coro(({"id": "bar"}, {"id": "update", "created_at": "time"})),
    )

    resp = await client.post("/refs/foo/updates")

    id_exists.assert_called_with(client.db.references, "foo")

    if not id_exists:
        await resp_is.not_found(resp)
        return

    if not check_ref_right:
        await resp_is.insufficient_rights(resp)
        return

    if error == "400":
        await resp_is.bad_request(resp, "Target release does not exist")
        return

    m_add_task.assert_called_with(

        UpdateRemoteReferenceTask,