From 8afdcd8f007af2c9c2df733d7e15e1e368327f1b Mon Sep 17 00:00:00 2001 From: Kevin Hahn Date: Fri, 27 Sep 2024 11:42:45 +0700 Subject: [PATCH] Create MongoDbContext which provides the IMongoDatabase to other contexts. Make it a scoped service so only 1 MongoClient is created per request. Use that to expose transactions which are now shared across all Repos. --- Backend/Contexts/BannerContext.cs | 10 ++--- Backend/Contexts/MergeBlacklistContext.cs | 11 ++---- Backend/Contexts/MergeGraylistContext.cs | 11 ++---- Backend/Contexts/MongoDbContext.cs | 47 +++++++++++++++++++++++ Backend/Contexts/PasswordResetContext.cs | 9 ++--- Backend/Contexts/ProjectContext.cs | 11 ++---- Backend/Contexts/SemanticDomainContext.cs | 13 +++---- Backend/Contexts/SpeakerContext.cs | 12 +++--- Backend/Contexts/UserContext.cs | 11 ++---- Backend/Contexts/UserEditContext.cs | 11 ++---- Backend/Contexts/UserRoleContext.cs | 11 ++---- Backend/Contexts/WordContext.cs | 13 +++---- Backend/Interfaces/IMongoDbContext.cs | 17 ++++++++ Backend/Startup.cs | 3 ++ 14 files changed, 114 insertions(+), 76 deletions(-) create mode 100644 Backend/Contexts/MongoDbContext.cs create mode 100644 Backend/Interfaces/IMongoDbContext.cs diff --git a/Backend/Contexts/BannerContext.cs b/Backend/Contexts/BannerContext.cs index ace2284f9f..15d123d25b 100644 --- a/Backend/Contexts/BannerContext.cs +++ b/Backend/Contexts/BannerContext.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using BackendFramework.Interfaces; using BackendFramework.Models; -using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BackendFramework.Contexts @@ -9,14 +8,13 @@ namespace BackendFramework.Contexts [ExcludeFromCodeCoverage] public class BannerContext : IBannerContext { - private readonly IMongoDatabase _db; + private readonly IMongoDbContext _mongoDbContext; - public BannerContext(IOptions options) + public BannerContext(IMongoDbContext mongoDbContext) { - var client = new MongoClient(options.Value.ConnectionString); - _db = client.GetDatabase(options.Value.CombineDatabase); + _mongoDbContext = mongoDbContext; } - public IMongoCollection Banners => _db.GetCollection("BannerCollection"); + public IMongoCollection Banners => _mongoDbContext.Db.GetCollection("BannerCollection"); } } diff --git a/Backend/Contexts/MergeBlacklistContext.cs b/Backend/Contexts/MergeBlacklistContext.cs index f977bf6d70..52c1c65f1c 100644 --- a/Backend/Contexts/MergeBlacklistContext.cs +++ b/Backend/Contexts/MergeBlacklistContext.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using BackendFramework.Interfaces; using BackendFramework.Models; -using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BackendFramework.Contexts @@ -9,15 +8,13 @@ namespace BackendFramework.Contexts [ExcludeFromCodeCoverage] public class MergeBlacklistContext : IMergeBlacklistContext { - private readonly IMongoDatabase _db; - - public MergeBlacklistContext(IOptions options) + private readonly IMongoDbContext _mongoDbContext; + public MergeBlacklistContext(IMongoDbContext mongoDbContext) { - var client = new MongoClient(options.Value.ConnectionString); - _db = client.GetDatabase(options.Value.CombineDatabase); + _mongoDbContext = mongoDbContext; } - public IMongoCollection MergeBlacklist => _db.GetCollection( + public IMongoCollection MergeBlacklist => _mongoDbContext.Db.GetCollection( "MergeBlacklistCollection"); } } diff --git a/Backend/Contexts/MergeGraylistContext.cs b/Backend/Contexts/MergeGraylistContext.cs index d9ea381829..35b0f8caf9 100644 --- a/Backend/Contexts/MergeGraylistContext.cs +++ b/Backend/Contexts/MergeGraylistContext.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using BackendFramework.Interfaces; using BackendFramework.Models; -using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BackendFramework.Contexts @@ -9,15 +8,13 @@ namespace BackendFramework.Contexts [ExcludeFromCodeCoverage] public class MergeGraylistContext : IMergeGraylistContext { - private readonly IMongoDatabase _db; - - public MergeGraylistContext(IOptions options) + private readonly IMongoDbContext _mongoDbContext; + public MergeGraylistContext(IMongoDbContext mongoDbContext) { - var client = new MongoClient(options.Value.ConnectionString); - _db = client.GetDatabase(options.Value.CombineDatabase); + _mongoDbContext = mongoDbContext; } - public IMongoCollection MergeGraylist => _db.GetCollection( + public IMongoCollection MergeGraylist => _mongoDbContext.Db.GetCollection( "MergeGraylistCollection"); } } diff --git a/Backend/Contexts/MongoDbContext.cs b/Backend/Contexts/MongoDbContext.cs new file mode 100644 index 0000000000..60785b5cbe --- /dev/null +++ b/Backend/Contexts/MongoDbContext.cs @@ -0,0 +1,47 @@ +using System.Threading.Tasks; +using BackendFramework.Interfaces; +using Microsoft.Extensions.Options; +using MongoDB.Driver; + +namespace BackendFramework.Contexts; + +public class MongoDbContext : IMongoDbContext +{ + public IMongoDatabase Db { get; } + + public MongoDbContext(IOptions options) + { + var client = new MongoClient(options.Value.ConnectionString); + Db = client.GetDatabase(options.Value.CombineDatabase); + } + + public async Task BeginTransaction() + { + return new MongoTransactionWrapper(await Db.Client.StartSessionAsync()); + } + + private class MongoTransactionWrapper : IMongoTransaction + { + private readonly IClientSessionHandle _session; + + public MongoTransactionWrapper(IClientSessionHandle session) + { + _session = session; + } + + public Task CommitTransactionAsync() + { + return _session.CommitTransactionAsync(); + } + + public Task AbortTransactionAsync() + { + return _session.AbortTransactionAsync(); + } + + public void Dispose() + { + _session.Dispose(); + } + } +} \ No newline at end of file diff --git a/Backend/Contexts/PasswordResetContext.cs b/Backend/Contexts/PasswordResetContext.cs index dbcc4041c0..84aebc7eed 100644 --- a/Backend/Contexts/PasswordResetContext.cs +++ b/Backend/Contexts/PasswordResetContext.cs @@ -10,17 +10,16 @@ namespace BackendFramework.Contexts [ExcludeFromCodeCoverage] public class PasswordResetContext : IPasswordResetContext { - private readonly IMongoDatabase _db; + private readonly IMongoDbContext _mongoDbContext; public int ExpireTime { get; } - public PasswordResetContext(IOptions options) + public PasswordResetContext(IOptions options, IMongoDbContext mongoDbContext) { - var client = new MongoClient(options.Value.ConnectionString); - _db = client.GetDatabase(options.Value.CombineDatabase); + _mongoDbContext = mongoDbContext; ExpireTime = options.Value.PassResetExpireTime; } - private IMongoCollection PasswordResets => _db.GetCollection( + private IMongoCollection PasswordResets => _mongoDbContext.Db.GetCollection( "PasswordResetCollection"); public Task ClearAll(string email) diff --git a/Backend/Contexts/ProjectContext.cs b/Backend/Contexts/ProjectContext.cs index 696a8a35da..0901b6b0e4 100644 --- a/Backend/Contexts/ProjectContext.cs +++ b/Backend/Contexts/ProjectContext.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using BackendFramework.Interfaces; using BackendFramework.Models; -using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BackendFramework.Contexts @@ -9,14 +8,12 @@ namespace BackendFramework.Contexts [ExcludeFromCodeCoverage] public class ProjectContext : IProjectContext { - private readonly IMongoDatabase _db; - - public ProjectContext(IOptions options) + private readonly IMongoDbContext _mongoDbContext; + public ProjectContext(IMongoDbContext mongoDbContext) { - var client = new MongoClient(options.Value.ConnectionString); - _db = client.GetDatabase(options.Value.CombineDatabase); + _mongoDbContext = mongoDbContext; } - public IMongoCollection Projects => _db.GetCollection("ProjectsCollection"); + public IMongoCollection Projects => _mongoDbContext.Db.GetCollection("ProjectsCollection"); } } diff --git a/Backend/Contexts/SemanticDomainContext.cs b/Backend/Contexts/SemanticDomainContext.cs index 5ad11cac28..66fa39acd0 100644 --- a/Backend/Contexts/SemanticDomainContext.cs +++ b/Backend/Contexts/SemanticDomainContext.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using BackendFramework.Interfaces; using BackendFramework.Models; -using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BackendFramework.Contexts @@ -9,15 +8,13 @@ namespace BackendFramework.Contexts [ExcludeFromCodeCoverage] public class SemanticDomainContext : ISemanticDomainContext { - private readonly IMongoDatabase _db; - - public SemanticDomainContext(IOptions options) + private readonly IMongoDbContext _mongoDbContext; + public SemanticDomainContext(IMongoDbContext mongoDbContext) { - var client = new MongoClient(options.Value.ConnectionString); - _db = client.GetDatabase(options.Value.CombineDatabase); + _mongoDbContext = mongoDbContext; } - public IMongoCollection SemanticDomains => _db.GetCollection("SemanticDomainTree"); - public IMongoCollection FullSemanticDomains => _db.GetCollection("SemanticDomains"); + public IMongoCollection SemanticDomains => _mongoDbContext.Db.GetCollection("SemanticDomainTree"); + public IMongoCollection FullSemanticDomains => _mongoDbContext.Db.GetCollection("SemanticDomains"); } } diff --git a/Backend/Contexts/SpeakerContext.cs b/Backend/Contexts/SpeakerContext.cs index f65c3e08c0..fb413f8f6b 100644 --- a/Backend/Contexts/SpeakerContext.cs +++ b/Backend/Contexts/SpeakerContext.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using BackendFramework.Interfaces; using BackendFramework.Models; -using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BackendFramework.Contexts @@ -9,14 +8,13 @@ namespace BackendFramework.Contexts [ExcludeFromCodeCoverage] public class SpeakerContext : ISpeakerContext { - private readonly IMongoDatabase _db; - - public SpeakerContext(IOptions options) + private readonly IMongoDbContext _mongoDbContext; + + public SpeakerContext(IMongoDbContext mongoDbContext) { - var client = new MongoClient(options.Value.ConnectionString); - _db = client.GetDatabase(options.Value.CombineDatabase); + _mongoDbContext = mongoDbContext; } - public IMongoCollection Speakers => _db.GetCollection("SpeakersCollection"); + public IMongoCollection Speakers => _mongoDbContext.Db.GetCollection("SpeakersCollection"); } } diff --git a/Backend/Contexts/UserContext.cs b/Backend/Contexts/UserContext.cs index 46122c146c..92778f02d7 100644 --- a/Backend/Contexts/UserContext.cs +++ b/Backend/Contexts/UserContext.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using BackendFramework.Interfaces; using BackendFramework.Models; -using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BackendFramework.Contexts @@ -9,14 +8,12 @@ namespace BackendFramework.Contexts [ExcludeFromCodeCoverage] public class UserContext : IUserContext { - private readonly IMongoDatabase _db; - - public UserContext(IOptions options) + private readonly IMongoDbContext _mongoDbContext; + public UserContext(IMongoDbContext mongoDbContext) { - var client = new MongoClient(options.Value.ConnectionString); - _db = client.GetDatabase(options.Value.CombineDatabase); + _mongoDbContext = mongoDbContext; } - public IMongoCollection Users => _db.GetCollection("UsersCollection"); + public IMongoCollection Users => _mongoDbContext.Db.GetCollection("UsersCollection"); } } diff --git a/Backend/Contexts/UserEditContext.cs b/Backend/Contexts/UserEditContext.cs index 7487d78ec0..d0de83a1a6 100644 --- a/Backend/Contexts/UserEditContext.cs +++ b/Backend/Contexts/UserEditContext.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using BackendFramework.Interfaces; using BackendFramework.Models; -using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BackendFramework.Contexts @@ -9,14 +8,12 @@ namespace BackendFramework.Contexts [ExcludeFromCodeCoverage] public class UserEditContext : IUserEditContext { - private readonly IMongoDatabase _db; - - public UserEditContext(IOptions options) + private readonly IMongoDbContext _mongoDbContext; + public UserEditContext(IMongoDbContext mongoDbContext) { - var client = new MongoClient(options.Value.ConnectionString); - _db = client.GetDatabase(options.Value.CombineDatabase); + _mongoDbContext = mongoDbContext; } - public IMongoCollection UserEdits => _db.GetCollection("UserEditsCollection"); + public IMongoCollection UserEdits => _mongoDbContext.Db.GetCollection("UserEditsCollection"); } } diff --git a/Backend/Contexts/UserRoleContext.cs b/Backend/Contexts/UserRoleContext.cs index 086c2ffe57..92b7c6506f 100644 --- a/Backend/Contexts/UserRoleContext.cs +++ b/Backend/Contexts/UserRoleContext.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using BackendFramework.Interfaces; using BackendFramework.Models; -using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BackendFramework.Contexts @@ -9,14 +8,12 @@ namespace BackendFramework.Contexts [ExcludeFromCodeCoverage] public class UserRoleContext : IUserRoleContext { - private readonly IMongoDatabase _db; - - public UserRoleContext(IOptions options) + private readonly IMongoDbContext _mongoDbContext; + public UserRoleContext(IMongoDbContext mongoDbContext) { - var client = new MongoClient(options.Value.ConnectionString); - _db = client.GetDatabase(options.Value.CombineDatabase); + _mongoDbContext = mongoDbContext; } - public IMongoCollection UserRoles => _db.GetCollection("UserRolesCollection"); + public IMongoCollection UserRoles => _mongoDbContext.Db.GetCollection("UserRolesCollection"); } } diff --git a/Backend/Contexts/WordContext.cs b/Backend/Contexts/WordContext.cs index 32876c6af2..d8989de00e 100644 --- a/Backend/Contexts/WordContext.cs +++ b/Backend/Contexts/WordContext.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using BackendFramework.Interfaces; using BackendFramework.Models; -using Microsoft.Extensions.Options; using MongoDB.Driver; namespace BackendFramework.Contexts @@ -9,15 +8,13 @@ namespace BackendFramework.Contexts [ExcludeFromCodeCoverage] public class WordContext : IWordContext { - private readonly IMongoDatabase _db; - - public WordContext(IOptions options) + private readonly IMongoDbContext _mongoDbContext; + public WordContext(IMongoDbContext mongoDbContext) { - var client = new MongoClient(options.Value.ConnectionString); - _db = client.GetDatabase(options.Value.CombineDatabase); + _mongoDbContext = mongoDbContext; } - public IMongoCollection Words => _db.GetCollection("WordsCollection"); - public IMongoCollection Frontier => _db.GetCollection("FrontierCollection"); + public IMongoCollection Words => _mongoDbContext.Db.GetCollection("WordsCollection"); + public IMongoCollection Frontier => _mongoDbContext.Db.GetCollection("FrontierCollection"); } } diff --git a/Backend/Interfaces/IMongoDbContext.cs b/Backend/Interfaces/IMongoDbContext.cs new file mode 100644 index 0000000000..cfd1363286 --- /dev/null +++ b/Backend/Interfaces/IMongoDbContext.cs @@ -0,0 +1,17 @@ +using System; +using System.Threading.Tasks; +using MongoDB.Driver; + +namespace BackendFramework.Interfaces; + +public interface IMongoDbContext +{ + IMongoDatabase Db { get; } + Task BeginTransaction(); +} + +public interface IMongoTransaction : IDisposable +{ + Task CommitTransactionAsync(); + Task AbortTransactionAsync(); +} \ No newline at end of file diff --git a/Backend/Startup.cs b/Backend/Startup.cs index 8bdad6da05..95f56f9260 100644 --- a/Backend/Startup.cs +++ b/Backend/Startup.cs @@ -287,6 +287,9 @@ public void ConfigureServices(IServiceCollection services) services.AddTransient(); services.AddTransient(); services.AddTransient(); + + // mongo context, scoped so it is shared across a single request + services.AddScoped(); } /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.