From a963a6baad6c1b331ca897c1dceb75f07caf2987 Mon Sep 17 00:00:00 2001 From: Igor Matsak Date: Wed, 26 Apr 2023 23:39:21 +0300 Subject: [PATCH] Add LiteDbConnectionPool, increase version to v1.0.23 --- Beacon.Sdk/Beacon.Sdk.csproj | 2 +- .../BeaconClientServiceExtensions.cs | 2 +- .../Infrastructure/ILiteDbConnectionPool.cs | 11 +++ .../Infrastructure/LiteDbConnectionPool.cs | 91 +++++++++++++++++++ .../Repositories/BaseLiteDbRepository.cs | 8 +- .../LiteDbAppMetadataRepository.cs | 14 ++- .../LiteDbMatrixSyncRepository.cs | 16 ++-- .../LiteDbP2PPeerRoomRepository.cs | 12 ++- .../Repositories/LiteDbPeerRepository.cs | 13 ++- .../LiteDbPermissionInfoRepository.cs | 16 ++-- .../Repositories/LiteDbSeedRepository.cs | 16 ++-- 11 files changed, 163 insertions(+), 38 deletions(-) create mode 100644 Beacon.Sdk/Core/Infrastructure/ILiteDbConnectionPool.cs create mode 100644 Beacon.Sdk/Core/Infrastructure/LiteDbConnectionPool.cs diff --git a/Beacon.Sdk/Beacon.Sdk.csproj b/Beacon.Sdk/Beacon.Sdk.csproj index 8de8f7d..f0ea709 100644 --- a/Beacon.Sdk/Beacon.Sdk.csproj +++ b/Beacon.Sdk/Beacon.Sdk.csproj @@ -14,7 +14,7 @@ Mikhail Tatarenko Beacon.Sdk Beacon .NET SDK for Tezos wallet / dApps developers. - 1.0.22 + 1.0.23 Copyright © Baking Bad 2019-2022 enable netstandard2.1 diff --git a/Beacon.Sdk/BeaconClients/BeaconClientServiceExtensions.cs b/Beacon.Sdk/BeaconClients/BeaconClientServiceExtensions.cs index b0c5c6d..dd8a558 100644 --- a/Beacon.Sdk/BeaconClients/BeaconClientServiceExtensions.cs +++ b/Beacon.Sdk/BeaconClients/BeaconClientServiceExtensions.cs @@ -68,6 +68,7 @@ private static IServiceCollection AddBeaconClient(this IServiceCollection servic }); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -79,7 +80,6 @@ private static IServiceCollection AddBeaconClient(this IServiceCollection servic #endregion - #region Domain services.AddSingleton(); diff --git a/Beacon.Sdk/Core/Infrastructure/ILiteDbConnectionPool.cs b/Beacon.Sdk/Core/Infrastructure/ILiteDbConnectionPool.cs new file mode 100644 index 0000000..8a6cb87 --- /dev/null +++ b/Beacon.Sdk/Core/Infrastructure/ILiteDbConnectionPool.cs @@ -0,0 +1,11 @@ +using LiteDB; + +namespace Beacon.Sdk.Core.Infrastructure +{ + public interface ILiteDbConnectionPool + { + void CloseAllConnections(); + void CloseConnection(string fileName); + ILiteDatabase OpenConnection(ConnectionString connectionString, BsonMapper? mapper = null); + } +} \ No newline at end of file diff --git a/Beacon.Sdk/Core/Infrastructure/LiteDbConnectionPool.cs b/Beacon.Sdk/Core/Infrastructure/LiteDbConnectionPool.cs new file mode 100644 index 0000000..87bcbd2 --- /dev/null +++ b/Beacon.Sdk/Core/Infrastructure/LiteDbConnectionPool.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Concurrent; +using System.IO; + +using LiteDB; + +namespace Beacon.Sdk.Core.Infrastructure +{ + public class LiteDbConnectionPool : IDisposable, ILiteDbConnectionPool + { + private readonly ConcurrentDictionary _dbs; + private bool _disposed; + + public LiteDbConnectionPool() + { + _dbs = new ConcurrentDictionary(); + } + + public ILiteDatabase OpenConnection(ConnectionString connectionString, BsonMapper? mapper = null) + { + var fullPath = Path.GetFullPath(connectionString.Filename); + + LiteDatabase? newDb = null; + + try + { + var db = _dbs.GetOrAdd(fullPath, path => + { + newDb = new LiteDatabase(connectionString, mapper); + return newDb; + }); + + if (db != newDb && newDb != null) + { + newDb.Dispose(); + } + + return db; + } + catch (Exception ex) + { + if (!_dbs.TryGetValue(fullPath, out var db)) + throw ex; // connection not found after another attempt to get => throw exception when creating connection + + return db; + } + } + + public void CloseConnection(string fileName) + { + var fullPath = Path.GetFullPath(fileName); + + if (_dbs.TryRemove(fullPath, out var db)) + { + db.Dispose(); + } + } + + public void CloseAllConnections() + { + var keysSnapshot = _dbs.Keys; + + foreach (var fullFilePath in keysSnapshot) + { + if (_dbs.TryRemove(fullFilePath, out var db)) + { + db.Dispose(); + } + } + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + CloseAllConnections(); + } + + _disposed = true; + } + } + + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/Beacon.Sdk/Core/Infrastructure/Repositories/BaseLiteDbRepository.cs b/Beacon.Sdk/Core/Infrastructure/Repositories/BaseLiteDbRepository.cs index beaa6a9..c65eb70 100644 --- a/Beacon.Sdk/Core/Infrastructure/Repositories/BaseLiteDbRepository.cs +++ b/Beacon.Sdk/Core/Infrastructure/Repositories/BaseLiteDbRepository.cs @@ -9,12 +9,12 @@ namespace Beacon.Sdk.Core.Infrastructure.Repositories public abstract class BaseLiteDbRepository { private readonly ILogger> _logger; - private readonly LiteDatabase _db; + private readonly ILiteDatabase _db; - protected BaseLiteDbRepository(ILogger> logger, RepositorySettings settings) + protected BaseLiteDbRepository(ILiteDbConnectionPool connectionPool, ILogger> logger, RepositorySettings settings) { _logger = logger; - _db = new LiteDatabase(settings.ConnectionString); + _db = connectionPool.OpenConnection(new ConnectionString(settings.ConnectionString)); } protected Task InConnectionAction(string collectionName, Action> func) @@ -46,7 +46,7 @@ protected Task InConnection(string collectionName, Func, T } } - protected Task InConnection(string collectionName, Action> func) + protected Task InConnection(string collectionName, Action> func) { try { diff --git a/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbAppMetadataRepository.cs b/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbAppMetadataRepository.cs index 5c5f4b4..b82c28d 100644 --- a/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbAppMetadataRepository.cs +++ b/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbAppMetadataRepository.cs @@ -1,19 +1,23 @@ using System; +using System.Linq; +using System.Threading.Tasks; + using LiteDB; +using Microsoft.Extensions.Logging; namespace Beacon.Sdk.Core.Infrastructure.Repositories { - using System.Linq; - using System.Threading.Tasks; using Beacon; - using Microsoft.Extensions.Logging; public class LiteDbAppMetadataRepository : BaseLiteDbRepository, IAppMetadataRepository { private const string CollectionName = "AppMetadata"; - public LiteDbAppMetadataRepository(ILogger logger, RepositorySettings settings) - : base(logger, settings) + public LiteDbAppMetadataRepository( + ILiteDbConnectionPool connectionPool, + ILogger logger, + RepositorySettings settings) + : base(connectionPool, logger, settings) { } diff --git a/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbMatrixSyncRepository.cs b/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbMatrixSyncRepository.cs index 8fdef92..d9a4a57 100644 --- a/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbMatrixSyncRepository.cs +++ b/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbMatrixSyncRepository.cs @@ -1,21 +1,25 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + using LiteDB; +using Microsoft.Extensions.Logging; namespace Beacon.Sdk.Core.Infrastructure.Repositories { - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; using Domain.Entities; using Domain.Interfaces; - using Microsoft.Extensions.Logging; public class LiteDbMatrixSyncRepository : BaseLiteDbRepository, IMatrixSyncRepository { private const string CollectionName = "MatrixSync"; - public LiteDbMatrixSyncRepository(ILogger logger, RepositorySettings settings) - : base(logger, settings) + public LiteDbMatrixSyncRepository( + ILiteDbConnectionPool connectionPool, + ILogger logger, + RepositorySettings settings) + : base(connectionPool, logger, settings) { } diff --git a/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbP2PPeerRoomRepository.cs b/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbP2PPeerRoomRepository.cs index d4c4028..227d66d 100644 --- a/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbP2PPeerRoomRepository.cs +++ b/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbP2PPeerRoomRepository.cs @@ -1,21 +1,25 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; + using LiteDB; +using Microsoft.Extensions.Logging; namespace Beacon.Sdk.Core.Infrastructure.Repositories { - using System.Threading.Tasks; using Domain.Entities.P2P; using Domain.Interfaces.Data; - using Microsoft.Extensions.Logging; using Utils; public class LiteDbP2PPeerRoomRepository : BaseLiteDbRepository, IP2PPeerRoomRepository { private const string CollectionName = "P2PPeerRoom"; - public LiteDbP2PPeerRoomRepository(ILogger logger, RepositorySettings settings) : - base(logger, settings) + public LiteDbP2PPeerRoomRepository( + ILiteDbConnectionPool connectionPool, + ILogger logger, + RepositorySettings settings) : + base(connectionPool, logger, settings) { } diff --git a/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbPeerRepository.cs b/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbPeerRepository.cs index 6813394..b434e1f 100644 --- a/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbPeerRepository.cs +++ b/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbPeerRepository.cs @@ -1,21 +1,24 @@ using System; using System.Collections.Generic; -using LiteDB; +using System.Threading.Tasks; +using LiteDB; +using Microsoft.Extensions.Logging; namespace Beacon.Sdk.Core.Infrastructure.Repositories { - using System.Threading.Tasks; using Domain.Entities; using Domain.Interfaces.Data; - using Microsoft.Extensions.Logging; public class LiteDbPeerRepository : BaseLiteDbRepository, IPeerRepository { private const string CollectionName = "Peer"; - public LiteDbPeerRepository(ILogger logger, RepositorySettings settings) - : base(logger, settings) + public LiteDbPeerRepository( + ILiteDbConnectionPool connectionPool, + ILogger logger, + RepositorySettings settings) + : base(connectionPool, logger, settings) { } diff --git a/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbPermissionInfoRepository.cs b/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbPermissionInfoRepository.cs index e412e76..35385f5 100644 --- a/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbPermissionInfoRepository.cs +++ b/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbPermissionInfoRepository.cs @@ -1,21 +1,25 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + using LiteDB; +using Microsoft.Extensions.Logging; namespace Beacon.Sdk.Core.Infrastructure.Repositories { - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; using Domain.Entities; using Domain.Interfaces.Data; - using Microsoft.Extensions.Logging; public class LiteDbPermissionInfoRepository : BaseLiteDbRepository, IPermissionInfoRepository { private const string CollectionName = "PermissionInfo"; - public LiteDbPermissionInfoRepository(ILogger logger, - RepositorySettings settings) : base(logger, settings) + public LiteDbPermissionInfoRepository( + ILiteDbConnectionPool connectionPool, + ILogger logger, + RepositorySettings settings) + : base(connectionPool, logger, settings) { } diff --git a/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbSeedRepository.cs b/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbSeedRepository.cs index 299e623..6521edb 100644 --- a/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbSeedRepository.cs +++ b/Beacon.Sdk/Core/Infrastructure/Repositories/LiteDbSeedRepository.cs @@ -1,22 +1,26 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + using LiteDB; +using Microsoft.Extensions.Logging; namespace Beacon.Sdk.Core.Infrastructure.Repositories { - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; using Domain.Entities; using Domain.Interfaces.Data; - using Microsoft.Extensions.Logging; // Todo: Add secure storage public class LiteDbSeedRepository : BaseLiteDbRepository, ISeedRepository { private const string CollectionName = "Seed"; - public LiteDbSeedRepository(ILogger logger, RepositorySettings settings) - : base(logger, settings) + public LiteDbSeedRepository( + ILiteDbConnectionPool connectionPool, + ILogger logger, + RepositorySettings settings) + : base(connectionPool, logger, settings) { }