@@ -878,9 +878,7 @@ async def test_workflow_with_envelope_arguments(self, mock_client: AsyncMock) ->
878878
879879
880880class TestCodecDecodeFailures :
881- """TD-P012 / #370 regression: codec decode failures at the task boundary
882- must turn into a deterministic fail_{workflow,activity}_task call so the
883- lease does not sit until timeout."""
881+ """Codec decode failures at the task boundary must fail tasks deterministically."""
884882
885883 @pytest .mark .asyncio
886884 async def test_activity_json_decode_failure_fails_task (self , mock_client : AsyncMock ) -> None :
@@ -919,6 +917,29 @@ async def test_activity_avro_decode_failure_fails_task(self, mock_client: AsyncM
919917 assert call_kwargs ["non_retryable" ] is True
920918 mock_client .complete_activity_task .assert_not_called ()
921919
920+ @pytest .mark .asyncio
921+ async def test_activity_unsupported_payload_codec_fails_before_handler (
922+ self , mock_client : AsyncMock
923+ ) -> None :
924+ worker = Worker (mock_client , task_queue = "q1" , workflows = [], activities = [echo_activity ])
925+ task = {
926+ "task_id" : "at-unsupported-codec" ,
927+ "activity_attempt_id" : "aa-unsupported-codec" ,
928+ "activity_type" : "test-act" ,
929+ "arguments" : {"codec" : "json" , "blob" : '["hello"]' },
930+ "payload_codec" : "zstd" ,
931+ }
932+
933+ outcome = await worker ._run_activity_task (task )
934+
935+ assert outcome == "decode_error"
936+ mock_client .fail_activity_task .assert_called_once ()
937+ call_kwargs = mock_client .fail_activity_task .call_args .kwargs
938+ assert "Unsupported payload codec 'zstd'" in call_kwargs ["message" ]
939+ assert call_kwargs ["failure_type" ] == "ValueError"
940+ assert call_kwargs ["non_retryable" ] is True
941+ mock_client .complete_activity_task .assert_not_called ()
942+
922943 @pytest .mark .asyncio
923944 async def test_activity_avro_missing_dependency_fails_task (
924945 self , mock_client : AsyncMock , monkeypatch : pytest .MonkeyPatch
@@ -968,6 +989,55 @@ async def test_workflow_json_decode_failure_fails_task(self, mock_client: AsyncM
968989 assert "json" in call_kwargs ["message" ]
969990 mock_client .complete_workflow_task .assert_not_called ()
970991
992+ @pytest .mark .asyncio
993+ async def test_workflow_unsupported_payload_codec_fails_before_replay (
994+ self , mock_client : AsyncMock
995+ ) -> None :
996+ worker = Worker (mock_client , task_queue = "q1" , workflows = [TestWorkflow ], activities = [])
997+ task = {
998+ "task_id" : "t-unsupported-codec" ,
999+ "workflow_type" : "test-wf" ,
1000+ "workflow_task_attempt" : 1 ,
1001+ "history_events" : [],
1002+ "arguments" : {"codec" : "json" , "blob" : '["hello"]' },
1003+ "payload_codec" : "zstd" ,
1004+ }
1005+
1006+ commands = await worker ._run_workflow_task (task )
1007+
1008+ assert commands is None
1009+ mock_client .fail_workflow_task .assert_called_once ()
1010+ call_kwargs = mock_client .fail_workflow_task .call_args .kwargs
1011+ assert "Unsupported payload codec 'zstd'" in call_kwargs ["message" ]
1012+ assert call_kwargs ["failure_type" ] == "ValueError"
1013+ mock_client .complete_workflow_task .assert_not_called ()
1014+
1015+ @pytest .mark .asyncio
1016+ async def test_query_unsupported_payload_codec_fails_before_query_handler (
1017+ self , mock_client : AsyncMock
1018+ ) -> None :
1019+ worker = Worker (mock_client , task_queue = "q1" , workflows = [QueryWorkflow ], activities = [])
1020+ task = {
1021+ "query_task_id" : "qt-unsupported-codec" ,
1022+ "query_task_attempt" : 1 ,
1023+ "workflow_type" : "query-wf" ,
1024+ "query_name" : "status" ,
1025+ "history_events" : [],
1026+ "workflow_arguments" : serializer .envelope ([], codec = "json" ),
1027+ "query_arguments" : serializer .envelope ([], codec = "json" ),
1028+ "payload_codec" : "zstd" ,
1029+ }
1030+
1031+ outcome = await worker ._run_query_task (task )
1032+
1033+ assert outcome == "failed"
1034+ mock_client .fail_query_task .assert_called_once ()
1035+ call_kwargs = mock_client .fail_query_task .call_args .kwargs
1036+ assert call_kwargs ["reason" ] == "query_payload_decode_failed"
1037+ assert "Unsupported payload codec 'zstd'" in call_kwargs ["message" ]
1038+ assert call_kwargs ["failure_type" ] == "ValueError"
1039+ mock_client .complete_query_task .assert_not_called ()
1040+
9711041 @pytest .mark .asyncio
9721042 async def test_workflow_avro_missing_dependency_fails_task (
9731043 self , mock_client : AsyncMock , monkeypatch : pytest .MonkeyPatch
0 commit comments