feat: begin working on database maintainer
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
namespace SanctionsSearch.Worker.Interfaces;
|
||||
|
||||
interface IDatabaseMaintainer
|
||||
{
|
||||
Task BuildSdnTableAsync();
|
||||
Task BuildAddressTableAsync();
|
||||
Task BuiltAliasTableAsync();
|
||||
Task BuildCommentTableAsync();
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
namespace SanctionsSearch.Worker.Models;
|
||||
|
||||
class DatabaseMaintainer(
|
||||
IUnitOfWork unitOfWork,
|
||||
IOfacFileService ofacFileService,
|
||||
ILogger<DatabaseMaintainer> logger
|
||||
) : IDatabaseMaintainer
|
||||
{
|
||||
private readonly IUnitOfWork _unitOfWork = unitOfWork;
|
||||
private readonly IOfacFileService _ofacFileService = ofacFileService;
|
||||
private readonly ILogger<DatabaseMaintainer> _logger = logger;
|
||||
|
||||
public async Task BuildSdnTableAsync()
|
||||
{
|
||||
var result = await _ofacFileService.GetSdnFileAsync();
|
||||
|
||||
if (result.IsFailed)
|
||||
{
|
||||
_logger.LogError("Failed to get SDN file from OFAC.");
|
||||
return;
|
||||
}
|
||||
|
||||
using var stream = result.Value;
|
||||
using var reader = new StreamReader(stream);
|
||||
var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false };
|
||||
using var csv = new CsvReader(reader, config);
|
||||
csv.Context.RegisterClassMap<SdnMap>();
|
||||
var records = csv.GetRecords<Sdn>();
|
||||
|
||||
foreach (var record in records)
|
||||
{
|
||||
await _unitOfWork.Sdns.Upsert(record);
|
||||
}
|
||||
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public Task BuildAddressTableAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task BuildCommentTableAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task BuiltAliasTableAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using CsvHelper.TypeConversion;
|
||||
|
||||
namespace SanctionsSearch.Worker.Models;
|
||||
|
||||
class NullCharacterConverter : DefaultTypeConverter
|
||||
{
|
||||
private const string NullCharacter = "-0-";
|
||||
|
||||
public override object ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
|
||||
{
|
||||
return text is null || text.Trim() is NullCharacter
|
||||
? string.Empty
|
||||
: text;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace SanctionsSearch.Worker.Models;
|
||||
|
||||
class SdnMap : ClassMap<Sdn>
|
||||
{
|
||||
public SdnMap()
|
||||
{
|
||||
Map(m => m.Id).Index(0);
|
||||
Map(m => m.Name).Index(1).TypeConverter<NullCharacterConverter>();
|
||||
Map(m => m.Type).Index(2).TypeConverter<NullCharacterConverter>();
|
||||
Map(m => m.Program).Index(3).TypeConverter<NullCharacterConverter>();
|
||||
Map(m => m.Title).Index(4).TypeConverter<NullCharacterConverter>();
|
||||
Map(m => m.CallSign).Index(5).TypeConverter<NullCharacterConverter>();
|
||||
Map(m => m.VesselType).Index(6).TypeConverter<NullCharacterConverter>();
|
||||
Map(m => m.Tonnage).Index(7).TypeConverter<NullCharacterConverter>();
|
||||
Map(m => m.GrossRegisteredTonnage).Index(8).TypeConverter<NullCharacterConverter>();
|
||||
Map(m => m.VesselFlag).Index(9).TypeConverter<NullCharacterConverter>();
|
||||
Map(m => m.VesselOwner).Index(10).TypeConverter<NullCharacterConverter>();
|
||||
Map(m => m.Remarks).Index(11).TypeConverter<NullCharacterConverter>();
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,8 @@ class Program
|
||||
builder.Logging.AddSerilog();
|
||||
|
||||
builder.Services.ConfigureOptions<OfacFileServiceOptionsSetup>();
|
||||
builder.Services.AddScoped(rs => rs.GetRequiredService<IOptionsSnapshot<OfacFileServiceOptions>>().Value);
|
||||
|
||||
builder.Services.ConfigureOptions<DbOptionsSetup>();
|
||||
builder.Services.AddScoped(rs => rs.GetRequiredService<IOptionsSnapshot<DbOptions>>().Value);
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ namespace SanctionsSearch.Worker.Services;
|
||||
class OfacFileService(
|
||||
HttpClient client,
|
||||
ILogger<OfacFileService> logger,
|
||||
IOptionsSnapshot<OfacFileServiceOptions> options
|
||||
OfacFileServiceOptions options
|
||||
) : IOfacFileService
|
||||
{
|
||||
private readonly HttpClient _client = client ?? throw new ArgumentNullException(nameof(client));
|
||||
private readonly ILogger<OfacFileService> _logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
private readonly OfacFileServiceOptions _options = options?.Value ?? throw new ArgumentNullException(nameof(options));
|
||||
private readonly OfacFileServiceOptions _options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
private async Task<Result<Stream>> GetFileAsync(Uri fileUri)
|
||||
{
|
||||
try
|
||||
@@ -19,7 +19,7 @@ class OfacFileService(
|
||||
|
||||
if (response.IsSuccessStatusCode is false)
|
||||
{
|
||||
_logger.LogError("Failed to download file from {FileUri}", fileUri);
|
||||
_logger.LogError("Failed to download file from {FileUri} with Status Code: {StatusCode}", fileUri, response.StatusCode);
|
||||
return Result.Fail($"Failed to download file from {fileUri}");
|
||||
}
|
||||
|
||||
|
||||
@@ -17,3 +17,7 @@ global using SanctionsSearch.Worker.Setup;
|
||||
global using Serilog;
|
||||
global using Serilog.Exceptions;
|
||||
global using Serilog.Formatting.Compact;
|
||||
|
||||
global using System.Globalization;
|
||||
global using CsvHelper;
|
||||
global using CsvHelper.Configuration;
|
||||
Reference in New Issue
Block a user