GopeedLab / gopeed

A modern download manager that supports all platforms. Built with Golang and Flutter.
https://gopeed.com
GNU General Public License v3.0
15.65k stars 1.12k forks source link

Task file naming problem. #609

Closed tick97115115 closed 4 weeks ago

tick97115115 commented 1 month ago

App Version 1.57

OS Version Windows 11

Description & Snapshots

If using RestAPI's Create a batch tasks endpoint to create some duplicated tasks, the actual file names don't match with task file info.

I created two duplicate tasks in below, there are two identical "index.html" files.

    def test_create_and_delete_a_batch_of_tasks(self):
        from gospeed_api.models.create_a_batch_of_tasks import TaskUrl, CreateABatchOfTasks, CreateABatchOfTasks_Response
        from gospeed_api.models.create_a_task import CreateTask_DownloadOpt
        from gospeed_api.models.get_task_info import GetTaskInfo_Response
        from gospeed_api.models import TASK_STATUS
        from gospeed_api.models.delete_a_task import DeleteATask_Response
        url1 = TaskUrl(url='https://example.com/index.html')
        url2 = TaskUrl(url='https://example.com/index.html')

        # define download opt
        opt = CreateTask_DownloadOpt(path=tempfile.gettempdir())
        # Create download task
        tasks = CreateABatchOfTasks(reqs=[url1, url2], opt=opt)
        res_data: CreateABatchOfTasks_Response = self.client.create_a_batch_of_tasks(data=tasks)

As you can see here, there are two files and their names don't math with the tasks inside Gopeed UI:

Screenshot 2024-07-14 220106

I tried to delete these two tasks by invoking the "delete one task" endpoint one by one, then the result was only one file, whose name can be matched the task file info, was deleted, but the other one still remained in system.

......
        res_data: CreateABatchOfTasks_Response = self.client.create_a_batch_of_tasks(data=tasks)
        assert res_data.code == 0
        assert len(res_data.data) == 2

        while True:
            time.sleep(2)
            task1_info: GetTaskInfo_Response = self.client.get_task_info(res_data.data[0])
            task2_info: GetTaskInfo_Response = self.client.get_task_info(res_data.data[1])
            # check task status and delete them
            if (task1_info.data.status == TASK_STATUS.DONE and task2_info.data.status == TASK_STATUS.DONE and task1_info.data.id != task2_info.data.id):
                task1_delete_res: DeleteATask_Response = self.client.delete_a_task(rid=task1_info.data.id, force=True)
                time.sleep(2)
                task2_delete_res: DeleteATask_Response = self.client.delete_a_task(rid=task2_info.data.id, force=True)
                # For avoid test exception, in here I delete them one by one, please take much care when use this function.
                # delete all exists tasks, like below: 
                # self.client.delete_tasks(status={TASK_STATUS.DONE, TASK_STATUS.ERROR}, force=True)
                assert task1_delete_res.code == 0
                assert task2_delete_res.code == 0
                break

Screenshot 2024-07-14 221453

I re-ran the script to download the two index.html files again, and tried to delete both of them using the UI's delete button. The result was same as before.

My deduction regarding the problem is that the batch download endpoint logic cannot handle duplicate task info appropriately. Because it seems like the delete logic is based on task info, if the task info isn't correct, then the delete logic goes wrong.

The full unit test code can be found in here: test_create_and_delete_a_batch_of_tasks

monkeyWie commented 1 month ago

Thanks for your feedback. This seems to be caused by a concurrency issue. I'll check it out.