Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ public async Task<Result<FileProfileModel>> GetFileProfile(Guid fileProfileId,
return Result.Success();
}

public async Task<Result<Models.FileImportLog>> GetFileImportLogForFile(Guid fileId,
Guid estateId,
CancellationToken cancellationToken) {
return Result.Success();
}

public async Task<Result<FileDetails>> GetFile(Guid fileId,
Guid estateId,
CancellationToken cancellationToken) {
Expand Down
16 changes: 16 additions & 0 deletions FileProcessor.BusinessLogic.Tests/FileProcessingManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,22 @@ public async Task FileProcessingManager_GetFileImportLog_WithMerchantId_ImportLo
this.VerifyImportLog(TestData.FileImportLogs.First(),importLog, TestData.MerchantId);
}

[Fact]
public async Task FileProcessingManager_GetFileImportLogForFile_ReturnsEntryWithoutFileReadModelRow()
{
this.Context.FileImportLogs.Add(TestData.FileImportLog1);
this.Context.FileImportLogFiles.Add(TestData.FileImportLog1Files.First());
await this.Context.SaveChangesAsync();

Result<FileImportLog> importLog = await this.Manager.GetFileImportLogForFile(TestData.FileId1, TestData.EstateId, CancellationToken.None);

importLog.IsSuccess.ShouldBeTrue();
importLog.Data.FileImportLogId.ShouldBe(TestData.FileImportLogId1);
importLog.Data.Files.ShouldHaveSingleItem();
importLog.Data.Files.Single().FileId.ShouldBe(TestData.FileId1);
importLog.Data.Files.Single().UploadedDateTime.ShouldBe(TestData.FileUploadedDateTime);
}

[Fact]
public async Task FileProcessingManager_GetFile_FileReturned()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using SimpleResults;
using FileProcessor.Testing;
using FileProfileModel = global::FileProcessor.Models.FileProfile;
using FileImportLogModel = global::FileProcessor.Models.FileImportLog;
using Xunit;

namespace FileProcessor.BusinessLogic.Tests;
Expand Down Expand Up @@ -66,4 +67,74 @@ public async Task RecoverInProgressFilesAsync_ReplaysFilesFoundInInProgressDirec
command.EstateId == TestData.EstateId),
Arg<CancellationToken>.Any()).Called(Count.Once());
}

[Fact]
public async Task RecoverInProgressFilesAsync_WhenFileAggregateIsMissing_ReplaysUsingImportLogDetails()
{
Shared.Logger.Logger.Initialise(Microsoft.Extensions.Logging.Abstractions.NullLogger.Instance);

IFileProcessorManagerImposter fileProcessorManager = new();
IMediatorImposter mediator = new();
MockFileSystem fileSystem = new();

FileProfileModel fileProfile = TestData.FileProfile;
string inProgressDirectory = $"{fileProfile.ListeningDirectory}/inprogress";
string inProgressFilePath = $"{inProgressDirectory}/{TestData.EstateId:N}-{TestData.FileId:N}";

fileSystem.AddDirectory(inProgressDirectory);
fileSystem.AddFile(inProgressFilePath, new MockFileData("D,1,1,1"));

fileProcessorManager
.GetAllFileProfiles(Arg<CancellationToken>.Any())
.ReturnsAsync(Result.Success(new List<FileProfileModel> { fileProfile }));

fileProcessorManager
.GetFile(TestData.FileId, TestData.EstateId, Arg<CancellationToken>.Any())
.ReturnsAsync(Result.NotFound("File aggregate not found"));

fileProcessorManager
.GetFileImportLogForFile(TestData.FileId, TestData.EstateId, Arg<CancellationToken>.Any())
.ReturnsAsync(Result.Success(new FileImportLogModel
{
EstateId = TestData.EstateId,
FileImportLogId = TestData.FileImportLogId,
FileImportLogDateTime = TestData.FileUploadedDateTime,
Files = new List<ImportLogFile>
{
new()
{
EstateId = TestData.EstateId,
FileId = TestData.FileId,
FileProfileId = TestData.FileProfileId,
MerchantId = TestData.MerchantId,
UserId = TestData.UserId,
UploadedDateTime = TestData.FileUploadedDateTime
}
}
}));

mediator
.Send(Arg<IRequest<Result>>.Any(), Arg<CancellationToken>.Any())
.ReturnsAsync(Result.Success());

FileProfileDirectoryRecoveryService service = new(
fileProcessorManager.Instance(),
mediator.Instance(),
fileSystem);

Result result = await service.RecoverInProgressFilesAsync(CancellationToken.None);

result.IsSuccess.ShouldBeTrue();
mediator.Send(
Arg<IRequest<Result>>.Is(request => request is FileCommands.ProcessUploadedFileCommand command &&
command.FileId == TestData.FileId &&
command.FileImportLogId == TestData.FileImportLogId &&
command.FileProfileId == TestData.FileProfileId &&
command.EstateId == TestData.EstateId &&
command.MerchantId == TestData.MerchantId &&
command.UserId == TestData.UserId &&
command.FileUploadedDateTime == TestData.FileUploadedDateTime &&
Path.GetFileName(command.FilePath) == Path.GetFileName(inProgressFilePath)),
Arg<CancellationToken>.Any()).Called(Count.Once());
}
}
5 changes: 3 additions & 2 deletions FileProcessor.BusinessLogic/Common/ModelFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ public List<FileImportLog> ConvertFrom(Guid estateId,
FilePath = importLogFile.Item1.FilePath,
FileProfileId = importLogFile.Item1.FileProfileId,
OriginalFileName = importLogFile.Item1.OriginalFileName,
UserId = importLogFile.Item1.UserId
UserId = importLogFile.Item1.UserId,
UploadedDateTime = importLogFile.Item1.FileUploadedDateTime
});
}

