1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-08 16:36:15 +00:00
CryptoExchange.Net/CryptoExchange.Net/Sockets/SocketListenerManager.cs
2024-02-03 15:35:26 +01:00

133 lines
4.1 KiB
C#

using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Objects.Sockets;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace CryptoExchange.Net.Sockets
{
internal class SocketListenerManager
{
private ILogger _logger;
private object _lock = new object();
private Dictionary<string, Type> _typeMap;
private Dictionary<string, List<IMessageProcessor>> _listeners;
public SocketListenerManager(ILogger logger)
{
_typeMap = new Dictionary<string, Type>();
_logger = logger;
}
public Dictionary<string, Type> GetMapping()
{
lock (this)
return _typeMap;
}
public void Add(IMessageProcessor processor)
{
lock (_lock)
{
foreach (var identifier in processor.Identifiers)
{
if (!_listeners.TryGetValue(identifier, out var list))
{
list = new List<IMessageProcessor>();
_listeners.Add(identifier, list);
}
list.Add(processor);
}
UpdateMap();
}
}
public async Task<bool> InvokeListenersAsync(string id, BaseParsedMessage data)
{
List<IMessageProcessor> listeners;
lock (_lock)
{
if (!_listeners.TryGetValue(id, out var idListeners))
return false;
listeners = idListeners.ToList();
}
foreach (var listener in listeners)
{
//_logger.Log(LogLevel.Trace, $"Socket {SocketId} Message mapped to processor {messageProcessor.Id} with identifier {result.Identifier}");
if (listener is BaseQuery query)
{
Remove(listener);
if (query.PendingRequest != null)
_pendingRequests.Remove(query.PendingRequest);
if (query.PendingRequest?.Completed == true)
{
// Answer to a timed out request
//_logger.Log(LogLevel.Warning, $"Socket {SocketId} Received after request timeout. Consider increasing the RequestTimeout");
}
}
// Matched based on identifier
var userSw = Stopwatch.StartNew();
var dataEvent = new DataEvent<BaseParsedMessage>(data, null, data.OriginalData, DateTime.UtcNow, null);
await listener.HandleMessageAsync(dataEvent).ConfigureAwait(false);
userSw.Stop();
}
return true;
}
public List<Subscription> GetSubscriptions()
{
lock (_lock)
return _listeners.Values.SelectMany(v => v.OfType<Subscription>()).ToList();
}
public List<BaseQuery> GetQueries()
{
lock (_lock)
return _listeners.Values.SelectMany(v => v.OfType<BaseQuery>()).ToList();
}
public bool Contains(IMessageProcessor processor)
{
lock (_lock)
return _listeners.Any(l => l.Value.Contains(processor));
}
public bool Remove(IMessageProcessor processor)
{
lock (_lock)
{
var removed = false;
foreach (var identifier in processor.Identifiers)
{
if (_listeners[identifier].Remove(processor))
removed = true;
if (!_listeners[identifier].Any())
_listeners.Remove(identifier);
}
UpdateMap();
return removed;
}
}
private void UpdateMap()
{
_typeMap = _listeners.ToDictionary(x => x.Key, x => x.Value.First().ExpectedMessageType);
}
}
}