mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-08 16:36:15 +00:00
wip
This commit is contained in:
parent
bf854c92af
commit
bee2e86c2f
@ -109,6 +109,9 @@ namespace CryptoExchange.Net
|
||||
|
||||
/// <inheritdoc />
|
||||
public new SocketApiOptions ApiOptions => (SocketApiOptions)base.ApiOptions;
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract SocketConverter StreamConverter { get; }
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@ -457,8 +460,6 @@ namespace CryptoExchange.Net
|
||||
return messageListener;
|
||||
}
|
||||
|
||||
protected internal abstract SocketConverter GetConverter();
|
||||
|
||||
/// <summary>
|
||||
/// Adds a system subscription. Used for example to reply to ping requests
|
||||
/// </summary>
|
||||
@ -552,7 +553,7 @@ namespace CryptoExchange.Net
|
||||
/// Process an unhandled message
|
||||
/// </summary>
|
||||
/// <param name="message">The message that wasn't processed</param>
|
||||
protected virtual void HandleUnhandledMessage(StreamMessage message)
|
||||
protected virtual void HandleUnhandledMessage(ParsedMessage message)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -3,35 +3,31 @@ using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.Converters
|
||||
{
|
||||
public class SocketConverter : JsonConverter
|
||||
public abstract class SocketConverter
|
||||
{
|
||||
private readonly List<string> _idFields;
|
||||
private readonly Func<Dictionary<string, string>, Type> _typeIdentifier;
|
||||
public abstract string[] IdFields { get; }
|
||||
|
||||
public SocketConverter(List<string> idFields, Func<Dictionary<string, string>, Type> typeIdentifier)
|
||||
{
|
||||
_idFields = idFields;
|
||||
_typeIdentifier = typeIdentifier;
|
||||
}
|
||||
public abstract Type? GetDeserializationType(Dictionary<string, string> idValues, List<MessageListener> listeners);
|
||||
public abstract List<MessageListener> MatchToListener(ParsedMessage message, List<MessageListener> listeners);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool CanConvert(Type objectType) => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
||||
public object? ReadJson(Stream stream, List<MessageListener> listeners)
|
||||
{
|
||||
// Start reading the data
|
||||
// Once we reach the property that identifies the message we save those in a string array
|
||||
// Once we reach the properties that identify the message we save those in a dict
|
||||
// Once all id properties have been read callback to see what the deserialization type should be
|
||||
// Deserialize to the correct type
|
||||
using var sr = new StreamReader(stream, Encoding.UTF8, false, (int)stream.Length, true);
|
||||
using var jsonTextReader = new JsonTextReader(sr);
|
||||
|
||||
var token = JToken.Load(reader);
|
||||
var token = JToken.Load(jsonTextReader);
|
||||
var dict = new Dictionary<string, string>();
|
||||
foreach(var idField in _idFields)
|
||||
foreach(var idField in IdFields)
|
||||
{
|
||||
var splitTokens = idField.Split(new char[] { ':' });
|
||||
var accessToken = token;
|
||||
@ -42,7 +38,7 @@ namespace CryptoExchange.Net.Converters
|
||||
dict[idField] = accessToken?.ToString();
|
||||
}
|
||||
|
||||
var resultType = _typeIdentifier(dict);
|
||||
var resultType = GetDeserializationType(dict, listeners);
|
||||
string idString = "";
|
||||
foreach(var item in dict)
|
||||
idString += item.Value;
|
||||
@ -53,20 +49,12 @@ namespace CryptoExchange.Net.Converters
|
||||
Data = resultType == null ? null : token.ToObject(resultType)
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool CanWrite { get { return false; } }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class ParsedMessage
|
||||
{
|
||||
public string Identifier { get; set; }
|
||||
public string Identifier { get; set; } = null!;
|
||||
|
||||
public object Data { get; set; }
|
||||
public object? Data { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using CryptoExchange.Net.Objects.Sockets;
|
||||
using CryptoExchange.Net.Converters;
|
||||
using CryptoExchange.Net.Objects.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CryptoExchange.Net.Interfaces
|
||||
@ -6,7 +7,7 @@ namespace CryptoExchange.Net.Interfaces
|
||||
internal interface IStreamMessageListener
|
||||
{
|
||||
int Priority { get; }
|
||||
bool MessageMatches(StreamMessage message);
|
||||
Task ProcessAsync(StreamMessage message);
|
||||
bool MessageMatches(ParsedMessage message);
|
||||
Task ProcessAsync(ParsedMessage message);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using CryptoExchange.Net.Interfaces;
|
||||
using CryptoExchange.Net.Converters;
|
||||
using CryptoExchange.Net.Interfaces;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@ -8,7 +9,7 @@ namespace CryptoExchange.Net.Objects.Sockets
|
||||
internal class PendingRequest : IStreamMessageListener
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public Func<StreamMessage, bool> MessageMatchesHandler { get; }
|
||||
public Func<ParsedMessage, bool> MessageMatchesHandler { get; }
|
||||
public bool Completed { get; private set; }
|
||||
public AsyncResetEvent Event { get; }
|
||||
public DateTime RequestTimestamp { get; set; }
|
||||
@ -19,7 +20,7 @@ namespace CryptoExchange.Net.Objects.Sockets
|
||||
|
||||
public int Priority => 100;
|
||||
|
||||
public PendingRequest(int id, Func<StreamMessage, bool> messageMatchesHandler, TimeSpan timeout, MessageListener? subscription)
|
||||
public PendingRequest(int id, Func<ParsedMessage, bool> messageMatchesHandler, TimeSpan timeout, MessageListener? subscription)
|
||||
{
|
||||
Id = id;
|
||||
MessageMatchesHandler = messageMatchesHandler;
|
||||
@ -42,12 +43,12 @@ namespace CryptoExchange.Net.Objects.Sockets
|
||||
Event.Set();
|
||||
}
|
||||
|
||||
public bool MessageMatches(StreamMessage message)
|
||||
public bool MessageMatches(ParsedMessage message)
|
||||
{
|
||||
return MessageMatchesHandler(message);
|
||||
}
|
||||
|
||||
public Task ProcessAsync(StreamMessage message)
|
||||
public Task ProcessAsync(ParsedMessage message)
|
||||
{
|
||||
Completed = true;
|
||||
Event.Set();
|
||||
|
@ -1,4 +1,5 @@
|
||||
using CryptoExchange.Net.Interfaces;
|
||||
using CryptoExchange.Net.Converters;
|
||||
using CryptoExchange.Net.Interfaces;
|
||||
using CryptoExchange.Net.Sockets;
|
||||
using System;
|
||||
using System.Threading;
|
||||
@ -84,13 +85,18 @@ namespace CryptoExchange.Net.Objects.Sockets
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public bool MessageMatches(StreamMessage message) => Subscription.MessageMatchesEvent(message);
|
||||
public bool MessageMatches(ParsedMessage message) => Subscription.MessageMatchesEvent(message);
|
||||
|
||||
/// <summary>
|
||||
/// Process the message
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public Task ProcessAsync(StreamMessage message) => Subscription.HandleEventAsync(message);
|
||||
public Task ProcessAsync(ParsedMessage message)
|
||||
{
|
||||
// TODO
|
||||
var dataEvent = new DataEvent<ParsedMessage>(message, null, null, DateTime.UtcNow, null);
|
||||
return Subscription.HandleEventAsync(dataEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,70 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using CryptoExchange.Net.Sockets;
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Data.Common;
|
||||
//using System.IO;
|
||||
//using System.Text;
|
||||
//using System.Threading.Tasks;
|
||||
//using CryptoExchange.Net.Sockets;
|
||||
|
||||
namespace CryptoExchange.Net.Objects.Sockets
|
||||
{
|
||||
/// <summary>
|
||||
/// A message received from a stream
|
||||
/// </summary>
|
||||
public class StreamMessage : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The connection it was received on
|
||||
/// </summary>
|
||||
public SocketConnection Connection { get; }
|
||||
/// <summary>
|
||||
/// The data stream
|
||||
/// </summary>
|
||||
public Stream Stream { get; }
|
||||
/// <summary>
|
||||
/// Receive timestamp
|
||||
/// </summary>
|
||||
public DateTime Timestamp { get; set; }
|
||||
//namespace CryptoExchange.Net.Objects.Sockets
|
||||
//{
|
||||
// /// <summary>
|
||||
// /// A message received from a stream
|
||||
// /// </summary>
|
||||
// public class StreamMessage : IDisposable
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// The connection it was received on
|
||||
// /// </summary>
|
||||
// public SocketConnection Connection { get; }
|
||||
// /// <summary>
|
||||
// /// The data stream
|
||||
// /// </summary>
|
||||
// public Stream Stream { get; }
|
||||
// /// <summary>
|
||||
// /// Receive timestamp
|
||||
// /// </summary>
|
||||
// public DateTime Timestamp { get; set; }
|
||||
|
||||
private Dictionary<Type, object> _casted;
|
||||
// private Dictionary<Type, object> _casted;
|
||||
|
||||
/// <summary>
|
||||
/// Get the data from the memory in specified type using the converter. If this type has been resolved before it will use that instead
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="converter"></param>
|
||||
/// <returns></returns>
|
||||
public T Get<T>(Func<Stream, T> converter)
|
||||
{
|
||||
if (_casted.TryGetValue(typeof(T), out var casted))
|
||||
return (T)casted;
|
||||
// /// <summary>
|
||||
// /// Get the data from the memory in specified type using the converter. If this type has been resolved before it will use that instead
|
||||
// /// </summary>
|
||||
// /// <typeparam name="T"></typeparam>
|
||||
// /// <param name="converter"></param>
|
||||
// /// <returns></returns>
|
||||
// public T Get<T>(Func<Stream, T> converter)
|
||||
// {
|
||||
// if (_casted.TryGetValue(typeof(T), out var casted))
|
||||
// return (T)casted;
|
||||
|
||||
var result = converter(Stream);
|
||||
_casted.Add(typeof(T), result!);
|
||||
Stream.Position = 0;
|
||||
return result;
|
||||
}
|
||||
// var result = converter(Stream);
|
||||
// _casted.Add(typeof(T), result!);
|
||||
// Stream.Position = 0;
|
||||
// return result;
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Dispose
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Stream.Dispose();
|
||||
}
|
||||
// /// <summary>
|
||||
// /// Dispose
|
||||
// /// </summary>
|
||||
// public void Dispose()
|
||||
// {
|
||||
// Stream.Dispose();
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="connection"></param>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="timestamp"></param>
|
||||
public StreamMessage(SocketConnection connection, Stream stream, DateTime timestamp)
|
||||
{
|
||||
Connection = connection;
|
||||
Stream = stream;
|
||||
Timestamp = timestamp;
|
||||
_casted = new Dictionary<Type, object>();
|
||||
}
|
||||
}
|
||||
}
|
||||
// /// <summary>
|
||||
// /// ctor
|
||||
// /// </summary>
|
||||
// /// <param name="connection"></param>
|
||||
// /// <param name="stream"></param>
|
||||
// /// <param name="timestamp"></param>
|
||||
// public StreamMessage(SocketConnection connection, Stream stream, DateTime timestamp)
|
||||
// {
|
||||
// Connection = connection;
|
||||
// Stream = stream;
|
||||
// Timestamp = timestamp;
|
||||
// _casted = new Dictionary<Type, object>();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using CryptoExchange.Net.Converters;
|
||||
using CryptoExchange.Net.Objects;
|
||||
using CryptoExchange.Net.Objects.Sockets;
|
||||
|
||||
namespace CryptoExchange.Net.Sockets
|
||||
@ -28,13 +29,13 @@ namespace CryptoExchange.Net.Sockets
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public abstract bool MessageMatchesQuery(StreamMessage message);
|
||||
public abstract bool MessageMatchesQuery(ParsedMessage message);
|
||||
/// <summary>
|
||||
/// Handle the query response
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public abstract CallResult HandleResponse(StreamMessage message);
|
||||
public abstract CallResult HandleResponse(ParsedMessage message);
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
|
@ -49,7 +49,7 @@ namespace CryptoExchange.Net.Sockets
|
||||
/// <summary>
|
||||
/// Unhandled message event
|
||||
/// </summary>
|
||||
public event Action<StreamMessage>? UnhandledMessage;
|
||||
public event Action<ParsedMessage>? UnhandledMessage;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of listeners on this connection
|
||||
@ -57,7 +57,7 @@ namespace CryptoExchange.Net.Sockets
|
||||
public int UserListenerCount
|
||||
{
|
||||
get { lock (_listenerLock)
|
||||
return _listeners.Count(h => h.UserListener); }
|
||||
return _messageIdentifierListeners.Count(h => h.UserListener); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -153,10 +153,11 @@ namespace CryptoExchange.Net.Sockets
|
||||
}
|
||||
|
||||
private bool _pausedActivity;
|
||||
private readonly List<MessageListener> _listeners;
|
||||
private readonly List<IStreamMessageListener> _messageListeners; // ?
|
||||
//private readonly List<MessageListener> _listeners;
|
||||
//private readonly List<IStreamMessageListener> _messageListeners; // ?
|
||||
|
||||
private readonly Dictionary<string, IStreamMessageListener> _messageIdentifierListeners;
|
||||
private readonly List<PendingRequest> _pendingRequests;
|
||||
private readonly Dictionary<string, MessageListener> _messageIdentifierListeners;
|
||||
|
||||
private readonly object _listenerLock = new();
|
||||
private readonly ILogger _logger;
|
||||
@ -167,8 +168,6 @@ namespace CryptoExchange.Net.Sockets
|
||||
/// The underlying websocket
|
||||
/// </summary>
|
||||
private readonly IWebsocket _socket;
|
||||
private readonly JsonSerializerSettings _options;
|
||||
private readonly JsonSerializer _serializer;
|
||||
|
||||
/// <summary>
|
||||
/// New socket connection
|
||||
@ -184,9 +183,8 @@ namespace CryptoExchange.Net.Sockets
|
||||
Tag = tag;
|
||||
Properties = new Dictionary<string, object>();
|
||||
|
||||
_messageListeners = new List<IStreamMessageListener>();
|
||||
_pendingRequests = new List<PendingRequest>();
|
||||
_messageIdentifierListeners = new Dictionary<string, IStreamMessageListener>();
|
||||
_listeners = new List<MessageListener>();
|
||||
|
||||
_socket = socket;
|
||||
_socket.OnStreamMessage += HandleStreamMessage;
|
||||
@ -197,11 +195,6 @@ namespace CryptoExchange.Net.Sockets
|
||||
_socket.OnReconnected += HandleReconnected;
|
||||
_socket.OnError += HandleError;
|
||||
_socket.GetReconnectionUrl = GetReconnectionUrlAsync;
|
||||
|
||||
var converter = ApiClient.GetConverter();
|
||||
_options = SerializerOptions.Default;
|
||||
_options.Converters.Add(converter);
|
||||
_serializer = JsonSerializer.Create(_options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -222,7 +215,7 @@ namespace CryptoExchange.Net.Sockets
|
||||
Authenticated = false;
|
||||
lock(_listenerLock)
|
||||
{
|
||||
foreach (var listener in _listeners)
|
||||
foreach (var listener in _messageIdentifierListeners.Values)
|
||||
listener.Confirmed = false;
|
||||
}
|
||||
Task.Run(() => ConnectionClosed?.Invoke());
|
||||
@ -325,81 +318,101 @@ namespace CryptoExchange.Net.Sockets
|
||||
protected virtual async Task HandleStreamMessage(Stream stream)
|
||||
{
|
||||
var timestamp = DateTime.UtcNow;
|
||||
var streamMessage = new StreamMessage(this, stream, timestamp);
|
||||
var handledResponse = false;
|
||||
MessageListener? currentSubscription = null;
|
||||
//var streamMessage = new StreamMessage(this, stream, timestamp);
|
||||
TimeSpan userCodeDuration = TimeSpan.Zero;
|
||||
|
||||
List<IStreamMessageListener> listeners;
|
||||
lock (_listenerLock)
|
||||
listeners = _messageListeners.OrderByDescending(x => x.Priority).ToList();
|
||||
|
||||
var converter = ApiClient.GetConverter();
|
||||
using var sr = new StreamReader(stream, Encoding.UTF8, false, (int)stream.Length, true);
|
||||
using var jsonTextReader = new JsonTextReader(sr);
|
||||
var result = (ParsedMessage)converter.ReadJson(jsonTextReader, typeof(object), null, _serializer);
|
||||
var result = (ParsedMessage)ApiClient.StreamConverter.ReadJson(stream, listeners.OfType<MessageListener>().ToList()); // TODO
|
||||
stream.Position = 0;
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
_logger.LogWarning("Message not matched to type");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_messageIdentifierListeners.TryGetValue(result.Identifier.ToLowerInvariant(), out var idListener))
|
||||
{
|
||||
var userSw = Stopwatch.StartNew();
|
||||
await idListener.ProcessAsync(streamMessage).ConfigureAwait(false);
|
||||
userSw.Stop();
|
||||
userCodeDuration = userSw.Elapsed;
|
||||
handledResponse = true;
|
||||
// Matched based on identifier
|
||||
await idListener.ProcessAsync(result).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
foreach (var pendingRequest in _messageListeners.OfType<PendingRequest>())
|
||||
{
|
||||
foreach (var listener in listeners)
|
||||
if (pendingRequest.MessageMatchesHandler(result))
|
||||
{
|
||||
if (listener.MessageMatches(streamMessage))
|
||||
{
|
||||
if (listener is PendingRequest pendingRequest)
|
||||
{
|
||||
lock (_messageListeners)
|
||||
_messageListeners.Remove(pendingRequest);
|
||||
|
||||
if (pendingRequest.Completed)
|
||||
{
|
||||
// Answer to a timed out request, unsub if it is a subscription request
|
||||
if (pendingRequest.MessageListener != null)
|
||||
{
|
||||
_logger.Log(LogLevel.Warning, $"Socket {SocketId} Received subscription info after request timed out; unsubscribing. Consider increasing the RequestTimeout");
|
||||
_ = UnsubscribeAsync(pendingRequest.MessageListener).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Trace, $"Socket {SocketId} - msg {pendingRequest.Id} - received data matched to pending request");
|
||||
await pendingRequest.ProcessAsync(streamMessage).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!ApiClient.ContinueOnQueryResponse)
|
||||
return;
|
||||
|
||||
handledResponse = true;
|
||||
break;
|
||||
}
|
||||
else if (listener is MessageListener subscription)
|
||||
{
|
||||
currentSubscription = subscription;
|
||||
handledResponse = true;
|
||||
var userSw = Stopwatch.StartNew();
|
||||
await subscription.ProcessAsync(streamMessage).ConfigureAwait(false);
|
||||
userSw.Stop();
|
||||
userCodeDuration = userSw.Elapsed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await pendingRequest.ProcessAsync(result).ConfigureAwait(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!handledResponse)
|
||||
{
|
||||
if (!ApiClient.UnhandledMessageExpected)
|
||||
_logger.Log(LogLevel.Warning, $"Socket {SocketId} Message not handled: " + streamMessage.Get(ParsingUtils.GetString));
|
||||
UnhandledMessage?.Invoke(streamMessage);
|
||||
}
|
||||
_logger.LogWarning("Message not matched"); // TODO
|
||||
return;
|
||||
|
||||
//if (_messageIdentifierListeners.TryGetValue(result.Identifier.ToLowerInvariant(), out var idListener))
|
||||
//{
|
||||
// var userSw = Stopwatch.StartNew();
|
||||
// await idListener.ProcessAsync(streamMessage).ConfigureAwait(false);
|
||||
// userSw.Stop();
|
||||
// userCodeDuration = userSw.Elapsed;
|
||||
// handledResponse = true;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// foreach (var listener in listeners)
|
||||
// {
|
||||
// if (listener.MessageMatches(streamMessage))
|
||||
// {
|
||||
// if (listener is PendingRequest pendingRequest)
|
||||
// {
|
||||
// lock (_messageListeners)
|
||||
// _messageListeners.Remove(pendingRequest);
|
||||
|
||||
// if (pendingRequest.Completed)
|
||||
// {
|
||||
// // Answer to a timed out request, unsub if it is a subscription request
|
||||
// if (pendingRequest.MessageListener != null)
|
||||
// {
|
||||
// _logger.Log(LogLevel.Warning, $"Socket {SocketId} Received subscription info after request timed out; unsubscribing. Consider increasing the RequestTimeout");
|
||||
// _ = UnsubscribeAsync(pendingRequest.MessageListener).ConfigureAwait(false);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// _logger.Log(LogLevel.Trace, $"Socket {SocketId} - msg {pendingRequest.Id} - received data matched to pending request");
|
||||
// await pendingRequest.ProcessAsync(streamMessage).ConfigureAwait(false);
|
||||
// }
|
||||
|
||||
// if (!ApiClient.ContinueOnQueryResponse)
|
||||
// return;
|
||||
|
||||
// handledResponse = true;
|
||||
// break;
|
||||
// }
|
||||
// else if (listener is MessageListener subscription)
|
||||
// {
|
||||
// currentSubscription = subscription;
|
||||
// handledResponse = true;
|
||||
// var userSw = Stopwatch.StartNew();
|
||||
// await subscription.ProcessAsync(streamMessage).ConfigureAwait(false);
|
||||
// userSw.Stop();
|
||||
// userCodeDuration = userSw.Elapsed;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//if (!handledResponse)
|
||||
//{
|
||||
// if (!ApiClient.UnhandledMessageExpected)
|
||||
// _logger.Log(LogLevel.Warning, $"Socket {SocketId} Message not handled: " + streamMessage.Get(ParsingUtils.GetString));
|
||||
// UnhandledMessage?.Invoke(streamMessage);
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -434,7 +447,7 @@ namespace CryptoExchange.Net.Sockets
|
||||
|
||||
lock (_listenerLock)
|
||||
{
|
||||
foreach (var listener in _listeners)
|
||||
foreach (var listener in _messageIdentifierListeners.Values)
|
||||
{
|
||||
if (listener.CancellationTokenRegistration.HasValue)
|
||||
listener.CancellationTokenRegistration.Value.Dispose();
|
||||
@ -562,7 +575,7 @@ namespace CryptoExchange.Net.Sockets
|
||||
/// <param name="handler">The response handler</param>
|
||||
/// <param name="weight">The weight of the message</param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task SendAndWaitAsync<T>(T obj, TimeSpan timeout, MessageListener? listener, int weight, Func<StreamMessage, bool> handler)
|
||||
public virtual async Task SendAndWaitAsync<T>(T obj, TimeSpan timeout, MessageListener? listener, int weight, Func<ParsedMessage, bool> handler)
|
||||
{
|
||||
var pending = new PendingRequest(ExchangeHelpers.NextId(), handler, timeout, listener);
|
||||
lock (_messageListeners)
|
||||
|
@ -1,4 +1,5 @@
|
||||
using CryptoExchange.Net.Interfaces;
|
||||
using CryptoExchange.Net.Converters;
|
||||
using CryptoExchange.Net.Interfaces;
|
||||
using CryptoExchange.Net.Objects;
|
||||
using CryptoExchange.Net.Objects.Sockets;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@ -52,7 +53,7 @@ namespace CryptoExchange.Net.Sockets
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public abstract (bool, CallResult?) MessageMatchesSubRequest(StreamMessage message);
|
||||
public abstract (bool, CallResult?) MessageMatchesSubRequest(ParsedMessage message);
|
||||
|
||||
/// <summary>
|
||||
/// Get the unsubscribe object to send when unsubscribing
|
||||
@ -64,54 +65,54 @@ namespace CryptoExchange.Net.Sockets
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public abstract (bool, CallResult?) MessageMatchesUnsubRequest(StreamMessage message);
|
||||
public abstract (bool, CallResult?) MessageMatchesUnsubRequest(ParsedMessage message);
|
||||
|
||||
/// <summary>
|
||||
/// Check if the message is an update for this subscription
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public abstract bool MessageMatchesEvent(StreamMessage message);
|
||||
public abstract bool MessageMatchesEvent(ParsedMessage message);
|
||||
/// <summary>
|
||||
/// Handle the update message
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public abstract Task HandleEventAsync(StreamMessage message);
|
||||
public abstract Task HandleEventAsync(DataEvent<ParsedMessage> message);
|
||||
|
||||
/// <summary>
|
||||
/// Create a data event
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="obj"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="topic"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual DataEvent<T> CreateDataEvent<T>(T obj, StreamMessage message, string? topic = null, SocketUpdateType? type = null)
|
||||
{
|
||||
string? originalData = null;
|
||||
if (_outputOriginalData)
|
||||
originalData = message.Get(ParsingUtils.GetString);
|
||||
///// <summary>
|
||||
///// Create a data event
|
||||
///// </summary>
|
||||
///// <typeparam name="T"></typeparam>
|
||||
///// <param name="obj"></param>
|
||||
///// <param name="message"></param>
|
||||
///// <param name="topic"></param>
|
||||
///// <param name="type"></param>
|
||||
///// <returns></returns>
|
||||
//protected virtual DataEvent<T> CreateDataEvent<T>(T obj, ParsedMessage message, string? topic = null, SocketUpdateType? type = null)
|
||||
//{
|
||||
// string? originalData = null;
|
||||
// if (_outputOriginalData)
|
||||
// originalData = message.Get(ParsingUtils.GetString);
|
||||
|
||||
return new DataEvent<T>(obj, topic, originalData, message.Timestamp, type);
|
||||
}
|
||||
// return new DataEvent<T>(obj, topic, originalData, message.Timestamp, type);
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize the message to an object using Json.Net
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="settings"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual Task<CallResult<T>> DeserializeAsync<T>(StreamMessage message, JsonSerializerSettings settings)
|
||||
{
|
||||
var serializer = JsonSerializer.Create(settings);
|
||||
using var sr = new StreamReader(message.Stream, Encoding.UTF8, false, (int)message.Stream.Length, true);
|
||||
using var jsonTextReader = new JsonTextReader(sr);
|
||||
var result = serializer.Deserialize<T>(jsonTextReader);
|
||||
message.Stream.Position = 0;
|
||||
return Task.FromResult(new CallResult<T>(result!));
|
||||
}
|
||||
///// <summary>
|
||||
///// Deserialize the message to an object using Json.Net
|
||||
///// </summary>
|
||||
///// <typeparam name="T"></typeparam>
|
||||
///// <param name="message"></param>
|
||||
///// <param name="settings"></param>
|
||||
///// <returns></returns>
|
||||
//protected virtual Task<CallResult<T>> DeserializeAsync<T>(StreamMessage message, JsonSerializerSettings settings)
|
||||
//{
|
||||
// var serializer = JsonSerializer.Create(settings);
|
||||
// using var sr = new StreamReader(message.Stream, Encoding.UTF8, false, (int)message.Stream.Length, true);
|
||||
// using var jsonTextReader = new JsonTextReader(sr);
|
||||
// var result = serializer.Deserialize<T>(jsonTextReader);
|
||||
// message.Stream.Position = 0;
|
||||
// return Task.FromResult(new CallResult<T>(result!));
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using CryptoExchange.Net.Interfaces;
|
||||
using CryptoExchange.Net.Converters;
|
||||
using CryptoExchange.Net.Interfaces;
|
||||
using CryptoExchange.Net.Objects;
|
||||
using CryptoExchange.Net.Objects.Sockets;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@ -24,11 +25,11 @@ namespace CryptoExchange.Net.Sockets
|
||||
/// <inheritdoc />
|
||||
public override object? GetSubRequest() => null;
|
||||
/// <inheritdoc />
|
||||
public override (bool, CallResult?) MessageMatchesSubRequest(StreamMessage message) => throw new NotImplementedException();
|
||||
public override (bool, CallResult?) MessageMatchesSubRequest(ParsedMessage message) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? GetUnsubRequest() => null;
|
||||
/// <inheritdoc />
|
||||
public override (bool, CallResult?) MessageMatchesUnsubRequest(StreamMessage message) => throw new NotImplementedException();
|
||||
public override (bool, CallResult?) MessageMatchesUnsubRequest(ParsedMessage message) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user