Encapsulates the future value of a retriable async gRPC request. Abstracts over the set of futures returned by a set of gRPC calls comprising a single logical gRPC request with retries. Communicates to the caller the result or exception resulting from the request. Args: comp
| 54 | |
| 55 | |
| 56 | class AsyncCallFuture: |
| 57 | """Encapsulates the future value of a retriable async gRPC request. |
| 58 | |
| 59 | Abstracts over the set of futures returned by a set of gRPC calls |
| 60 | comprising a single logical gRPC request with retries. Communicates |
| 61 | to the caller the result or exception resulting from the request. |
| 62 | |
| 63 | Args: |
| 64 | completion_event: The constructor should provide a `threding.Event` which |
| 65 | will be used to communicate when the set of gRPC requests is complete. |
| 66 | """ |
| 67 | |
| 68 | def __init__(self, completion_event): |
| 69 | self._active_grpc_future = None |
| 70 | self._active_grpc_future_lock = threading.Lock() |
| 71 | self._completion_event = completion_event |
| 72 | |
| 73 | def _set_active_future(self, grpc_future): |
| 74 | if grpc_future is None: |
| 75 | raise RuntimeError( |
| 76 | "_set_active_future invoked with grpc_future=None." |
| 77 | ) |
| 78 | with self._active_grpc_future_lock: |
| 79 | self._active_grpc_future = grpc_future |
| 80 | |
| 81 | def result(self, timeout): |
| 82 | """Analogous to `grpc.Future.result`. Returns the value or exception. |
| 83 | |
| 84 | This method will wait until the full set of gRPC requests is complete |
| 85 | and then act as `grpc.Future.result` for the single gRPC invocation |
| 86 | corresponding to the first successful call or final failure, as |
| 87 | appropriate. |
| 88 | |
| 89 | Args: |
| 90 | timeout: How long to wait in seconds before giving up and raising. |
| 91 | |
| 92 | Returns: |
| 93 | The result of the future corresponding to the single gRPC |
| 94 | corresponding to the successful call. |
| 95 | |
| 96 | Raises: |
| 97 | * `grpc.FutureTimeoutError` if timeout seconds elapse before the gRPC |
| 98 | calls could complete, including waits and retries. |
| 99 | * The exception corresponding to the last non-retryable gRPC request |
| 100 | in the case that a successful gRPC request was not made. |
| 101 | """ |
| 102 | if not self._completion_event.wait(timeout): |
| 103 | raise grpc.FutureTimeoutError( |
| 104 | f"AsyncCallFuture timed out after {timeout} seconds" |
| 105 | ) |
| 106 | with self._active_grpc_future_lock: |
| 107 | if self._active_grpc_future is None: |
| 108 | raise RuntimeError("AsyncFuture never had an active future set") |
| 109 | return self._active_grpc_future.result() |
| 110 | |
| 111 | |
| 112 | def async_call_with_retries(api_method, request, clock=None): |
no outgoing calls
no test coverage detected
searching dependent graphs…