private void verifySize() { if (count > maxMessageSize) { throw Status.RESOURCE_EXHAUSTED.withDescription(String.format( "%s: Compressed frame exceeds maximum frame size: %d. Bytes read: %d. ", debugString, maxMessageSize, count)).asRuntimeException(); } } }
@Override public void onError(Throwable t) { Metadata metadata = Status.trailersFromThrowable(t); if (metadata == null) { metadata = new Metadata(); } if (t instanceof MotanBizException) { call.close(Status.INTERNAL.withDescription(t.getMessage()).withCause(t), metadata); } else { call.close(Status.UNAVAILABLE.withDescription(t.getMessage()).withCause(t), metadata); } }
/** * Maps HTTP error response status codes to transport codes, as defined in <a * href="https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md"> * http-grpc-status-mapping.md</a>. Never returns a status for which {@code status.isOk()} is * {@code true}. * * <p>Copied from <a href="https://github.com/grpc/grpc-java/blob/master/core/src/main/java/io/grpc/internal/GrpcUtil.java"> * GrpcUtil.java</a> */ public static Status httpStatusToGrpcStatus(int httpStatusCode) { return httpStatusToGrpcCode(httpStatusCode).toStatus() .withDescription("HTTP status code " + httpStatusCode); }
private void doCancel(@Nullable String message, @Nullable Throwable cause) { if (message == null && cause == null) { cause = new CancellationException("Cancelled without a message or cause"); logger.warn("Cancelling without a message or cause is suboptimal", cause); } if (cancelCalled) { return; } cancelCalled = true; Status status = Status.CANCELLED; if (message != null) { status = status.withDescription(message); } if (cause != null) { status = status.withCause(cause); } close(status); req.abort(); }
@Override public StreamObserver<SimpleRequest> streamThrowsErrorInStub( StreamObserver<SimpleResponse> responseObserver) { throw Status.ABORTED.withDescription("bad streaming stub").asRuntimeException(); }
@Override public void unaryThrowsError(SimpleRequest request, StreamObserver<SimpleResponse> responseObserver) { throw Status.ABORTED.withDescription("call aborted").asRuntimeException(); }
@Override public void onNext(SimpleRequest value) { throw Status.ABORTED.withDescription("bad streaming message").asRuntimeException(); }
@Override public Object[] parse(InputStream stream) { try { BinaryDecoder in = DECODER_FACTORY.binaryDecoder(stream, null); Schema reqSchema = message.getRequest(); GenericRecord request = (GenericRecord) new SpecificDatumReader<>(reqSchema).read(null, in); Object[] args = new Object[reqSchema.getFields().size()]; int i = 0; for (Schema.Field field : reqSchema.getFields()) { args[i++] = request.get(field.name()); } return args; } catch (IOException e) { throw Status.INTERNAL.withCause(e). withDescription("Error deserializing avro request arguments").asRuntimeException(); } finally { AvroGrpcUtils.skipAndCloseQuietly(stream); } }
private ByteBufOrStream getCompressedBody(ByteBuf buf) { if (decompressor == Codec.Identity.NONE) { buf.release(); throw Status.INTERNAL.withDescription( DEBUG_STRING + ": Can't decode compressed frame as compression not configured.") .asRuntimeException(); } try { // Enforce the maxMessageSizeBytes limit on the returned stream. final InputStream unlimitedStream = decompressor.decompress(new ByteBufInputStream(buf, true)); return new ByteBufOrStream( new SizeEnforcingInputStream(unlimitedStream, maxMessageSizeBytes, DEBUG_STRING)); } catch (IOException e) { throw new RuntimeException(e); } }
@Override public void errorWithMessage(SimpleRequest request, StreamObserver<SimpleResponse> responseObserver) { responseObserver.onError(Status.ABORTED.withDescription("aborted call").asException()); }
@Override public void batchPoll(TaskServicePb.BatchPollRequest req, StreamObserver<TaskPb.Task> response) { final int count = GRPC_HELPER.optionalOr(req.getCount(), 1); final int timeout = GRPC_HELPER.optionalOr(req.getTimeout(), POLL_TIMEOUT_MS); if (timeout > MAX_POLL_TIMEOUT_MS) { response.onError(Status.INVALID_ARGUMENT .withDescription("longpoll timeout cannot be longer than " + MAX_POLL_TIMEOUT_MS + "ms") .asRuntimeException() ); return; } try { List<Task> polledTasks = taskService.batchPoll(req.getTaskType(), req.getWorkerId(), GRPC_HELPER.optional(req.getDomain()), count, timeout); LOGGER.info("polled tasks: "+polledTasks); polledTasks.stream().map(PROTO_MAPPER::toProto).forEach(response::onNext); response.onCompleted(); } catch (Exception e) { GRPC_HELPER.onError(response, e); } }
/** Convert an entry's status from a protobuf to an {@link ApiException}. */ private ApiException createEntryError(com.google.rpc.Status protoStatus) { io.grpc.Status grpcStatus = io.grpc.Status.fromCodeValue(protoStatus.getCode()) .withDescription(protoStatus.getMessage()); StatusCode gaxStatusCode = GrpcStatusCode.of(grpcStatus.getCode()); return ApiExceptionFactory.createException( grpcStatus.asRuntimeException(), gaxStatusCode, retryableCodes.contains(gaxStatusCode.getCode())); }
@Override public void getTask(MetadataServicePb.GetTaskRequest req, StreamObserver<MetadataServicePb.GetTaskResponse> response) { TaskDef def = service.getTaskDef(req.getTaskType()); if (def != null) { TaskDefPb.TaskDef task = PROTO_MAPPER.toProto(def); response.onNext(MetadataServicePb.GetTaskResponse.newBuilder() .setTask(task) .build() ); response.onCompleted(); } else { response.onError(Status.NOT_FOUND .withDescription("No such TaskDef found by taskType=" + req.getTaskType()) .asRuntimeException() ); } }
@Override public void getWorkflow(MetadataServicePb.GetWorkflowRequest req, StreamObserver<MetadataServicePb.GetWorkflowResponse > response) { try { WorkflowDef workflowDef = service.getWorkflowDef(req.getName(), GRPC_HELPER.optional(req.getVersion())); WorkflowDefPb.WorkflowDef workflow = PROTO_MAPPER.toProto(workflowDef); response.onNext(MetadataServicePb.GetWorkflowResponse.newBuilder() .setWorkflow(workflow) .build() ); response.onCompleted(); } catch (ApplicationException e) { // TODO replace this with gRPC exception interceptor. response.onError(Status.NOT_FOUND .withDescription("No such workflow found by name=" + req.getName()) .asRuntimeException() ); } }
@Override public void getTask(TaskServicePb.GetTaskRequest req, StreamObserver<TaskServicePb.GetTaskResponse> response) { try { Task task = taskService.getTask(req.getTaskId()); if (task == null) { response.onError(Status.NOT_FOUND .withDescription("No such task found by id="+req.getTaskId()) .asRuntimeException() ); } else { response.onNext( TaskServicePb.GetTaskResponse.newBuilder() .setTask(PROTO_MAPPER.toProto(task)) .build() ); response.onCompleted(); } } catch (Exception e) { GRPC_HELPER.onError(response, e); } }
@Test public void http2InternalErrorIsRetryable() { Status status = Status.fromCodeValue(Status.Code.INTERNAL.value()) .withDescription("HTTP/2 error code: INTERNAL_ERROR"); SpannerException e = SpannerExceptionFactory.newSpannerException(new StatusRuntimeException(status)); assertThat(e.isRetryable()).isTrue(); }
@Test public void connectionClosedIsRetryable() { Status status = Status.fromCodeValue(Status.Code.INTERNAL.value()) .withDescription("Connection closed with unknown cause"); SpannerException e = SpannerExceptionFactory.newSpannerException(new StatusRuntimeException(status)); assertThat(e.isRetryable()).isTrue(); }
@Test public void resourceExhausted() { Status status = Status.fromCodeValue(Status.Code.RESOURCE_EXHAUSTED.value()) .withDescription("Memory pushback"); SpannerException e = SpannerExceptionFactory.newSpannerException(new StatusRuntimeException(status)); assertThat(e.isRetryable()).isFalse(); }
@Override public void onNext(StreamingOutputCallRequest request) { if (request.hasResponseStatus()) { dispatcher.cancel(); responseObserver.onError(Status.fromCodeValue(request.getResponseStatus().getCode()) .withDescription( request.getResponseStatus().getMessage()) .asRuntimeException()); return; } dispatcher.enqueue(toChunkQueue(request)); }
@Test public void resourceExhaustedWithBackoff() { Status status = Status.fromCodeValue(Status.Code.RESOURCE_EXHAUSTED.value()) .withDescription("Memory pushback"); Metadata trailers = new Metadata(); Metadata.Key<RetryInfo> key = ProtoUtils.keyForProto(RetryInfo.getDefaultInstance()); RetryInfo retryInfo = RetryInfo.newBuilder() .setRetryDelay(Duration.newBuilder().setNanos(1000000).setSeconds(1L)) .build(); trailers.put(key, retryInfo); SpannerException e = SpannerExceptionFactory.newSpannerException(new StatusRuntimeException(status, trailers)); assertThat(e.isRetryable()).isTrue(); assertThat(e.getRetryDelayInMillis()).isEqualTo(1001); }