sportradar / UnifiedOddsSdkNet

UnifiedFeed SDK is a client library that enables easier integration with the Betradar XML feeds. SDK exposes XML feed service interface in a more user-friendly way and isolates the client from having to do XML feed parsing, proper connection handling, error recovery, event queuing, data caching and dispatching.
Other
15 stars 8 forks source link

Fix disposing of Feed #18

Closed deuko closed 4 years ago

deuko commented 4 years ago

We encountered a rare case, where our provided token was accepted, but the connection to the broker was somehow refused (still being investigated) with the following exception: Sportradar.OddsFeed.SDK.Common.Exceptions.CommunicationException: Connection to the message broker failed, Probable Reason={Invalid or expired token} ---> RabbitMQ.Client.Exceptions.AuthenticationFailureException: ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN. For details see the broker logfile. at RabbitMQ.Client.Framing.Impl.Connection.StartAndTune() at RabbitMQ.Client.Framing.Impl.Connection.Open(Boolean insist) at RabbitMQ.Client.Framing.Impl.Connection..ctor(IConnectionFactory factory, Boolean insist, IFrameHandler frameHandler, String clientProvidedName) at RabbitMQ.Client.Framing.Impl.AutorecoveringConnection.Init(AmqpTcpEndpoint endpoint) at RabbitMQ.Client.Framing.Impl.AutorecoveringConnection.Init(IList1 endpoints) at RabbitMQ.Client.ConnectionFactory.CreateConnection(IList1 endpoints, String clientProvidedName) --- End of inner exception stack trace --- at Sportradar.OddsFeed.SDK.API.Feed.Open()

This uncovered some bugs, as in this case the connection is an inconsistent state, and calling Feed.Close() leads to a NullReferenceException as _connection is null.

Another problem is the throwing of exceptions in the Close methods (which should be generally avoided), as they also prevent Dispose() from finishing correctly (without proper handling in the calling Dispose-method). In this case, the exception of the FeedRecoveryManager prevented the Sessions from being disposed correctly, leading ultimately to an inconsistent state, where the Session and the Feed could not be initialized correctly anymore, as the following exception indicates (when trying to instantiate a new Feed and opening it again): System.InvalidOperationException: Current OddsFeedSession is already opened at Sportradar.OddsFeed.SDK.API.Internal.EntityDispatcher1.Open() at Sportradar.OddsFeed.SDK.API.Feed.Open() at Polly.Policy.<>cDisplayClass108_0.b0(Context ctx, CancellationToken ct) at Polly.Policy.<>cDisplayClass138_0.b0(Context ctx, CancellationToken token) at Polly.Retry.RetryEngine.Implementation[TResult](Func3 action, Context context, CancellationToken cancellationToken, ExceptionPredicates shouldRetryExceptionPredicates, ResultPredicates1 shouldRetryResultPredicates, Action4 onRetry, Int32 permittedRetryCount, IEnumerable1 sleepDurationsEnumerable, Func4 sleepDurationProvider)

Of course this could be also handled differently, by wrapping the call of Close within the Dispose-method if you want to preserve the exception, but you get the idea what the problem is here.

Thank you in advance

deuko commented 4 years ago

thank you very much, this can be closed / ignored then.