This commit is contained in:
2026-03-29 23:47:31 +02:00
commit 216d5d2280
75 changed files with 5702 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
using LehrerApp.Sync.Models;
namespace LehrerApp.Sync;
/// <summary>
/// Entscheidet bei kollidierenden Events welcher gewinnt.
/// Desktop hat Vorrang vor Companion. Bei Gleichstand gewinnt der spätere Timestamp.
/// </summary>
public class ConflictResolver
{
private readonly EventQueue _queue;
public ConflictResolver(EventQueue queue)
{
_queue = queue;
}
/// <summary>
/// Prüft ob ein Remote-Event mit einem lokalen Event kollidiert.
/// Gibt null zurück wenn kein Konflikt besteht.
/// </summary>
public ConflictEntry? TryResolve(SyncEvent remoteEvent, string localDeviceId)
{
// Lokalen Event für dieselbe Entity suchen
var localEvent = _queue.GetPending()
.FirstOrDefault(e =>
e.EntityType == remoteEvent.EntityType &&
e.EntityId == remoteEvent.EntityId &&
e.DeviceId != remoteEvent.DeviceId);
if (localEvent is null)
return null; // kein Konflikt Remote-Event einfach anwenden
// Konflikt aufgelöst Gewinner bestimmen
var winner = DetermineWinner(localEvent, remoteEvent);
var resolution = winner == localEvent ? "LocalWon" : "RemoteWon";
// Wenn Remote gewinnt: lokalen Event aus Queue entfernen
if (winner == remoteEvent)
_queue.Acknowledge([localEvent.EventId]);
return new ConflictEntry
{
LocalEvent = localEvent,
RemoteEvent = remoteEvent,
Resolution = resolution,
};
}
private static SyncEvent DetermineWinner(SyncEvent local, SyncEvent remote)
{
// Regel 1: Desktop schlägt Companion
if (local.DeviceType == DeviceType.Desktop &&
remote.DeviceType == DeviceType.Companion)
return local;
if (remote.DeviceType == DeviceType.Desktop &&
local.DeviceType == DeviceType.Companion)
return remote;
// Regel 2: Späterer Timestamp gewinnt
return local.Timestamp >= remote.Timestamp ? local : remote;
}
}