mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-10-13 22:51:39 +00:00
WebSocket covered subscriptions
Updated WebSocket duplicate subscription handling Fixed incorrect status keeping of WebSocket subscriptions which don't expect a response
This commit is contained in:
@@ -23,6 +23,10 @@ namespace CryptoExchange.Net.SharedApis
|
||||
/// Get user funding history capability.
|
||||
/// </summary>
|
||||
public static SharedRestCapability<IGetUserFundingHistory, IGetUserFundingHistoryRest> GetUserFundingHistory { get; } = new();
|
||||
/// <summary>
|
||||
/// Subscribe to funding info updates capability.
|
||||
/// </summary>
|
||||
public static SharedCapabilityReference<ISubscribeFundingInfoSocket> SubscribeFundingInfo { get; } = new();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -702,7 +702,7 @@ namespace CryptoExchange.Net.Sockets.Default
|
||||
if (subscription.CancellationTokenRegistration.HasValue)
|
||||
subscription.CancellationTokenRegistration.Value.Dispose();
|
||||
|
||||
bool anyDuplicateSubscription = _listeners.OfType<Subscription>().Any(x => x != subscription && x.MessageRouter.Routes.All(l => subscription.MessageRouter.ContainsCheck(l)));
|
||||
bool anyDuplicateSubscription = SubscriptionIsCovered(subscription);
|
||||
bool shouldCloseConnection = _listeners.OfType<Subscription>().All(r => !r.UserSubscription || r.Status == SubscriptionStatus.Closing || r.Status == SubscriptionStatus.Closed) && !DedicatedRequestConnection.IsDedicatedRequestConnection;
|
||||
|
||||
if (!anyDuplicateSubscription)
|
||||
@@ -1069,6 +1069,32 @@ namespace CryptoExchange.Net.Sockets.Default
|
||||
return CallResult.Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether there is currently a subscription covering all the routes the subscription lists
|
||||
/// </summary>
|
||||
protected bool SubscriptionIsCovered(Subscription subscription)
|
||||
=> _listeners.OfType<Subscription>().Any(
|
||||
x => x != subscription
|
||||
&& x.Active
|
||||
&& x.MessageRouter.Routes.All(l => subscription.MessageRouter.ContainsCheck(l)));
|
||||
|
||||
/// <summary>
|
||||
/// Whether there is a subscription earlier in the list covering all the routes the subscription lists
|
||||
/// </summary>
|
||||
protected bool IsCoveredByEarlierSubscription(Subscription subscription)
|
||||
{
|
||||
foreach (var other in _listeners.OfType<Subscription>())
|
||||
{
|
||||
if (other == subscription)
|
||||
return false;
|
||||
|
||||
if (other.Active && other.MessageRouter.Routes.All(x => subscription.MessageRouter.ContainsCheck(x)))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to subscribe a new subscription by sending the subscribe query and wait for the result as needed
|
||||
/// </summary>
|
||||
@@ -1103,11 +1129,11 @@ namespace CryptoExchange.Net.Sockets.Default
|
||||
return WebSocketResult.Ok(ApiClient.Exchange, SocketId, default, 0, ConnectionUriString);
|
||||
}
|
||||
|
||||
var subCompleteHandler = () =>
|
||||
var subCompleteHandler = (bool success) =>
|
||||
{
|
||||
subscription.Status = subQuery.Success ? SubscriptionStatus.Subscribed : SubscriptionStatus.Pending;
|
||||
subscription.Status = success ? SubscriptionStatus.Subscribed : SubscriptionStatus.Pending;
|
||||
subscription.HandleSubQueryResponse(this, subQuery.Response);
|
||||
if (newSubscription && subQuery.Success)
|
||||
if (newSubscription && success)
|
||||
{
|
||||
subscription.TokenExpired += HandleTokenExpired;
|
||||
if (subCancelToken != default)
|
||||
@@ -1122,6 +1148,14 @@ namespace CryptoExchange.Net.Sockets.Default
|
||||
};
|
||||
subQuery.OnComplete = subCompleteHandler;
|
||||
|
||||
// For duplicate subscription don't send another subscribe request but just handle it internally
|
||||
// Unsubscribe also doesn't unsubscribe when there is still a duplicate subscription running
|
||||
if (IsCoveredByEarlierSubscription(subscription))
|
||||
{
|
||||
subQuery.Complete();
|
||||
return WebSocketResult.Ok(ApiClient.Exchange, SocketId, default, subQuery.Id, ConnectionUriString);
|
||||
}
|
||||
|
||||
var subQueryResult = await SendAndWaitQueryAsync(subQuery).ConfigureAwait(false);
|
||||
if (!subQueryResult.Success)
|
||||
{
|
||||
@@ -1132,9 +1166,6 @@ namespace CryptoExchange.Net.Sockets.Default
|
||||
return WebSocketResult.Fail(ApiClient.Exchange, subQueryResult.Error!);
|
||||
}
|
||||
|
||||
if (!subQuery.ExpectsResponse)
|
||||
subCompleteHandler();
|
||||
|
||||
return subQueryResult;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace CryptoExchange.Net.Sockets
|
||||
/// <summary>
|
||||
/// On complete callback
|
||||
/// </summary>
|
||||
public Action? OnComplete { get; set; }
|
||||
public Action<bool>? OnComplete { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public event Action? OnMessageRouterUpdated;
|
||||
@@ -157,8 +157,7 @@ namespace CryptoExchange.Net.Sockets
|
||||
}
|
||||
else
|
||||
{
|
||||
Completed = true;
|
||||
_event.Set();
|
||||
Complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,6 +174,11 @@ namespace CryptoExchange.Net.Sockets
|
||||
/// </summary>
|
||||
public abstract void Timeout();
|
||||
|
||||
/// <summary>
|
||||
/// Mark request as successfully completed
|
||||
/// </summary>
|
||||
public abstract void Complete();
|
||||
|
||||
/// <summary>
|
||||
/// Mark request as failed
|
||||
/// </summary>
|
||||
@@ -248,7 +252,7 @@ namespace CryptoExchange.Net.Sockets
|
||||
{
|
||||
Completed = true;
|
||||
_event.Set();
|
||||
OnComplete?.Invoke();
|
||||
OnComplete?.Invoke(Success);
|
||||
}
|
||||
|
||||
return handled;
|
||||
@@ -267,7 +271,19 @@ namespace CryptoExchange.Net.Sockets
|
||||
|
||||
Completed = true;
|
||||
_event.Set();
|
||||
OnComplete?.Invoke();
|
||||
OnComplete?.Invoke(Success);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Complete()
|
||||
{
|
||||
if (Completed)
|
||||
return;
|
||||
|
||||
Result = CallResult<THandlerResponse>.Ok(default!);
|
||||
Completed = true;
|
||||
_event.Set();
|
||||
OnComplete?.Invoke(Success);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -280,7 +296,7 @@ namespace CryptoExchange.Net.Sockets
|
||||
Completed = true;
|
||||
|
||||
_event.Set();
|
||||
OnComplete?.Invoke();
|
||||
OnComplete?.Invoke(Success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user