EventStore / EventStore-Client-Dotnet

Dotnet Client SDK for the Event Store gRPC Client API written in C#
Other
137 stars 38 forks source link

Regression: exception with stack trace on graceful subscription shutdown #313

Open alexeyzimarev opened 1 week ago

alexeyzimarev commented 1 week ago

Describe the bug

When a subscription (persistent in my case) gets disposed, the following exception is thrown by the client:

info: Grpc.Net.Client.Internal.GrpcCall[3]
      Call failed with gRPC error status. Status code: 'Cancelled', Message: 'Call canceled by the client.'.
      System.OperationCanceledException: The operation was canceled.
dbug: Grpc.Net.Client.Internal.GrpcCall[4]
      Finished gRPC call.
dbug: Grpc.Net.Client.Internal.GrpcCall[8]
      gRPC call canceled.
fail: EventStore.Client.EventStorePersistentSubscriptionsClient[0]
      Persistent Subscription $ce-telemetry::testSub was dropped because an error occurred on the server.
      System.OperationCanceledException: The operation was canceled.
         at System.Threading.Channels.AsyncOperation`1.GetResult(Int16 token)
         at System.Threading.Channels.ChannelReader`1.ReadAllAsync(CancellationToken cancellationToken)+MoveNext()
         at EventStore.Client.EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult.<get_Messages>g__GetMessages|18_0()+MoveNext()
         at EventStore.Client.EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult.<get_Messages>g__GetMessages|18_0()+MoveNext()
         at EventStore.Client.EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult.<get_Messages>g__GetMessages|18_0()+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()

I thought it has been fixed, but maybe only for catch-up subscriptions. The gRPC exception clearly says "Call cancelled by the client" and it should be handled accordingly, so not produce a high-level exception in the logs.

alexeyzimarev commented 1 week ago

I fixed it with https://github.com/EventStore/EventStore-Client-Dotnet/pull/209 but then the new API was introduced and the exception is back.

alexeyzimarev commented 1 week ago

Same for catch-up subscriptions btw

2024-06-27T12:21:36.3513580+02:00 - Error - 0 - EventStore.Client.EventStoreClient - Subscription d763fde7-dd02-43e8-b589-f3e8b17ec9db was dropped because an error occurred on the server.
System.OperationCanceledException: The operation was canceled.
   at System.Threading.Channels.AsyncOperation`1.GetResult(Int16 token)
   at System.Threading.Channels.ChannelReader`1.ReadAllAsync(CancellationToken cancellationToken)+MoveNext()
   at EventStore.Client.EventStoreClient.StreamSubscriptionResult.<get_Messages>g__GetMessages|12_0()+MoveNext()
   at EventStore.Client.EventStoreClient.StreamSubscriptionResult.<get_Messages>g__GetMessages|12_0()+MoveNext()
   at EventStore.Client.EventStoreClient.StreamSubscriptionResult.<get_Messages>g__GetMessages|12_0()+MoveNext()
   at EventStore.Client.EventStoreClient.StreamSubscriptionResult.<get_Messages>g__GetMessages|12_0()+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()
   at EventStore.Client.StreamSubscription.Subscribe()
alexeyzimarev commented 1 week ago

Ok, it happens if the cancellation token gets cancelled before calling Dispose() on subscription. I'd expect that be a normal sequence - request cancellation and then call Dispose. So, there's a workaround, but it feels weird.