diff --git a/src/conductor/client/automator/async_task_runner.py b/src/conductor/client/automator/async_task_runner.py index 41e7ab56..c0e601f2 100644 --- a/src/conductor/client/automator/async_task_runner.py +++ b/src/conductor/client/automator/async_task_runner.py @@ -841,11 +841,12 @@ async def __async_update_task(self, task_result: TaskResult): ) return None except ApiException as e: - if e.status == 404 and self._use_update_v2: + if e.status in (404, 405) and self._use_update_v2: logger.warning( - "Server does not support update-task-v2 endpoint (HTTP 404). " + "Server does not support update-task-v2 endpoint (HTTP %d). " "Falling back to v1 update endpoint. " - "Upgrade your Conductor instance to v5+ to enable the v2 endpoint." + "Upgrade your Conductor instance to v5+ to enable the v2 endpoint.", + e.status, ) self._use_update_v2 = False # Retry immediately with v1 diff --git a/src/conductor/client/automator/task_runner.py b/src/conductor/client/automator/task_runner.py index 7168edf5..dbc97f18 100644 --- a/src/conductor/client/automator/task_runner.py +++ b/src/conductor/client/automator/task_runner.py @@ -871,11 +871,12 @@ def __update_task(self, task_result: TaskResult): ) return None except ApiException as e: - if e.status == 404 and self._use_update_v2: + if e.status in (404, 405) and self._use_update_v2: logger.warning( - "Server does not support update-task-v2 endpoint (HTTP 404). " + "Server does not support update-task-v2 endpoint (HTTP %d). " "Falling back to v1 update endpoint. " - "Upgrade your Orkes instance to v5+ to enable the v2 endpoint." + "Upgrade your Orkes instance to v5+ to enable the v2 endpoint.", + e.status, ) self._use_update_v2 = False # Retry immediately with v1 diff --git a/tests/unit/automator/test_task_runner_coverage.py b/tests/unit/automator/test_task_runner_coverage.py index d7b0ba91..e2d474bf 100644 --- a/tests/unit/automator/test_task_runner_coverage.py +++ b/tests/unit/automator/test_task_runner_coverage.py @@ -829,6 +829,29 @@ def test_update_task_v2_404_falls_back_to_v1(self): mock_v1.assert_called_once() self.assertIsNone(result) + @patch('time.sleep', Mock(return_value=None)) + def test_update_task_v2_405_falls_back_to_v1(self): + """When server returns 405 for v2 endpoint (older Conductor), should fall back to v1.""" + worker = MockWorker('test_task') + task_runner = TaskRunner(worker=worker) + + task_result = TaskResult( + task_id='test_id', + workflow_instance_id='wf_id', + worker_id=worker.get_identity(), + status=TaskResultStatus.COMPLETED + ) + + with patch.object(TaskResourceApi, 'update_task_v2', + side_effect=ApiException(status=405)) as mock_v2, \ + patch.object(TaskResourceApi, 'update_task', return_value='ok') as mock_v1: + result = task_runner._TaskRunner__update_task(task_result) + + mock_v2.assert_called_once() + mock_v1.assert_called_once() + self.assertIsNone(result) + self.assertFalse(task_runner._use_update_v2) + @patch('time.sleep', Mock(return_value=None)) def test_update_task_v2_404_sets_v1_flag(self): """After a 404 on v2, _use_update_v2 flag must be False."""