big refactoring. get rid of static properties and coupled architecture. prepare system for integration tests

This commit is contained in:
Oleksandr Bezdieniezhnykh
2025-11-17 13:14:05 +02:00
parent 22529c26ec
commit e7ea5a8ded
38 changed files with 808 additions and 157 deletions
+18 -7
View File
@@ -33,6 +33,8 @@ public class AnnotationService : IAnnotationService
private readonly QueueConfig _queueConfig;
private Consumer _consumer = null!;
private readonly UIConfig _uiConfig;
private readonly IAnnotationPathResolver _pathResolver;
private readonly IFileSystem _fileSystem;
private readonly SemaphoreSlim _imageAccessSemaphore = new(1, 1);
private readonly SemaphoreSlim _messageProcessingSemaphore = new(1, 1);
private static readonly Guid SaveQueueOffsetTaskId = Guid.NewGuid();
@@ -46,7 +48,9 @@ public class AnnotationService : IAnnotationService
IGalleryService galleryService,
IMediator mediator,
IAzaionApi api,
ILogger<AnnotationService> logger)
ILogger<AnnotationService> logger,
IAnnotationPathResolver pathResolver,
IFileSystem fileSystem)
{
_dbFactory = dbFactory;
_producer = producer;
@@ -56,8 +60,13 @@ public class AnnotationService : IAnnotationService
_logger = logger;
_queueConfig = queueConfig.Value;
_uiConfig = uiConfig.Value;
_pathResolver = pathResolver;
_fileSystem = fileSystem;
}
Task.Run(async () => await InitQueueConsumer()).Wait();
public async Task StartQueueConsumerAsync(CancellationToken token = default)
{
await InitQueueConsumer(token);
}
private async Task InitQueueConsumer(CancellationToken token = default)
@@ -221,13 +230,14 @@ public class AnnotationService : IAnnotationService
Image image = null!;
if (stream != null)
{
var imagePath = _pathResolver.GetImagePath(annotation);
image = Image.FromStream(stream);
if (File.Exists(annotation.ImagePath))
ResilienceExt.WithRetry(() => File.Delete(annotation.ImagePath));
image.Save(annotation.ImagePath, ImageFormat.Jpeg);
if (_fileSystem.FileExists(imagePath))
ResilienceExt.WithRetry(() => _fileSystem.DeleteFile(imagePath));
image.Save(imagePath, ImageFormat.Jpeg);
}
await YoloLabel.WriteToFile(detections, annotation.LabelPath, token);
await YoloLabel.WriteToFile(detections, _pathResolver.GetLabelPath(annotation), token);
await _galleryService.CreateThumbnail(annotation, image, token);
if (_uiConfig.GenerateAnnotatedImage)
@@ -235,7 +245,7 @@ public class AnnotationService : IAnnotationService
}
catch (Exception e)
{
_logger.LogError(e, $"Try to save {annotation.ImagePath}, Error: {e.Message}");
_logger.LogError(e, $"Try to save {_pathResolver.GetImagePath(annotation)}, Error: {e.Message}");
throw;
}
finally
@@ -274,6 +284,7 @@ public class AnnotationService : IAnnotationService
public interface IAnnotationService
{
Task StartQueueConsumerAsync(CancellationToken token = default);
Task<Annotation> SaveAnnotation(AnnotationImage a, CancellationToken ct = default);
Task<Annotation> SaveAnnotation(string mediaHash, string originalMediaName, string annotationName, TimeSpan time, List<Detection> detections, Stream? stream = null, CancellationToken token = default);
Task ValidateAnnotations(List<string> annotationNames, bool fromQueue = false, CancellationToken token = default);