gps matcher async

put cryptography lib to fixed version
fix race condition bug in queue handler
add lock to db writing and backup to file db on each write
This commit is contained in:
Alex Bezdieniezhnykh
2025-05-29 00:35:35 +03:00
parent 34ea821fb3
commit d842466594
12 changed files with 245 additions and 191 deletions
+52 -11
View File
@@ -1,10 +1,9 @@
using System.Data.SQLite;
using System.Diagnostics;
using System.IO;
using Azaion.Common.DTO;
using Azaion.Common.DTO.Config;
using Azaion.Common.Extensions;
using LinqToDB;
using LinqToDB.Data;
using LinqToDB.DataProvider.SQLite;
using LinqToDB.Mapping;
using Microsoft.Extensions.Logging;
@@ -16,13 +15,14 @@ namespace Azaion.Common.Database;
public interface IDbFactory
{
Task<T> Run<T>(Func<AnnotationsDb, Task<T>> func);
Task Run(Func<AnnotationsDb, Task> func);
void SaveToDisk();
Task RunWrite(Func<AnnotationsDb, Task> func);
Task<T> RunWrite<T>(Func<AnnotationsDb, Task<T>> func);
Task DeleteAnnotations(List<string> annotationNames, CancellationToken cancellationToken = default);
}
public class DbFactory : IDbFactory
{
private readonly ILogger<DbFactory> _logger;
private readonly AnnotationConfig _annConfig;
private string MemoryConnStr => "Data Source=:memory:";
@@ -33,8 +33,12 @@ public class DbFactory : IDbFactory
private readonly SQLiteConnection _fileConnection;
private readonly DataOptions _fileDataOptions;
private static readonly SemaphoreSlim WriteSemaphore = new(1, 1);
private static readonly Guid SaveTaskId = Guid.NewGuid();
public DbFactory(IOptions<AnnotationConfig> annConfig, ILogger<DbFactory> logger)
{
_logger = logger;
_annConfig = annConfig.Value;
_memoryConnection = new SQLiteConnection(MemoryConnStr);
@@ -79,26 +83,63 @@ public class DbFactory : IDbFactory
return await func(db);
}
public async Task Run(Func<AnnotationsDb, Task> func)
public async Task RunWrite(Func<AnnotationsDb, Task> func)
{
await using var db = new AnnotationsDb(_memoryDataOptions);
await func(db);
await WriteSemaphore.WaitAsync();
try
{
await using var db = new AnnotationsDb(_memoryDataOptions);
await func(db);
ThrottleExt.Throttle(async () =>
{
_memoryConnection.BackupDatabase(_fileConnection, "main", "main", -1, null, -1);
await Task.CompletedTask;
}, SaveTaskId, TimeSpan.FromSeconds(5), true);
}
catch (Exception e)
{
_logger.LogError(e, e.Message);
throw;
}
finally
{
WriteSemaphore.Release();
}
}
public void SaveToDisk()
public async Task<T> RunWrite<T>(Func<AnnotationsDb, Task<T>> func)
{
_memoryConnection.BackupDatabase(_fileConnection, "main", "main", -1, null, -1);
await WriteSemaphore.WaitAsync();
try
{
await using var db = new AnnotationsDb(_memoryDataOptions);
var result = await func(db);
ThrottleExt.Throttle(async () =>
{
_memoryConnection.BackupDatabase(_fileConnection, "main", "main", -1, null, -1);
await Task.CompletedTask;
}, SaveTaskId, TimeSpan.FromSeconds(5), true);
return result;
}
catch (Exception e)
{
_logger.LogError(e, e.Message);
throw;
}
finally
{
WriteSemaphore.Release();
}
}
public async Task DeleteAnnotations(List<string> annotationNames, CancellationToken cancellationToken = default)
{
await Run(async db =>
await RunWrite(async db =>
{
var detDeleted = await db.Detections.DeleteAsync(x => annotationNames.Contains(x.AnnotationName), token: cancellationToken);
var annDeleted = await db.Annotations.DeleteAsync(x => annotationNames.Contains(x.Name), token: cancellationToken);
Console.WriteLine($"Deleted {detDeleted} detections, {annDeleted} annotations");
});
SaveToDisk();
}
}