in src/buildstream/sandbox/_sandboxremote.py [0:0]
def run_remote_command(self, action_digest):
# Sends an execution request to the remote execution server.
#
# This function blocks until it gets a response from the server.
stub = self.exec_remote.exec_service
request = remote_execution_pb2.ExecuteRequest(
instance_name=self.exec_remote.instance_name, action_digest=action_digest, skip_cache_lookup=False
)
def __run_remote_command(stub, execute_request=None, running_operation=None):
try:
last_operation = None
if execute_request is not None:
operation_iterator = stub.Execute(execute_request)
else:
request = remote_execution_pb2.WaitExecutionRequest(name=running_operation.name)
operation_iterator = stub.WaitExecution(request)
for operation in operation_iterator:
if not self.operation_name:
self.operation_name = operation.name
if operation.done:
return operation
else:
last_operation = operation
except grpc.RpcError as e:
status_code = e.code()
if status_code in (
grpc.StatusCode.INVALID_ARGUMENT,
grpc.StatusCode.FAILED_PRECONDITION,
grpc.StatusCode.RESOURCE_EXHAUSTED,
grpc.StatusCode.INTERNAL,
grpc.StatusCode.DEADLINE_EXCEEDED,
):
raise SandboxError(
"Failed contacting remote execution server at {}."
"{}: {}".format(self.exec_spec.url, status_code.name, e.details())
)
if running_operation and status_code == grpc.StatusCode.UNIMPLEMENTED:
raise SandboxError(
"Failed trying to recover from connection loss: "
"server does not support operation status polling recovery."
)
return last_operation
# Set up signal handler to trigger cancel_operation on SIGTERM
operation = None
with self._get_context().messenger.timed_activity(
"Waiting for the remote build to complete", element_name=self._get_element_name()
), _signals.terminator(self.cancel_operation):
operation = __run_remote_command(stub, execute_request=request)
if operation is None:
return None
elif operation.done:
return operation
while operation is not None and not operation.done:
operation = __run_remote_command(stub, running_operation=operation)
return operation