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.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)
{ {

View File

@@ -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();
} }
} }
} }