Re: [grpc-io] What is the suggested way to use onError on StreamObserver?

2024-04-23 Thread 'Eric Anderson' via grpc.io
On Sat, Apr 13, 2024 at 9:23 AM Debraj  wrote:

> I did not quite understand the statement - "*It will respond
> with Status.UNKNOWN and interceptors might get confused"* .
>
> Let's say I do not have the try - catch in the purge() method and I have
> a ServerInterceptor like below.
>

If you really want to throw and for it to be propagated, use
TransmitStatusRuntimeExceptionInterceptor
.
It has to be carefully placed in the interceptor chain to work well. But we
generally discourage using it because it can make understanding errors
difficult.

  handleException(ex);
>   throw ex;
>

This calls call.close() *and* throws an exception. That very well might be
racy. If you handle the exception (by calling close), don't re-throw the
exception. gRPC ignores the exception's contents and always uses UNKNOWN
when processing it.

If the HttpServer is not available then from gRPC2 server
Status.UNAVAILABLE error
> is thrown with some Metadata as shown below. But we are observing that
> sometimes the Metadata is not coming to gRPC1. It does not happen always.
>

If you get UNAVAILABLE without the Metadata you expect, then that was
probably a failure between gRPC1 → gRPC2. If the problem is caused by
throwing an exception, you'd see UNKNOWN instead. In either case, the
status description tells you a lot about what is going on, so if you want
us to tell you why something is happening, you need to give us the full
status.

-- 
You received this message because you are subscribed to the Google Groups 
"grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to grpc-io+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/grpc-io/CA%2B4M1oPWRfK5M%2BUEWcUGFesedht%2B0UEg8EzDV0Vx5tSA7ww6hQ%40mail.gmail.com.


smime.p7s
Description: S/MIME Cryptographic Signature


Re: [grpc-io] What is the suggested way to use onError on StreamObserver?

2024-04-19 Thread Debraj
For more context, I am using gRPC 1.55.1. We are calling gRPC services like 
below

gRPC1 --> gRCP2 -> HttpServer

If the HttpServer is not available then from gRPC2 server Status.UNAVAILABLE 
error is thrown with some Metadata as shown below. But we are observing 
that sometimes the Metadata is not coming to gRPC1. It does not happen 
always. Most of the time gRPC1 receives the Status.UNAVAILABLE along with 
the Metadata. Can someone let me know if there are some known issues with 
gRPC 1.55.1 or it could be due to responseObserver.onError() not done in a 
try-catch in the gRPC server's purge() method as suggested by Eric in this 
thread. 

gRPC2
---
public void purge(
  final PurgeRequest request, final StreamObserver 
responseObserver) {
  validator.validate(request);
  responseObserver.onNext(service.purge(request));
  responseObserver.onCompleted();
  }


class Service {
void purge() {
try {
// http call
} catch(Http Service Not available) {
var metadata = new Metadata();
// Add some data in metadata
throw new StatusRunTimeException(Status.UNAVAILABLE, metadata);
}
}
}

On Saturday 13 April 2024 at 21:53:06 UTC+5:30 Debraj wrote:

> Thanks for replying. 
>
> I did not quite understand the statement - "*It will respond 
> with Status.UNKNOWN and interceptors might get confused"* .
>
> Let's say I do not have the try - catch in the purge() method and I have 
> a ServerInterceptor like below. Are you saying that the 
> statusException.getStatus() 
> in the below code may be Status.UNKNOWN sometime even if the 
> validator.validate() is throwing StatusRunTImeException with some 
> different Status. In that case statusException.getTrailers() can also be 
> null or empty?
>
> public class ServerInterceptor implements io.grpc.ServerInterceptor {
>   public < ReqT, RespT > ServerCall.Listener < ReqT > interceptCall(
> final ServerCall < ReqT, RespT > call,
> final Metadata requestHeaders,
> final ServerCallHandler < ReqT, RespT > next) {
> return new SimpleForwardingServerCallListener < > 
> (next.startCall(grpcServerCall, requestHeaders)) {
>   public void onMessage(final ReqT message) {
> try {
>   // do something
>   super.onMessage(message);
> } catch (Exception e) {
>   handleException(ex);
>   throw ex;
> }
>   }
>   // Similiar logic for onReady(), onHalfClose(), onComplete(), 
>   // where in a try .. catch handleException() & throw ex
>   private void handleException(final Exception exception) {
> if (exception instance of StatusRunTimeException statusException) {
>   val metadata = statusException.getTrailers();
>   log.error("Request failed with metadata={}", metadata, 
> statusException);
>   call.close(statusException.getStatus(), 
> ObjectUtils.defaultIfNull(metadata, new Metadata()));
>   return;
> }
> call.close(Status.UNKNOWN.withDescription(exception.getMessage()), 
> requestHeaders);
>   }
> }
>   }
> }
>
> On Friday 12 April 2024 at 03:21:52 UTC+5:30 Eric Anderson wrote:
>
>> If validator.validate() and service.purge() can throw, then you want a 
>> try-catch. You must call onCompleted() or onError() on the observer for the 
>> RPC to complete (and thus release its memory). gRPC does have some handling 
>> for exceptions thrown by the service method, but it is a worst-case backup. 
>> It will respond with Status.UNKNOWN and interceptors might get confused.
>>
>> If you are very concerned, you can catch exceptions from onNext(). In 
>> general code tends to assume onNext() won't throw (or rather, won't throw 
>> randomly; it will totally throw if you use it incorrectly, like calling it 
>> after onCompleted()). So that's why the Hello World example server doesn't 
>> have a try-catch.
>>
>> On Thu, Apr 11, 2024 at 1:55 PM Debraj  wrote:
>>
>>> If I have a code like below on a Java-based gRPC service
>>>
>>>  @Override
>>>   public void purge(
>>>   final PurgeRequest request, final StreamObserver 
>>> responseObserver) {
>>>   validator.validate(request);
>>>   responseObserver.onNext(service.purge(request));
>>>   responseObserver.onCompleted();
>>>   }
>>>
>>> Is it recommended that I catch the exception and call onError() like 
>>> below or it is not recommended? Is there any advantage of one approach over 
>>> the other?
>>>
>>>  @Override
>>>   public void purge(
>>>   final PurgeRequest request, final StreamObserver 
>>> responseObserver) {
>>> try {
>>>   validator.validate(request);
>>>   responseObserver.onNext(gdprService.purge(request));
>>>   responseObserver.onCompleted();
>>> } catch (final Exception e) {
>>>   log.error("Failed to purge {}", request, e);
>>>   responseObserver.onError(e);
>>> }
>>>   }
>>>
>>>
>>> -- 
>>> You received this message because you are 

Re: [grpc-io] What is the suggested way to use onError on StreamObserver?

2024-04-13 Thread Debraj
Thanks for replying. 

I did not quite understand the statement - "*It will respond 
with Status.UNKNOWN and interceptors might get confused"* .

Let's say I do not have the try - catch in the purge() method and I have a 
ServerInterceptor like below. Are you saying that the 
statusException.getStatus() 
in the below code may be Status.UNKNOWN sometime even if the 
validator.validate() is throwing StatusRunTImeException with some different 
Status. In that case statusException.getTrailers() can also be null or empty
?

public class ServerInterceptor implements io.grpc.ServerInterceptor {
  public < ReqT, RespT > ServerCall.Listener < ReqT > interceptCall(
final ServerCall < ReqT, RespT > call,
final Metadata requestHeaders,
final ServerCallHandler < ReqT, RespT > next) {
return new SimpleForwardingServerCallListener < > 
(next.startCall(grpcServerCall, requestHeaders)) {
  public void onMessage(final ReqT message) {
try {
  // do something
  super.onMessage(message);
} catch (Exception e) {
  handleException(ex);
  throw ex;
}
  }
  // Similiar logic for onReady(), onHalfClose(), onComplete(), 
  // where in a try .. catch handleException() & throw ex
  private void handleException(final Exception exception) {
if (exception instance of StatusRunTimeException statusException) {
  val metadata = statusException.getTrailers();
  log.error("Request failed with metadata={}", metadata, 
statusException);
  call.close(statusException.getStatus(), 
ObjectUtils.defaultIfNull(metadata, new Metadata()));
  return;
}
call.close(Status.UNKNOWN.withDescription(exception.getMessage()), 
requestHeaders);
  }
}
  }
}

On Friday 12 April 2024 at 03:21:52 UTC+5:30 Eric Anderson wrote:

> If validator.validate() and service.purge() can throw, then you want a 
> try-catch. You must call onCompleted() or onError() on the observer for the 
> RPC to complete (and thus release its memory). gRPC does have some handling 
> for exceptions thrown by the service method, but it is a worst-case backup. 
> It will respond with Status.UNKNOWN and interceptors might get confused.
>
> If you are very concerned, you can catch exceptions from onNext(). In 
> general code tends to assume onNext() won't throw (or rather, won't throw 
> randomly; it will totally throw if you use it incorrectly, like calling it 
> after onCompleted()). So that's why the Hello World example server doesn't 
> have a try-catch.
>
> On Thu, Apr 11, 2024 at 1:55 PM Debraj  wrote:
>
>> If I have a code like below on a Java-based gRPC service
>>
>>  @Override
>>   public void purge(
>>   final PurgeRequest request, final StreamObserver 
>> responseObserver) {
>>   validator.validate(request);
>>   responseObserver.onNext(service.purge(request));
>>   responseObserver.onCompleted();
>>   }
>>
>> Is it recommended that I catch the exception and call onError() like 
>> below or it is not recommended? Is there any advantage of one approach over 
>> the other?
>>
>>  @Override
>>   public void purge(
>>   final PurgeRequest request, final StreamObserver 
>> responseObserver) {
>> try {
>>   validator.validate(request);
>>   responseObserver.onNext(gdprService.purge(request));
>>   responseObserver.onCompleted();
>> } catch (final Exception e) {
>>   log.error("Failed to purge {}", request, e);
>>   responseObserver.onError(e);
>> }
>>   }
>>
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "grpc.io" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to grpc-io+u...@googlegroups.com.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/grpc-io/985e6aee-2de0-4ca4-b99e-f17e61297cc5n%40googlegroups.com
>>  
>> 
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to grpc-io+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/grpc-io/cd5b1191-9d4e-472f-86e9-6f3f4ac0ec1fn%40googlegroups.com.


Re: [grpc-io] What is the suggested way to use onError on StreamObserver?

2024-04-11 Thread 'Eric Anderson' via grpc.io
If validator.validate() and service.purge() can throw, then you want a
try-catch. You must call onCompleted() or onError() on the observer for the
RPC to complete (and thus release its memory). gRPC does have some handling
for exceptions thrown by the service method, but it is a worst-case backup.
It will respond with Status.UNKNOWN and interceptors might get confused.

If you are very concerned, you can catch exceptions from onNext(). In
general code tends to assume onNext() won't throw (or rather, won't throw
randomly; it will totally throw if you use it incorrectly, like calling it
after onCompleted()). So that's why the Hello World example server doesn't
have a try-catch.

On Thu, Apr 11, 2024 at 1:55 PM Debraj  wrote:

> If I have a code like below on a Java-based gRPC service
>
>  @Override
>   public void purge(
>   final PurgeRequest request, final StreamObserver
> responseObserver) {
>   validator.validate(request);
>   responseObserver.onNext(service.purge(request));
>   responseObserver.onCompleted();
>   }
>
> Is it recommended that I catch the exception and call onError() like below
> or it is not recommended? Is there any advantage of one approach over the
> other?
>
>  @Override
>   public void purge(
>   final PurgeRequest request, final StreamObserver
> responseObserver) {
> try {
>   validator.validate(request);
>   responseObserver.onNext(gdprService.purge(request));
>   responseObserver.onCompleted();
> } catch (final Exception e) {
>   log.error("Failed to purge {}", request, e);
>   responseObserver.onError(e);
> }
>   }
>
>
> --
> You received this message because you are subscribed to the Google Groups "
> grpc.io" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to grpc-io+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/grpc-io/985e6aee-2de0-4ca4-b99e-f17e61297cc5n%40googlegroups.com
> 
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to grpc-io+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/grpc-io/CA%2B4M1oPa2ieyMp%2BSW%3DwtjH4Kuuw1vxmxVEKiLRYr2JROzUNwHw%40mail.gmail.com.


smime.p7s
Description: S/MIME Cryptographic Signature


[grpc-io] What is the suggested way to use onError on StreamObserver?

2024-04-11 Thread Debraj
If I have a code like below on a Java-based gRPC service

 @Override
  public void purge(
  final PurgeRequest request, final StreamObserver 
responseObserver) {
  validator.validate(request);
  responseObserver.onNext(service.purge(request));
  responseObserver.onCompleted();
  }

Is it recommended that I catch the exception and call onError() like below 
or it is not recommended? Is there any advantage of one approach over the 
other?

 @Override
  public void purge(
  final PurgeRequest request, final StreamObserver 
responseObserver) {
try {
  validator.validate(request);
  responseObserver.onNext(gdprService.purge(request));
  responseObserver.onCompleted();
} catch (final Exception e) {
  log.error("Failed to purge {}", request, e);
  responseObserver.onError(e);
}
  }


-- 
You received this message because you are subscribed to the Google Groups 
"grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to grpc-io+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/grpc-io/985e6aee-2de0-4ca4-b99e-f17e61297cc5n%40googlegroups.com.