Expand Down Expand Up @@ -97,4 +98,4 @@ public FileImportLog ConvertFrom(Guid estateId,

#endregion
}
}
}
39 changes: 39 additions & 0 deletions FileProcessor.BusinessLogic/Managers/FileProcessorManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,45 @@ join merchant in context.Merchants on file.MerchantId equals merchant.MerchantId
return Result.Success(x);
}

public async Task<Result<FileImportLog>> GetFileImportLogForFile(Guid fileId,
Guid estateId,
CancellationToken cancellationToken)
{
EstateManagementContext context = await this.GetContext(estateId);

var importLogFile = await (from fileImportLogFile in context.FileImportLogFiles
join importLog in context.FileImportLogs on fileImportLogFile.FileImportLogId equals importLog.FileImportLogId
where fileImportLogFile.FileId == fileId
select new { fileImportLogFile, importLog })
.SingleOrDefaultAsync(cancellationToken);

if (importLogFile == null)
{
return Result.NotFound($"No import log file found for File Id [{fileId}]");
}

return Result.Success(new FileImportLog
{
EstateId = estateId,
FileImportLogId = importLogFile.importLog.FileImportLogId,
FileImportLogDateTime = importLogFile.importLog.ImportLogDateTime,
Files = new List<ImportLogFile>
{
new()
{
EstateId = estateId,
FileId = importLogFile.fileImportLogFile.FileId,
FilePath = importLogFile.fileImportLogFile.FilePath,
FileProfileId = importLogFile.fileImportLogFile.FileProfileId,
MerchantId = importLogFile.fileImportLogFile.MerchantId,
OriginalFileName = importLogFile.fileImportLogFile.OriginalFileName,
UploadedDateTime = importLogFile.fileImportLogFile.FileUploadedDateTime,
UserId = importLogFile.fileImportLogFile.UserId
}
}
});
}

public async Task<Result<FileDetails>> GetFile(Guid fileId,
Guid estateId,
CancellationToken cancellationToken)
Expand Down
2 changes: 2 additions & 0 deletions FileProcessor.BusinessLogic/Managers/IFileProcessorManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public interface IFileProcessorManager

Task<Result<Models.FileImportLog>> GetFileImportLog(Guid fileImportLogId, Guid estateId, Guid? merchantId, CancellationToken cancellationToken);

Task<Result<Models.FileImportLog>> GetFileImportLogForFile(Guid fileId, Guid estateId, CancellationToken cancellationToken);

Task<Result<FileDetails>> GetFile(Guid fileId, Guid estateId, CancellationToken cancellationToken);

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Shared.Results;
using SimpleResults;
using FileProfileModel = global::FileProcessor.Models.FileProfile;
using FileImportLogModel = global::FileProcessor.Models.FileImportLog;

namespace FileProcessor.BusinessLogic.Services;

Expand Down Expand Up @@ -68,28 +69,47 @@ private async Task RecoverFileAsync(FileProfileModel fileProfile, string filePat
}

Result<FileDetails> fileResult = await this.FileProcessorManager.GetFile(fileId, estateId, cancellationToken);
if (fileResult.IsFailed)
{
Shared.Logger.Logger.LogWarning($"Skipping leftover in-progress file [{filePath}] because file [{fileId}] could not be loaded: {fileResult.Message}");
return;
}
FileCommands.ProcessUploadedFileCommand command;

FileDetails fileDetails = fileResult.Data;
if (fileDetails == null)
if (fileResult.IsSuccess && fileResult.Data != null)
{
Shared.Logger.Logger.LogWarning($"Skipping leftover in-progress file [{filePath}] because file [{fileId}] returned no details");
return;
FileDetails fileDetails = fileResult.Data;
command = new(
fileDetails.EstateId,
fileDetails.MerchantId,
fileDetails.FileImportLogId,
fileId,
fileDetails.UserId,
filePath,
fileDetails.FileProfileId,
fileDetails.FileReceivedDateTime);
}
else
{
Result<FileImportLogModel> importLogResult = await this.FileProcessorManager.GetFileImportLogForFile(
fileId,
estateId,
cancellationToken);

FileCommands.ProcessUploadedFileCommand command = new(
fileDetails.EstateId,
fileDetails.MerchantId,
fileDetails.FileImportLogId,
fileDetails.FileId,
fileDetails.UserId,
filePath,
fileDetails.FileProfileId,
fileDetails.FileReceivedDateTime);
FileImportLogModel importLog = importLogResult.Data;
ImportLogFile importLogFile = importLog?.Files?.Find(file => file.FileId == fileId);

if (importLogResult.IsFailed || importLog == null || importLogFile == null)
{
Shared.Logger.Logger.LogWarning($"Skipping leftover in-progress file [{filePath}] because file [{fileId}] could not be loaded from the file aggregate or import log read model");
return;
}

command = new(
estateId,
importLogFile.MerchantId,
importLog.FileImportLogId,
fileId,
importLogFile.UserId,
filePath,
importLogFile.FileProfileId,
importLogFile.UploadedDateTime == default ? importLog.FileImportLogDateTime : importLogFile.UploadedDateTime);
}

Result result = await this.Mediator.Send(command, cancellationToken);
if (result.IsFailed)
Expand Down
Loading