Upgrade Sitzplan - Jetzt mit Bewertungsfeature

This commit is contained in:
2026-08-19 16:46:08 +02:00
parent f514d1d58c
commit 0faa3f54de
14 changed files with 370 additions and 14 deletions
+37 -2
View File
@@ -19,6 +19,7 @@ public class SyncEngine : IDisposable
private readonly SyncConfig _config;
private readonly AppLogger? _logger;
private readonly Timer _timer;
private readonly SemaphoreSlim _syncGate = new(1, 1);
public SyncStatus Status { get; private set; } = new();
public event Action<SyncStatus>? StatusChanged;
@@ -49,8 +50,42 @@ public class SyncEngine : IDisposable
public async Task<SyncResult> SyncNowAsync(bool isAutomatic = false)
{
if (Status.State == SyncState.Syncing)
if (!await _syncGate.WaitAsync(0))
return new() { Skipped = true, Reason = "Sync bereits aktiv" };
try
{
return await RunSyncAsync(isAutomatic);
}
finally
{
_syncGate.Release();
}
}
/// <summary>
/// Wartet kurz auf noch laufende lokale Speicheroperationen und führt anschließend garantiert
/// einen Sync aus. Anders als <see cref="SyncNowAsync"/> wird bei einem bereits laufenden Sync
/// nicht abgebrochen, sondern gewartet; so bleiben Änderungen, die während dieses Laufs in die
/// Outbox gelangen, beim Beenden nicht zurück.
/// </summary>
public async Task<SyncResult> SyncBeforeShutdownAsync(TimeSpan delay)
{
if (delay > TimeSpan.Zero)
await Task.Delay(delay);
await _syncGate.WaitAsync();
try
{
return await RunSyncAsync(isAutomatic: true);
}
finally
{
_syncGate.Release();
}
}
private async Task<SyncResult> RunSyncAsync(bool isAutomatic)
{
SetState(SyncState.Syncing);
_logger?.Info($"Sync: Start ({(isAutomatic ? "automatisch" : "manuell")}), Gerät={_config.DeviceId}, " +
$"{_queue.PendingCount()} lokal ausstehend");
@@ -256,7 +291,7 @@ public class SyncEngine : IDisposable
StatusChanged?.Invoke(Status);
}
private void UpdateStatus() => SetState(Status.State);
public void Dispose() { _timer.Dispose(); _queue.Dispose(); }
public void Dispose() { _timer.Dispose(); _syncGate.Dispose(); _queue.Dispose(); }
}
public class SyncConfig