Skip to content

Commit

Permalink
use a transaction when merging words to ensure changes are either all…
Browse files Browse the repository at this point in the history
… made or not.
  • Loading branch information
hahn-kev committed Sep 27, 2024
1 parent 8afdcd8 commit b73f10a
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 5 deletions.
4 changes: 3 additions & 1 deletion Backend.Tests/Controllers/MergeControllerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class MergeControllerTests : IDisposable
private IMergeBlacklistRepository _mergeBlacklistRepo = null!;
private IMergeGraylistRepository _mergeGraylistRepo = null!;
private IWordRepository _wordRepo = null!;
private IMongoDbContext _mongoDbContext = null!;
private IMergeService _mergeService = null!;
private IPermissionService _permissionService = null!;
private IWordService _wordService = null!;
Expand Down Expand Up @@ -42,7 +43,8 @@ public void Setup()
_mergeGraylistRepo = new MergeGraylistRepositoryMock();
_wordRepo = new WordRepositoryMock();
_wordService = new WordService(_wordRepo);
_mergeService = new MergeService(_mergeBlacklistRepo, _mergeGraylistRepo, _wordRepo, _wordService);
_mongoDbContext = new MongoDbContextMock();
_mergeService = new MergeService(_mergeBlacklistRepo, _mergeGraylistRepo, _wordRepo, _wordService, _mongoDbContext);
_permissionService = new PermissionServiceMock();
_mergeController = new MergeController(_mergeService, _permissionService);
}
Expand Down
32 changes: 32 additions & 0 deletions Backend.Tests/Mocks/MongoDbContextMock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Threading.Tasks;
using BackendFramework.Interfaces;
using MongoDB.Driver;

namespace Backend.Tests.Mocks;

public class MongoDbContextMock: IMongoDbContext
{
public IMongoDatabase Db => throw new NotSupportedException();
public Task<IMongoTransaction> BeginTransaction()
{
return Task.FromResult<IMongoTransaction>(new MongoTransactionMock());
}

private sealed class MongoTransactionMock : IMongoTransaction
{
public Task CommitTransactionAsync()
{
return Task.CompletedTask;
}

public Task AbortTransactionAsync()
{
return Task.CompletedTask;
}

public void Dispose()
{
}
}
}
4 changes: 3 additions & 1 deletion Backend.Tests/Services/MergeServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class MergeServiceTests
private IMergeGraylistRepository _mergeGraylistRepo = null!;
private IWordRepository _wordRepo = null!;
private IWordService _wordService = null!;
private IMongoDbContext _mongoDbContext = null!;
private IMergeService _mergeService = null!;

private const string ProjId = "MergeServiceTestProjId";
Expand All @@ -26,7 +27,8 @@ public void Setup()
_mergeGraylistRepo = new MergeGraylistRepositoryMock();
_wordRepo = new WordRepositoryMock();
_wordService = new WordService(_wordRepo);
_mergeService = new MergeService(_mergeBlacklistRepo, _mergeGraylistRepo, _wordRepo, _wordService);
_mongoDbContext = new MongoDbContextMock();
_mergeService = new MergeService(_mergeBlacklistRepo, _mergeGraylistRepo, _wordRepo, _wordService, _mongoDbContext);
}

[Test]
Expand Down
15 changes: 12 additions & 3 deletions Backend/Services/MergeService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ public class MergeService : IMergeService
private readonly IMergeGraylistRepository _mergeGraylistRepo;
private readonly IWordRepository _wordRepo;
private readonly IWordService _wordService;
private readonly IMongoDbContext _mongoDbContext;

public MergeService(IMergeBlacklistRepository mergeBlacklistRepo, IMergeGraylistRepository mergeGraylistRepo,
IWordRepository wordRepo, IWordService wordService)
IWordRepository wordRepo, IWordService wordService,
IMongoDbContext mongoDbContext)
{
_mergeBlacklistRepo = mergeBlacklistRepo;
_mergeGraylistRepo = mergeGraylistRepo;
_wordRepo = wordRepo;
_wordService = wordService;
_mongoDbContext = mongoDbContext;
}

/// <summary> Prepares a merge parent to be added to the database. </summary>
Expand Down Expand Up @@ -75,8 +78,11 @@ public async Task<List<Word>> Merge(string projectId, string userId, List<MergeW
{
var keptWords = mergeWordsList.Where(m => !m.DeleteOnly);
var newWords = keptWords.Select(m => MergePrepParent(projectId, m).Result).ToList();
using var transaction = await _mongoDbContext.BeginTransaction();
await Task.WhenAll(mergeWordsList.Select(m => MergeDeleteChildren(projectId, m)));
return await _wordService.Create(userId, newWords);
var words = await _wordService.Create(userId, newWords);
await transaction.CommitTransactionAsync();
return words;
}

/// <summary> Undo merge </summary>
Expand All @@ -92,15 +98,18 @@ public async Task<bool> UndoMerge(string projectId, string userId, MergeUndoIds
}
}

using var transaction = await _mongoDbContext.BeginTransaction();
// If children are not restorable, return without any undo.
if (!await _wordService.RestoreFrontierWords(projectId, ids.ChildIds))
{
// Nothing happens, transaction does not need to commit.
return false;
};
}
foreach (var parentId in ids.ParentIds)
{
await _wordService.DeleteFrontierWord(projectId, userId, parentId);
}
await transaction.CommitTransactionAsync();
return true;
}

Expand Down

0 comments on commit b73f10a

Please sign in to comment.