Skip to content
This repository was archived by the owner on Jul 28, 2025. It is now read-only.

Commit 7472d74

Browse files
feat: fileParser validation handling, FileParsingExcpetion class created, Filetransform try catch added, tests and test data files added,,
1 parent 9191037 commit 7472d74

File tree

11 files changed

+474
-22
lines changed

11 files changed

+474
-22
lines changed

src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/FileParser.cs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using CsvHelper;
22
using CsvHelper.Configuration;
33
using ServiceLayer.Mesh.FileTypes.NbssAppointmentEvents.Models;
4+
using ServiceLayer.Mesh.FileTypes.NbssAppointmentEvents.Validation;
45
using System.Globalization;
56
using System.Text;
67

@@ -31,6 +32,7 @@ public ParsedFile Parse(Stream stream)
3132

3233
var rowNumber = 0;
3334
var fields = new List<string>();
35+
var fieldsFound = false;
3436

3537
while (csv.Read())
3638
{
@@ -44,9 +46,15 @@ public ParsedFile Parse(Stream stream)
4446

4547
case FieldsIdentifier:
4648
fields = ParseFields(csv);
49+
fieldsFound = true;
4750
break;
4851

4952
case DataIdentifier:
53+
if (!fieldsFound)
54+
{
55+
throw new FileParsingException(
56+
ErrorCodes.MissingFieldHeadings, "Field headings are missing");
57+
}
5058
rowNumber++;
5159
result.DataRecords.Add(ParseDataRecord(csv, fields, rowNumber));
5260
break;
@@ -56,7 +64,10 @@ public ParsedFile Parse(Stream stream)
5664
break;
5765

5866
default:
59-
throw new InvalidOperationException($"Unknown record identifier: {recordIdentifier}");
67+
recordIdentifier = recordIdentifier ?? "No Record Identifier found";
68+
throw new FileParsingException(
69+
ErrorCodes.UnknownRecordTypeIdentifier,
70+
$"Unknown Record Identifier {recordIdentifier}");
6071
}
6172
}
6273

@@ -96,11 +107,6 @@ private static CsvReader CreateCsvReader(StreamReader reader)
96107

97108
private static FileDataRecord ParseDataRecord(CsvReader csv, List<string> columnHeadings, int rowNumber)
98109
{
99-
if (columnHeadings.Count == 0)
100-
{
101-
throw new InvalidOperationException("Field headers (NBSSAPPT_FLDS) must appear before data records.");
102-
}
103-
104110
const int dataFieldStartIndex = 1;
105111

106112
var record = new FileDataRecord { RowNumber = rowNumber };
@@ -140,4 +146,3 @@ public FileHeaderRecordMap()
140146
}
141147
}
142148
}
143-
Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Microsoft.Extensions.Logging;
12
using ServiceLayer.Data.Models;
23
using ServiceLayer.Mesh.FileTypes.NbssAppointmentEvents.Validation;
34

@@ -6,22 +7,65 @@ namespace ServiceLayer.Mesh.FileTypes.NbssAppointmentEvents;
67
public class FileTransformer(
78
IFileParser fileParser,
89
IValidationRunner validationRunner,
9-
IStagingPersister stagingPersister)
10+
IStagingPersister stagingPersister,
11+
ILogger<FileTransformer> logger)
1012
: FileTransformerBase
1113
{
1214
protected override MeshFileType HandlesFileType => MeshFileType.NbssAppointmentEvents;
1315

1416
public override async Task<IList<ValidationError>> TransformFileAsync(Stream stream, MeshFile metaData)
1517
{
16-
// TODO - wrap this parsing in a try-catch and return a List<ValidationError> in case of any unforeseen parsing issues (file is totally unlike anything we expect)
17-
var parsed = fileParser.Parse(stream);
18+
try
19+
{
20+
var parsed = fileParser.Parse(stream);
21+
var validationErrors = validationRunner.Validate(parsed);
22+
23+
if (!validationErrors.Any())
24+
{
25+
await stagingPersister.WriteStagedData(parsed, metaData);
26+
}
1827

19-
var validationErrors = validationRunner.Validate(parsed);
20-
if (!validationErrors.Any())
28+
return validationErrors;
29+
}
30+
catch (FileParsingException ex)
2131
{
22-
await stagingPersister.WriteStagedData(parsed, metaData);
32+
return HandleFileParsingException(ex);
2333
}
34+
catch (Exception ex)
35+
{
36+
return HandleUnexpectedException(ex, metaData);
37+
}
38+
}
39+
40+
private List<ValidationError> HandleFileParsingException(FileParsingException ex)
41+
{
42+
logger.LogError("File parsing failed with validation error. Code: {ErrorCode}, Message: {ErrorMessage}",
43+
ex.Code, ex.ErrorMessage);
44+
45+
return
46+
[
47+
new ValidationError
48+
{
49+
Code = ex.Code,
50+
Error = ex.ErrorMessage,
51+
Scope = ValidationErrorScope.File
52+
}
53+
];
54+
}
55+
56+
private IList<ValidationError> HandleUnexpectedException(Exception ex, MeshFile metaData)
57+
{
58+
logger.LogError(ex, "System error occurred while parsing NBSS appointment file. File: {FileName}",
59+
metaData?.FileId ?? "Unknown");
2460

25-
return validationErrors;
61+
return
62+
[
63+
new ValidationError
64+
{
65+
Code = ErrorCodes.UnableToParseFile,
66+
Error = "Unable to parse file",
67+
Scope = ValidationErrorScope.File
68+
}
69+
];
2670
}
2771
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace ServiceLayer.Mesh.FileTypes.NbssAppointmentEvents;
2+
3+
public class FileParsingException : Exception
4+
{
5+
public string Code { get; }
6+
public string ErrorMessage { get; }
7+
8+
public FileParsingException(string code, string errorMessage)
9+
: base(errorMessage)
10+
{
11+
Code = code;
12+
ErrorMessage = errorMessage;
13+
}
14+
15+
public FileParsingException(string code, string errorMessage, Exception innerException)
16+
: base(errorMessage, innerException)
17+
{
18+
Code = code;
19+
ErrorMessage = errorMessage;
20+
}
21+
}

src/ServiceLayer.Mesh/Functions/FileExtractFunction.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ private async Task ProcessFileExtraction(MeshFile file)
109109

110110
private async Task HandleExtractionError(MeshFile file, FileExtractQueueMessage message, Exception ex)
111111
{
112-
logger.LogError(ex, "An exception occurred during file extraction for fileId: {fileId}", message.FileId);
112+
logger.LogError(ex, "An exception occurred during file extraction for fileId: {FileId}", message.FileId);
113113
file.Status = MeshFileStatus.FailedExtract;
114114
file.LastUpdatedUtc = DateTime.UtcNow;
115115
await serviceLayerDbContext.SaveChangesAsync();

src/ServiceLayer.Shared/Data/Models/MeshFileType.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ namespace ServiceLayer.Data.Models;
22

33
public enum MeshFileType
44
{
5-
NbssAppointmentEvents
5+
NbssAppointmentEvents,
6+
Unknown
67
}

0 commit comments

Comments
 (0)