@@ -592,6 +592,48 @@ async def test_read_rows_stream_failure_unauthorized(
592592 and attempt .gfe_latency_ns < operation .duration_ns
593593 )
594594
595+ @CrossSync .pytest
596+ async def test_read_rows_stream_failure_unauthorized_with_retries (
597+ self , handler , authorized_view , cluster_config
598+ ):
599+ """
600+ retry unauthorized request multiple times before timing out
601+ """
602+ from google .cloud .bigtable .data .row_filters import FamilyNameRegexFilter
603+
604+ with pytest .raises (GoogleAPICallError ) as e :
605+ generator = await authorized_view .read_rows_stream (
606+ ReadRowsQuery (row_filter = FamilyNameRegexFilter ("unauthorized" )),
607+ retryable_errors = [PermissionDenied ],
608+ operation_timeout = 0.1 ,
609+ )
610+ [_ async for _ in generator ]
611+ assert e .value .grpc_status_code .name == "DEADLINE_EXCEEDED"
612+ # validate counts
613+ assert len (handler .completed_operations ) == 1
614+ assert len (handler .completed_attempts ) > 1
615+ assert len (handler .cancelled_operations ) == 0
616+ # validate operation
617+ operation = handler .completed_operations [0 ]
618+ assert isinstance (operation , CompletedOperationMetric )
619+ assert operation .final_status .name == "DEADLINE_EXCEEDED"
620+ assert operation .op_type .value == "ReadRows"
621+ assert operation .is_streaming is True
622+ assert len (operation .completed_attempts ) > 1
623+ assert operation .cluster_id == next (iter (cluster_config .keys ()))
624+ assert (
625+ operation .zone
626+ == cluster_config [operation .cluster_id ].location .split ("/" )[- 1 ]
627+ )
628+ # validate attempts
629+ for attempt in handler .completed_attempts :
630+ assert isinstance (attempt , CompletedAttemptMetric )
631+ assert attempt .end_status .name == "PERMISSION_DENIED"
632+ assert (
633+ attempt .gfe_latency_ns >= 0
634+ and attempt .gfe_latency_ns < operation .duration_ns
635+ )
636+
595637 @CrossSync .pytest
596638 async def test_read_rows_stream_failure_mid_stream (
597639 self , table , temp_rows , handler , error_injector
@@ -1574,7 +1616,7 @@ async def test_mutate_row_failure_unauthorized_with_retries(
15741616 mutation = SetCell ("unauthorized" , b"q" , b"v" )
15751617
15761618 with pytest .raises (GoogleAPICallError ) as e :
1577- await authorized_view .mutate_row (row_key , [mutation ], retryable_errors = [PermissionDenied ], operation_timeout = 30 )
1619+ await authorized_view .mutate_row (row_key , [mutation ], retryable_errors = [PermissionDenied ], operation_timeout = 0.1 )
15781620 assert e .value .grpc_status_code .name == "DEADLINE_EXCEEDED"
15791621 # validate counts
15801622 assert len (handler .completed_operations ) == 1
0 commit comments