Imap client pool improvements and implementation of MaxConcurrentClients.
This commit is contained in:
@@ -9,6 +9,7 @@ using MailKit;
|
|||||||
using MailKit.Net.Imap;
|
using MailKit.Net.Imap;
|
||||||
using MailKit.Net.Proxy;
|
using MailKit.Net.Proxy;
|
||||||
using MailKit.Security;
|
using MailKit.Security;
|
||||||
|
using MoreLinq;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
@@ -39,10 +40,10 @@ namespace Wino.Core.Integration
|
|||||||
Vendor = "Wino"
|
Vendor = "Wino"
|
||||||
};
|
};
|
||||||
|
|
||||||
private const int MaxPoolSize = 5;
|
private readonly int MinimumPoolSize = 5;
|
||||||
|
|
||||||
private readonly ConcurrentBag<ImapClient> _clients = [];
|
private readonly ConcurrentStack<ImapClient> _clients = [];
|
||||||
private readonly SemaphoreSlim _semaphore = new(MaxPoolSize);
|
private readonly SemaphoreSlim _semaphore;
|
||||||
private readonly CustomServerInformation _customServerInformation;
|
private readonly CustomServerInformation _customServerInformation;
|
||||||
private readonly Stream _protocolLogStream;
|
private readonly Stream _protocolLogStream;
|
||||||
private readonly ILogger _logger = Log.ForContext<ImapClientPool>();
|
private readonly ILogger _logger = Log.ForContext<ImapClientPool>();
|
||||||
@@ -51,6 +52,9 @@ namespace Wino.Core.Integration
|
|||||||
{
|
{
|
||||||
_customServerInformation = customServerInformation;
|
_customServerInformation = customServerInformation;
|
||||||
_protocolLogStream = protocolLogStream;
|
_protocolLogStream = protocolLogStream;
|
||||||
|
|
||||||
|
// Set the maximum pool size to 5 or the custom value if it's greater.
|
||||||
|
_semaphore = new(Math.Max(MinimumPoolSize, customServerInformation.MaxConcurrentClients));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task EnsureConnectivityAsync(ImapClient client, bool isCreatedNew)
|
private async Task EnsureConnectivityAsync(ImapClient client, bool isCreatedNew)
|
||||||
@@ -126,7 +130,7 @@ namespace Wino.Core.Integration
|
|||||||
{
|
{
|
||||||
await _semaphore.WaitAsync();
|
await _semaphore.WaitAsync();
|
||||||
|
|
||||||
if (_clients.TryTake(out ImapClient item))
|
if (_clients.TryPop(out ImapClient item))
|
||||||
{
|
{
|
||||||
await EnsureConnectivityAsync(item, false);
|
await EnsureConnectivityAsync(item, false);
|
||||||
|
|
||||||
@@ -140,16 +144,37 @@ namespace Wino.Core.Integration
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Release(ImapClient item)
|
public void Release(ImapClient item, bool destroyClient = false)
|
||||||
{
|
{
|
||||||
if (item != null)
|
if (item != null)
|
||||||
{
|
{
|
||||||
_clients.Add(item);
|
if (destroyClient)
|
||||||
|
{
|
||||||
|
lock (item.SyncRoot)
|
||||||
|
{
|
||||||
|
item.Disconnect(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
item.Dispose();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_clients.Push(item);
|
||||||
|
}
|
||||||
|
|
||||||
_semaphore.Release();
|
_semaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImapClient CreateNewClient()
|
public void DestroyClient(ImapClient client)
|
||||||
|
{
|
||||||
|
if (client == null) return;
|
||||||
|
|
||||||
|
client.Disconnect(true);
|
||||||
|
client.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImapClient CreateNewClient()
|
||||||
{
|
{
|
||||||
ImapClient client = null;
|
ImapClient client = null;
|
||||||
|
|
||||||
@@ -232,11 +257,20 @@ namespace Wino.Core.Integration
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
foreach (var client in _clients)
|
_clients.ForEach(client =>
|
||||||
|
{
|
||||||
|
lock (client.SyncRoot)
|
||||||
|
{
|
||||||
|
client.Disconnect(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_clients.ForEach(client =>
|
||||||
{
|
{
|
||||||
client.Disconnect(true);
|
|
||||||
client.Dispose();
|
client.Dispose();
|
||||||
}
|
});
|
||||||
|
|
||||||
|
_clients.Clear();
|
||||||
|
|
||||||
if (_protocolLogStream != null)
|
if (_protocolLogStream != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -45,8 +45,7 @@ namespace Wino.Core.Services
|
|||||||
// This call will make sure that everything is authenticated + connected successfully.
|
// This call will make sure that everything is authenticated + connected successfully.
|
||||||
var client = await clientPool.GetClientAsync();
|
var client = await clientPool.GetClientAsync();
|
||||||
|
|
||||||
await client.DisconnectAsync(true);
|
clientPool.Release(client);
|
||||||
client.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user