EventStore / EventStoreDB-Client-Java

Official Asynchronous Java 8+ Client Library for EventStoreDB 20.6+
https://eventstore.com
Apache License 2.0
61 stars 19 forks source link

Fix IllegalStateException when stopping a subscription. #250

Closed YoEight closed 8 months ago

YoEight commented 8 months ago

Fixed: Fix IllegalStateException when stopping a subscription.

Fixes #248

While I added a test, the exception is not thrown to the user thread so can't be captured. Prior the patch we could see this stackstrace in the log:

SEVERE: Exception while executing runnable io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed@707b11e9
java.lang.IllegalStateException: call was cancelled
    at com.google.common.base.Preconditions.checkState(Preconditions.java:512)
    at io.grpc.internal.ClientCallImpl.halfCloseInternal(ClientCallImpl.java:510)
    at io.grpc.internal.ClientCallImpl.halfClose(ClientCallImpl.java:504)
    at io.grpc.PartialForwardingClientCall.halfClose(PartialForwardingClientCall.java:44)
    at io.grpc.ForwardingClientCall.halfClose(ForwardingClientCall.java:22)
    at io.grpc.ForwardingClientCall$SimpleForwardingClientCall.halfClose(ForwardingClientCall.java:44)
    at io.grpc.stub.ClientCalls$CallToStreamObserverAdapter.onCompleted(ClientCalls.java:379)
    at com.eventstore.dbclient.AbstractRegularSubscription$1.onError(AbstractRegularSubscription.java:116)
    at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:481)
    at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:574)
    at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:72)
    at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:742)
    at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:723)
    at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
    at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:840)

The exception is no longer raised. The culprit was when calling stop on the subscription, we already close the internal gRPC stream. By calling onCompleted on the observer, we broke the gRPC library expectation to close or cancel a gRPC stream only once.

The patch also fix persistent subscriptions too.

linear[bot] commented 8 months ago

DB-484 Fix subscription cancellation regression in Java client.