diff --git a/CryptoExchange.Net/Clients/SocketApiClient.cs b/CryptoExchange.Net/Clients/SocketApiClient.cs index 21bf2d4..ace701a 100644 --- a/CryptoExchange.Net/Clients/SocketApiClient.cs +++ b/CryptoExchange.Net/Clients/SocketApiClient.cs @@ -269,7 +269,7 @@ namespace CryptoExchange.Net.Clients { _logger.FailedToSubscribe(socketConnection.SocketId, subResult.Error?.ToString()); // If this was a timeout we still need to send an unsubscribe to prevent messages coming in later - await socketConnection.CloseAsync(subscription, isTimeout).ConfigureAwait(false); + await socketConnection.CloseAsync(subscription).ConfigureAwait(false); return new CallResult(subResult.Error!); } } diff --git a/CryptoExchange.Net/Logging/Extensions/CryptoExchangeWebSocketClientLoggingExtension.cs b/CryptoExchange.Net/Logging/Extensions/CryptoExchangeWebSocketClientLoggingExtension.cs index c3581e9..c80792a 100644 --- a/CryptoExchange.Net/Logging/Extensions/CryptoExchangeWebSocketClientLoggingExtension.cs +++ b/CryptoExchange.Net/Logging/Extensions/CryptoExchangeWebSocketClientLoggingExtension.cs @@ -3,6 +3,7 @@ using System; namespace CryptoExchange.Net.Logging.Extensions { +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public static class CryptoExchangeWebSocketClientLoggingExtension { private static readonly Action _connecting; diff --git a/CryptoExchange.Net/Logging/Extensions/RateLimitGateLoggingExtensions.cs b/CryptoExchange.Net/Logging/Extensions/RateLimitGateLoggingExtensions.cs index bdaf411..a327f18 100644 --- a/CryptoExchange.Net/Logging/Extensions/RateLimitGateLoggingExtensions.cs +++ b/CryptoExchange.Net/Logging/Extensions/RateLimitGateLoggingExtensions.cs @@ -3,6 +3,7 @@ using System; namespace CryptoExchange.Net.Logging.Extensions { +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public static class RateLimitGateLoggingExtensions { private static readonly Action _rateLimitRequestFailed; diff --git a/CryptoExchange.Net/Logging/Extensions/RestApiClientLoggingExtensions.cs b/CryptoExchange.Net/Logging/Extensions/RestApiClientLoggingExtensions.cs index 7f3e081..59e9625 100644 --- a/CryptoExchange.Net/Logging/Extensions/RestApiClientLoggingExtensions.cs +++ b/CryptoExchange.Net/Logging/Extensions/RestApiClientLoggingExtensions.cs @@ -6,6 +6,7 @@ using System.Net.Http; namespace CryptoExchange.Net.Logging.Extensions { +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public static class RestApiClientLoggingExtensions { private static readonly Action _restApiErrorReceived; diff --git a/CryptoExchange.Net/Logging/Extensions/SocketApiClientLoggingExtension.cs b/CryptoExchange.Net/Logging/Extensions/SocketApiClientLoggingExtension.cs index b5997e2..3590a17 100644 --- a/CryptoExchange.Net/Logging/Extensions/SocketApiClientLoggingExtension.cs +++ b/CryptoExchange.Net/Logging/Extensions/SocketApiClientLoggingExtension.cs @@ -3,6 +3,7 @@ using System; namespace CryptoExchange.Net.Logging.Extensions { +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public static class SocketApiClientLoggingExtension { private static readonly Action _failedToAddSubscriptionRetryOnDifferentConnection; diff --git a/CryptoExchange.Net/Logging/Extensions/SocketConnectionLoggingExtension.cs b/CryptoExchange.Net/Logging/Extensions/SocketConnectionLoggingExtension.cs index ea8b23b..d543d84 100644 --- a/CryptoExchange.Net/Logging/Extensions/SocketConnectionLoggingExtension.cs +++ b/CryptoExchange.Net/Logging/Extensions/SocketConnectionLoggingExtension.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Logging; namespace CryptoExchange.Net.Logging.Extensions { +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public static class SocketConnectionLoggingExtension { private static readonly Action _activityPaused; diff --git a/CryptoExchange.Net/Logging/Extensions/SymbolOrderBookLoggingExtensions.cs b/CryptoExchange.Net/Logging/Extensions/SymbolOrderBookLoggingExtensions.cs index 872f60c..e49ea44 100644 --- a/CryptoExchange.Net/Logging/Extensions/SymbolOrderBookLoggingExtensions.cs +++ b/CryptoExchange.Net/Logging/Extensions/SymbolOrderBookLoggingExtensions.cs @@ -4,6 +4,8 @@ using Microsoft.Extensions.Logging; namespace CryptoExchange.Net.Logging.Extensions { +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + public static class SymbolOrderBookLoggingExtensions { private static readonly Action _orderBookStatusChanged; diff --git a/CryptoExchange.Net/Objects/Sockets/DataEvent.cs b/CryptoExchange.Net/Objects/Sockets/DataEvent.cs index d627fcc..2b49131 100644 --- a/CryptoExchange.Net/Objects/Sockets/DataEvent.cs +++ b/CryptoExchange.Net/Objects/Sockets/DataEvent.cs @@ -144,5 +144,11 @@ namespace CryptoExchange.Net.Objects.Sockets { return new CallResult(default, OriginalData, error); } + + /// + public override string ToString() + { + return $"{StreamId} - {(Symbol == null ? "" : (Symbol + " - "))}{(UpdateType == null ? "" : (UpdateType + " - "))}{Data}"; + } } } diff --git a/CryptoExchange.Net/Sockets/CryptoExchangeWebSocketClient.cs b/CryptoExchange.Net/Sockets/CryptoExchangeWebSocketClient.cs index c8f90b5..2c1226f 100644 --- a/CryptoExchange.Net/Sockets/CryptoExchangeWebSocketClient.cs +++ b/CryptoExchange.Net/Sockets/CryptoExchangeWebSocketClient.cs @@ -245,7 +245,8 @@ namespace CryptoExchange.Net.Sockets await Task.Delay(50).ConfigureAwait(false); await _closeTask.ConfigureAwait(false); - _closeTask = null; + if (!_stopRequested) + _closeTask = null; if (Parameters.ReconnectPolicy == ReconnectPolicy.Disabled) { diff --git a/CryptoExchange.Net/Sockets/Query.cs b/CryptoExchange.Net/Sockets/Query.cs index 5427b45..54d0954 100644 --- a/CryptoExchange.Net/Sockets/Query.cs +++ b/CryptoExchange.Net/Sockets/Query.cs @@ -24,6 +24,17 @@ namespace CryptoExchange.Net.Sockets /// public bool Completed { get; set; } + /// + /// The number of required responses. Can be more than 1 when for example subscribing multiple symbols streams in a single request, + /// and each symbol receives it's own confirmation response + /// + public int RequiredResponses { get; set; } = 1; + + /// + /// The current number of responses received on this query + /// + public int CurrentResponses { get; set; } + /// /// Timestamp of when the request was send /// @@ -108,7 +119,7 @@ namespace CryptoExchange.Net.Sockets } /// - /// Wait untill timeout or the request is competed + /// Wait until timeout or the request is completed /// /// /// Cancellation token @@ -167,12 +178,24 @@ namespace CryptoExchange.Net.Sockets /// public override async Task Handle(SocketConnection connection, DataEvent message) { - Completed = true; - Response = message.Data; - Result = HandleMessage(connection, message.As((TServerResponse)message.Data)); - _event.Set(); - if (ContinueAwaiter != null) - await ContinueAwaiter.WaitAsync().ConfigureAwait(false); + CurrentResponses++; + if (CurrentResponses == RequiredResponses) + { + Completed = true; + Response = message.Data; + } + + if (Result?.Success != false) + // If an error result is already set don't override that + Result = HandleMessage(connection, message.As((TServerResponse)message.Data)); + + if (CurrentResponses == RequiredResponses) + { + _event.Set(); + if (ContinueAwaiter != null) + await ContinueAwaiter.WaitAsync().ConfigureAwait(false); + } + return Result; } diff --git a/CryptoExchange.Net/Sockets/SocketConnection.cs b/CryptoExchange.Net/Sockets/SocketConnection.cs index 502468f..33c1e98 100644 --- a/CryptoExchange.Net/Sockets/SocketConnection.cs +++ b/CryptoExchange.Net/Sockets/SocketConnection.cs @@ -508,6 +508,8 @@ namespace CryptoExchange.Net.Sockets { var innerSw = Stopwatch.StartNew(); await processor.Handle(this, new DataEvent(deserialized, null, null, originalData, receiveTime, null)).ConfigureAwait(false); + if (processor is Query query && query.RequiredResponses != 1) + _logger.LogDebug($"[Sckt {SocketId}] [Req {query.Id}] responses: {query.CurrentResponses}/{query.RequiredResponses}"); totalUserTime += (int)innerSw.ElapsedMilliseconds; } catch (Exception ex) @@ -573,9 +575,8 @@ namespace CryptoExchange.Net.Sockets /// Close a subscription on this connection. If all subscriptions on this connection are closed the connection gets closed as well /// /// Subscription to close - /// Whether to send an unsub request even if the subscription wasn't confirmed /// - public async Task CloseAsync(Subscription subscription, bool unsubEvenIfNotConfirmed = false) + public async Task CloseAsync(Subscription subscription) { subscription.Closed = true; @@ -596,7 +597,7 @@ namespace CryptoExchange.Net.Sockets lock (_listenersLock) needUnsub = _listeners.Contains(subscription); - if (needUnsub && (unsubEvenIfNotConfirmed || subscription.Confirmed) && _socket.IsOpen) + if (needUnsub && _socket.IsOpen) await UnsubscribeAsync(subscription).ConfigureAwait(false); } else