Imap client pool improvements and implementation of MaxConcurrentClients.

This commit is contained in:
Burak Kaan Köse
2024-06-21 04:27:44 +02:00
parent 1c96c0ccbf
commit 150bf124a9
2 changed files with 45 additions and 12 deletions

View File

@@ -9,6 +9,7 @@ using MailKit;
using MailKit.Net.Imap;
using MailKit.Net.Proxy;
using MailKit.Security;
using MoreLinq;
using Serilog;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Enums;
@@ -39,10 +40,10 @@ namespace Wino.Core.Integration
Vendor = "Wino"
};
private const int MaxPoolSize = 5;
private readonly int MinimumPoolSize = 5;
private readonly ConcurrentBag<ImapClient> _clients = [];
private readonly SemaphoreSlim _semaphore = new(MaxPoolSize);
private readonly ConcurrentStack<ImapClient> _clients = [];
private readonly SemaphoreSlim _semaphore;
private readonly CustomServerInformation _customServerInformation;
private readonly Stream _protocolLogStream;
private readonly ILogger _logger = Log.ForContext<ImapClientPool>();
@@ -51,6 +52,9 @@ namespace Wino.Core.Integration
{
_customServerInformation = customServerInformation;
_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)
@@ -126,7 +130,7 @@ namespace Wino.Core.Integration
{
await _semaphore.WaitAsync();
if (_clients.TryTake(out ImapClient item))
if (_clients.TryPop(out ImapClient item))
{
await EnsureConnectivityAsync(item, false);
@@ -140,16 +144,37 @@ namespace Wino.Core.Integration
return client;
}
public void Release(ImapClient item)
public void Release(ImapClient item, bool destroyClient = false)
{
if (item != null)
{
_clients.Add(item);
if (destroyClient)
{
lock (item.SyncRoot)
{
item.Disconnect(true);
}
item.Dispose();
}
else
{
_clients.Push(item);
}
_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;
@@ -232,11 +257,20 @@ namespace Wino.Core.Integration
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();
}
});
_clients.Clear();
if (_protocolLogStream != null)
{

View File

@@ -45,8 +45,7 @@ namespace Wino.Core.Services
// This call will make sure that everything is authenticated + connected successfully.
var client = await clientPool.GetClientAsync();
await client.DisconnectAsync(true);
client.Dispose();
clientPool.Release(client);
}
}
}