diff --git a/arkindex/process/serializers/imports.py b/arkindex/process/serializers/imports.py index 9a345d520c403ca3be27bf5a43a04c8f591242cb..ef42f8524e3ba42c4cba4f58756ea18d7fed3c0e 100644 --- a/arkindex/process/serializers/imports.py +++ b/arkindex/process/serializers/imports.py @@ -600,7 +600,10 @@ class ExportProcessSerializer(ProcessDetailsSerializer): # https://docs.djangoproject.com/en/5.1/ref/models/instances/#state if export._state.adding: export.save() - export.start() + # We must only start after the transaction completes, as the task might be started very quickly by an RQ worker + # before the transaction completes and the CorpusExport does not fully exist in DB yet + transaction.on_commit(export.start) + # Get or create the worker configuration worker_configuration, _ = worker_version.worker.configurations.get_or_create( configuration={**validated_data["configuration"], "export_id": str(export.id)}, diff --git a/arkindex/process/tests/process/test_export_process.py b/arkindex/process/tests/process/test_export_process.py index 3fd3d5b8eb4a3030a39145bdc06c6c107549dc7c..7a311291a3aa8471ee4cba7b582a871cf9c5d738 100644 --- a/arkindex/process/tests/process/test_export_process.py +++ b/arkindex/process/tests/process/test_export_process.py @@ -426,7 +426,7 @@ class TestExportProcess(FixtureAPITestCase): def test_create_export_process_new_sql_export(self, delay_mock): self.client.force_login(self.user) - with self.assertNumQueries(26): + with self.assertNumQueries(26), self.captureOnCommitCallbacks(execute=True): response = self.client.post( reverse("api:export-process", kwargs={"corpus_id": str(self.corpus.id)}), { @@ -438,6 +438,7 @@ class TestExportProcess(FixtureAPITestCase): }, ) self.assertEqual(response.status_code, status.HTTP_201_CREATED) + created_process = Process.objects.get(mode=ProcessMode.Export) created_run = created_process.worker_runs.get() new_export = self.corpus.exports.order_by("-created").first() @@ -455,11 +456,19 @@ class TestExportProcess(FixtureAPITestCase): "page_type": "page" }) + # The new SQLite export has been started + self.assertEqual(delay_mock.call_count, 1) + self.assertEqual(delay_mock.call_args, call( + corpus_export=new_export, + user_id=self.user.id, + description="Export of corpus Unit Tests", + )) + @patch("arkindex.project.triggers.export.local_export.delay") def test_create_export_process_new_sql_export_with_element(self, delay_mock): self.client.force_login(self.user) - with self.assertNumQueries(30): + with self.assertNumQueries(30), self.captureOnCommitCallbacks(execute=True): response = self.client.post( reverse("api:export-process", kwargs={"corpus_id": str(self.corpus.id)}), { @@ -472,6 +481,7 @@ class TestExportProcess(FixtureAPITestCase): }, ) self.assertEqual(response.status_code, status.HTTP_201_CREATED) + created_process = Process.objects.get(mode=ProcessMode.Export) created_run = created_process.worker_runs.get() new_export = self.corpus.exports.order_by("-created").first() @@ -490,13 +500,21 @@ class TestExportProcess(FixtureAPITestCase): "page_type": "page" }) + # The new SQLite export has been started + self.assertEqual(delay_mock.call_count, 1) + self.assertEqual(delay_mock.call_args, call( + corpus_export=new_export, + user_id=self.user.id, + description="Export of corpus Unit Tests", + )) + @patch("arkindex.project.triggers.export.local_export.delay") def test_create_export_process_new_sql_export_with_selection(self, delay_mock): self.client.force_login(self.user) self.user.selected_elements.add(self.corpus_element) self.user.selected_elements.add(self.other_element) - with self.assertNumQueries(29): + with self.assertNumQueries(29), self.captureOnCommitCallbacks(execute=True): response = self.client.post( reverse("api:export-process", kwargs={"corpus_id": str(self.corpus.id)}), { @@ -527,6 +545,14 @@ class TestExportProcess(FixtureAPITestCase): "page_type": "page" }) + # The new SQLite export has been started + self.assertEqual(delay_mock.call_count, 1) + self.assertEqual(delay_mock.call_args, call( + corpus_export=new_export, + user_id=self.user.id, + description="Export of corpus Unit Tests", + )) + def test_farm(self): farm = Farm.objects.get() self.client.force_login(self.user)