@@ -1014,6 +1014,103 @@ async def test_describe_task_queue_matches_polyglot_fixture(self, client: Client
10141014 assert result .admission .query_tasks .status == semantic ["query_admission_status" ]
10151015 assert [lease ["task_id" ] for lease in result .current_leases or []] == semantic ["current_lease_ids" ]
10161016
1017+ @pytest .mark .asyncio
1018+ async def test_list_task_queue_build_ids_matches_polyglot_fixture (self , client : Client ) -> None :
1019+ fixture_path = (
1020+ Path (__file__ ).parent
1021+ / "fixtures"
1022+ / "control-plane"
1023+ / "task-queue-build-ids-parity.json"
1024+ )
1025+ fixture = json .loads (fixture_path .read_text ())
1026+ assert fixture ["operation" ] == "task_queue.build_ids"
1027+ sdk = fixture ["sdk_python" ]
1028+ resp = _mock_response (200 , fixture ["response_body" ])
1029+
1030+ with patch .object (
1031+ client ._http , "request" , new_callable = AsyncMock , return_value = resp
1032+ ) as mock :
1033+ result = await client .list_task_queue_build_ids (** sdk ["args" ])
1034+
1035+ assert mock .call_args .args [0 ] == fixture ["request" ]["method" ]
1036+ assert mock .call_args .args [1 ] == f"/api{ fixture ['request' ]['path' ]} "
1037+
1038+ semantic = fixture ["semantic_body" ]
1039+ assert result .namespace == semantic ["namespace" ]
1040+ assert result .task_queue == semantic ["task_queue" ]
1041+ assert result .stale_after_seconds == fixture ["response_body" ]["stale_after_seconds" ]
1042+ assert [cohort .build_id for cohort in result .build_ids ] == semantic ["build_ids" ]
1043+
1044+ rollout_statuses = {
1045+ (cohort .build_id if cohort .build_id is not None else "unversioned" ): cohort .rollout_status
1046+ for cohort in result .build_ids
1047+ }
1048+ assert rollout_statuses == semantic ["rollout_statuses" ]
1049+
1050+ @pytest .mark .asyncio
1051+ async def test_list_task_queue_build_ids_surfaces_cohort_worker_counts (
1052+ self , client : Client
1053+ ) -> None :
1054+ resp = _mock_response (
1055+ 200 ,
1056+ {
1057+ "namespace" : "default" ,
1058+ "task_queue" : "orders" ,
1059+ "stale_after_seconds" : 90 ,
1060+ "build_ids" : [
1061+ {
1062+ "build_id" : "build-alpha" ,
1063+ "rollout_status" : "active_with_draining" ,
1064+ "active_worker_count" : 2 ,
1065+ "draining_worker_count" : 1 ,
1066+ "stale_worker_count" : 0 ,
1067+ "total_worker_count" : 3 ,
1068+ "runtimes" : ["worker-runtime" ],
1069+ "sdk_versions" : ["polyglot-sdk/2.0.0" ],
1070+ "last_heartbeat_at" : "2026-04-22T09:30:00Z" ,
1071+ "first_seen_at" : "2026-04-22T08:00:00Z" ,
1072+ },
1073+ {
1074+ "build_id" : None ,
1075+ "rollout_status" : "stale_only" ,
1076+ "active_worker_count" : 0 ,
1077+ "draining_worker_count" : 0 ,
1078+ "stale_worker_count" : 1 ,
1079+ "total_worker_count" : 1 ,
1080+ "runtimes" : [],
1081+ "sdk_versions" : [],
1082+ "last_heartbeat_at" : None ,
1083+ "first_seen_at" : None ,
1084+ },
1085+ ],
1086+ },
1087+ )
1088+
1089+ with patch .object (
1090+ client ._http , "request" , new_callable = AsyncMock , return_value = resp
1091+ ) as mock :
1092+ result = await client .list_task_queue_build_ids ("orders" )
1093+
1094+ assert mock .call_args .args [0 ] == "GET"
1095+ assert mock .call_args .args [1 ] == "/api/task-queues/orders/build-ids"
1096+ assert result .task_queue == "orders"
1097+ assert result .stale_after_seconds == 90
1098+ assert len (result .build_ids ) == 2
1099+
1100+ alpha , unversioned = result .build_ids
1101+ assert alpha .build_id == "build-alpha"
1102+ assert alpha .rollout_status == "active_with_draining"
1103+ assert alpha .active_worker_count == 2
1104+ assert alpha .draining_worker_count == 1
1105+ assert alpha .total_worker_count == 3
1106+ assert alpha .runtimes == ["worker-runtime" ]
1107+ assert alpha .sdk_versions == ["polyglot-sdk/2.0.0" ]
1108+ assert unversioned .build_id is None
1109+ assert unversioned .rollout_status == "stale_only"
1110+ assert unversioned .stale_worker_count == 1
1111+ assert unversioned .last_heartbeat_at is None
1112+ assert unversioned .first_seen_at is None
1113+
10171114 @pytest .mark .asyncio
10181115 async def test_list_task_queues_parses_admission (self , client : Client ) -> None :
10191116 resp = _mock_response (200 , {
0 commit comments