Skip to content
This repository was archived by the owner on Apr 1, 2026. It is now read-only.

Commit d4ae637

Browse files
committed
added test for starting attempts
1 parent 84f61ee commit d4ae637

2 files changed

Lines changed: 60 additions & 11 deletions

File tree

google/cloud/bigtable/data/_async/metrics_interceptor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def wrapper(self, continuation, client_call_details, request):
5555
operation: "ActiveOperationMetric" = self.operation_map.get(key)
5656
if operation:
5757
# start a new attempt if not started
58-
if operation.state != OperationState.ACTIVE_ATTEMPT:
58+
if operation.state == OperationState.CREATED or operation.state == OperationState.BETWEEN_ATTEMPTS:
5959
operation.start_attempt()
6060
# wrap continuation in logic to process the operation
6161
return func(self, operation, continuation, client_call_details, request)

tests/unit/data/_async/test_metrics_interceptor.py

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import asyncio
1717
from grpc import RpcError
1818

19+
from google.cloud.bigtable.data._metrics.data_model import OperationState
1920
from google.cloud.bigtable.data._cross_sync import CrossSync
2021

2122
# try/except added for compatibility with python < 3.8
@@ -142,7 +143,7 @@ async def test_unary_unary_interceptor_success(self):
142143
instance = self._make_one()
143144
op = mock.Mock()
144145
op.uuid = "test-uuid"
145-
op.state = 1 # ACTIVE_ATTEMPT
146+
op.state = OperationState.ACTIVE_ATTEMPT
146147
instance.operation_map[op.uuid] = op
147148
continuation = CrossSync.Mock()
148149
call = continuation.return_value
@@ -167,7 +168,7 @@ async def test_unary_unary_interceptor_failure(self):
167168
instance = self._make_one()
168169
op = mock.Mock()
169170
op.uuid = "test-uuid"
170-
op.state = 1 # ACTIVE_ATTEMPT
171+
op.state = OperationState.ACTIVE_ATTEMPT
171172
instance.operation_map[op.uuid] = op
172173
exc = RpcError("test")
173174
exc.trailing_metadata = CrossSync.Mock(return_value=[("a", "b")])
@@ -194,7 +195,7 @@ async def test_unary_unary_interceptor_failure_no_metadata(self):
194195
instance = self._make_one()
195196
op = mock.Mock()
196197
op.uuid = "test-uuid"
197-
op.state = 1 # ACTIVE_ATTEMPT
198+
op.state = OperationState.ACTIVE_ATTEMPT
198199
instance.operation_map[op.uuid] = op
199200
exc = RpcError("test")
200201
continuation = CrossSync.Mock(side_effect=exc)
@@ -221,7 +222,7 @@ async def test_unary_unary_interceptor_failure_generic(self):
221222
instance = self._make_one()
222223
op = mock.Mock()
223224
op.uuid = "test-uuid"
224-
op.state = 1 # ACTIVE_ATTEMPT
225+
op.state = OperationState.ACTIVE_ATTEMPT
225226
instance.operation_map[op.uuid] = op
226227
exc = ValueError("test")
227228
continuation = CrossSync.Mock(side_effect=exc)
@@ -260,7 +261,7 @@ async def test_unary_stream_interceptor_success(self):
260261
instance = self._make_one()
261262
op = mock.Mock()
262263
op.uuid = "test-uuid"
263-
op.state = 1 # ACTIVE_ATTEMPT
264+
op.state = OperationState.ACTIVE_ATTEMPT
264265
op.start_time_ns = 0
265266
op.first_response_latency = None
266267
instance.operation_map[op.uuid] = op
@@ -291,7 +292,7 @@ async def test_unary_stream_interceptor_failure_mid_stream(self):
291292
instance = self._make_one()
292293
op = mock.Mock()
293294
op.uuid = "test-uuid"
294-
op.state = 1 # ACTIVE_ATTEMPT
295+
op.state = OperationState.ACTIVE_ATTEMPT
295296
op.start_time_ns = 0
296297
op.first_response_latency = None
297298
instance.operation_map[op.uuid] = op
@@ -327,7 +328,7 @@ async def test_unary_stream_interceptor_failure_start_stream(self):
327328
instance = self._make_one()
328329
op = mock.Mock()
329330
op.uuid = "test-uuid"
330-
op.state = 1 # ACTIVE_ATTEMPT
331+
op.state = OperationState.ACTIVE_ATTEMPT
331332
op.start_time_ns = 0
332333
op.first_response_latency = None
333334
instance.operation_map[op.uuid] = op
@@ -358,7 +359,7 @@ async def test_unary_stream_interceptor_failure_start_stream_no_metadata(self):
358359
instance = self._make_one()
359360
op = mock.Mock()
360361
op.uuid = "test-uuid"
361-
op.state = 1 # ACTIVE_ATTEMPT
362+
op.state = OperationState.ACTIVE_ATTEMPT
362363
op.start_time_ns = 0
363364
op.first_response_latency = None
364365
instance.operation_map[op.uuid] = op
@@ -387,7 +388,7 @@ async def test_unary_stream_interceptor_failure_start_stream_generic(self):
387388
instance = self._make_one()
388389
op = mock.Mock()
389390
op.uuid = "test-uuid"
390-
op.state = 1 # ACTIVE_ATTEMPT
391+
op.state = OperationState.ACTIVE_ATTEMPT
391392
op.start_time_ns = 0
392393
op.first_response_latency = None
393394
instance.operation_map[op.uuid] = op
@@ -404,4 +405,52 @@ async def test_unary_stream_interceptor_failure_start_stream_generic(self):
404405
continuation.assert_called_once_with(details, request)
405406
assert op.first_response_latency_ns is not None
406407
op.add_response_metadata.assert_not_called()
407-
op.end_attempt_with_status.assert_called_once_with(exc)
408+
op.end_attempt_with_status.assert_called_once_with(exc)
409+
410+
@CrossSync.pytest
411+
@pytest.mark.parametrize(
412+
"initial_state", [OperationState.CREATED, OperationState.BETWEEN_ATTEMPTS]
413+
)
414+
async def test_unary_unary_interceptor_start_operation(self, initial_state):
415+
"""if called with a newly created operation, it should be started"""
416+
from google.cloud.bigtable.data._metrics.data_model import (
417+
OPERATION_INTERCEPTOR_METADATA_KEY,
418+
)
419+
420+
instance = self._make_one()
421+
op = mock.Mock()
422+
op.uuid = "test-uuid"
423+
op.state = initial_state
424+
instance.operation_map[op.uuid] = op
425+
continuation = CrossSync.Mock()
426+
call = continuation.return_value
427+
details = mock.Mock()
428+
details.metadata = [(OPERATION_INTERCEPTOR_METADATA_KEY, op.uuid)]
429+
request = mock.Mock()
430+
await instance.intercept_unary_unary(continuation, details, request)
431+
op.start_attempt.assert_called_once()
432+
433+
@CrossSync.pytest
434+
@pytest.mark.parametrize(
435+
"initial_state", [OperationState.CREATED, OperationState.BETWEEN_ATTEMPTS]
436+
)
437+
async def test_unary_stream_interceptor_start_operation(self, initial_state):
438+
"""if called with a newly created operation, it should be started"""
439+
from google.cloud.bigtable.data._metrics.data_model import (
440+
OPERATION_INTERCEPTOR_METADATA_KEY,
441+
)
442+
443+
instance = self._make_one()
444+
op = mock.Mock()
445+
op.uuid = "test-uuid"
446+
op.state = initial_state
447+
instance.operation_map[op.uuid] = op
448+
449+
continuation = CrossSync.Mock()
450+
call = continuation.return_value
451+
call.__aiter__ = mock.Mock(return_value=_AsyncIterator([1, 2]))
452+
details = mock.Mock()
453+
details.metadata = [(OPERATION_INTERCEPTOR_METADATA_KEY, op.uuid)]
454+
request = mock.Mock()
455+
await instance.intercept_unary_stream(continuation, details, request)
456+
op.start_attempt.assert_called_once()

0 commit comments

Comments
 (0)