1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-07 16:06:15 +00:00

Added support for requiring multiple responses for queries, fixed possible exception when closing connection, added ToString override DataEvent object

This commit is contained in:
JKorf 2024-07-16 15:23:09 +02:00
parent 17d85fdd85
commit a85bfb4432
11 changed files with 50 additions and 12 deletions

View File

@ -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<UpdateSubscription>(subResult.Error!);
}
}

View File

@ -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<ILogger, int, Exception?> _connecting;

View File

@ -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<ILogger, int, string, string, string, Exception?> _rateLimitRequestFailed;

View File

@ -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<ILogger, int?, int?, long, string?, Exception?> _restApiErrorReceived;

View File

@ -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<ILogger, int, Exception?> _failedToAddSubscriptionRetryOnDifferentConnection;

View File

@ -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<ILogger, int, bool, Exception?> _activityPaused;

View File

@ -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<ILogger, string, string, OrderBookStatus, OrderBookStatus, Exception?> _orderBookStatusChanged;

View File

@ -144,5 +144,11 @@ namespace CryptoExchange.Net.Objects.Sockets
{
return new CallResult<K>(default, OriginalData, error);
}
/// <inheritdoc />
public override string ToString()
{
return $"{StreamId} - {(Symbol == null ? "" : (Symbol + " - "))}{(UpdateType == null ? "" : (UpdateType + " - "))}{Data}";
}
}
}

View File

@ -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)
{

View File

@ -24,6 +24,17 @@ namespace CryptoExchange.Net.Sockets
/// </summary>
public bool Completed { get; set; }
/// <summary>
/// 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
/// </summary>
public int RequiredResponses { get; set; } = 1;
/// <summary>
/// The current number of responses received on this query
/// </summary>
public int CurrentResponses { get; set; }
/// <summary>
/// Timestamp of when the request was send
/// </summary>
@ -108,7 +119,7 @@ namespace CryptoExchange.Net.Sockets
}
/// <summary>
/// Wait untill timeout or the request is competed
/// Wait until timeout or the request is completed
/// </summary>
/// <param name="timeout"></param>
/// <param name="ct">Cancellation token</param>
@ -167,12 +178,24 @@ namespace CryptoExchange.Net.Sockets
/// <inheritdoc />
public override async Task<CallResult> Handle(SocketConnection connection, DataEvent<object> 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;
}

View File

@ -508,6 +508,8 @@ namespace CryptoExchange.Net.Sockets
{
var innerSw = Stopwatch.StartNew();
await processor.Handle(this, new DataEvent<object>(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
/// </summary>
/// <param name="subscription">Subscription to close</param>
/// <param name="unsubEvenIfNotConfirmed">Whether to send an unsub request even if the subscription wasn't confirmed</param>
/// <returns></returns>
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