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.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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user