Files
meeting-assistant/MeetingAssistant/Recording/FileOfflineTranscriptionBacklog.cs
codex aecef30627
PR and Push Build/Test / build-and-test (push) Successful in 9m19s
Archive completed meeting assistant changes
2026-06-26 13:15:47 +02:00

125 lines
4.0 KiB
C#

using System.Text.Json;
using Microsoft.Extensions.Options;
namespace MeetingAssistant.Recording;
public sealed class FileOfflineTranscriptionBacklog : IOfflineTranscriptionBacklog
{
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web)
{
WriteIndented = true
};
private readonly MeetingAssistantOptions options;
private readonly ILogger<FileOfflineTranscriptionBacklog> logger;
public FileOfflineTranscriptionBacklog(
IOptions<MeetingAssistantOptions> options,
ILogger<FileOfflineTranscriptionBacklog> logger)
{
this.options = options.Value;
this.logger = logger;
}
public async Task EnqueueAsync(OfflineTranscriptionBacklogItem item, CancellationToken cancellationToken)
{
var folder = GetBacklogFolder(options);
Directory.CreateDirectory(folder);
var path = GetItemPath(folder, item.Id);
await File.WriteAllTextAsync(path, JsonSerializer.Serialize(item, JsonOptions), cancellationToken);
logger.LogInformation(
"Queued offline transcription backlog item {BacklogItemId} for recording {RecordingPath}",
item.Id,
item.AudioPath);
}
public async Task<IReadOnlyList<OfflineTranscriptionBacklogItem>> ListAsync(CancellationToken cancellationToken)
{
var folder = GetBacklogFolder(options);
if (!Directory.Exists(folder))
{
return [];
}
var items = new List<OfflineTranscriptionBacklogItem>();
foreach (var path in Directory.EnumerateFiles(folder, "*.json", SearchOption.TopDirectoryOnly))
{
cancellationToken.ThrowIfCancellationRequested();
try
{
var content = await File.ReadAllTextAsync(path, cancellationToken);
if (JsonSerializer.Deserialize<OfflineTranscriptionBacklogItem>(content, JsonOptions) is { } item)
{
items.Add(item);
}
}
catch (JsonException exception)
{
logger.LogWarning(exception, "Could not read offline transcription backlog item {BacklogItemPath}", path);
}
catch (IOException exception)
{
logger.LogWarning(exception, "Could not read offline transcription backlog item {BacklogItemPath}", path);
}
}
return items;
}
public Task CompleteAsync(OfflineTranscriptionBacklogItem item, CancellationToken cancellationToken)
{
var folder = GetBacklogFolder(options);
var path = GetItemPath(folder, item.Id);
if (!File.Exists(path))
{
return Task.CompletedTask;
}
File.Delete(path);
if (File.Exists(item.AudioPath))
{
DeleteCompletedAudio(item.AudioPath);
}
return Task.CompletedTask;
}
private static string GetBacklogFolder(MeetingAssistantOptions options)
{
return Path.Combine(VaultPath.Resolve(options.Recording.TemporaryRecordingsFolder), "offline-transcription-backlog");
}
private static string GetItemPath(string folder, string id)
{
return Path.Combine(folder, $"{id}.json");
}
private void DeleteCompletedAudio(string audioPath)
{
try
{
File.Delete(audioPath);
}
catch (FileNotFoundException)
{
}
catch (DirectoryNotFoundException)
{
}
catch (IOException exception)
{
logger.LogWarning(
exception,
"Could not delete completed offline transcription recording file {RecordingPath}",
audioPath);
}
catch (UnauthorizedAccessException exception)
{
logger.LogWarning(
exception,
"Could not delete completed offline transcription recording file {RecordingPath}",
audioPath);
}
}
}