feat: Erfolgs-Protokollierung für die gesamte Sync-Kette

SyncEventPublisher/SyncEngine/EventApplier protokollierten bisher
ausschließlich Fehlschläge - ein sauberes Log bewies nur "nichts ist
abgestürzt", nicht ob eine Änderung tatsächlich hoch-/heruntergeladen
wurde. Jetzt wird auch der Erfolgspfad geloggt: Einreihen in die Outbox
(mit SequenceNr), Push/Pull mit Anzahl und Entitätstypen sowie der vom
Server bestätigten ServerSequenceNr, und jedes tatsächlich angewendete
Ereignis. Damit lässt sich anhand der Log-Dateien beider Geräte
nachvollziehen, an welcher Stelle der Kette eine Änderung verloren geht.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 22:20:33 +02:00
co-authored by Claude Sonnet 5
parent dea7da8cca
commit 270c4d40cd
5 changed files with 44 additions and 6 deletions
+8 -2
View File
@@ -1,4 +1,5 @@
using LehrerApp.Core.Models;
using LehrerApp.Core.Services;
using LehrerApp.Data;
using LehrerApp.Sync.Crypto;
using LehrerApp.Sync.Models;
@@ -10,12 +11,17 @@ namespace LehrerApp.Sync;
/// AppBootstrapper an <see cref="LiteDbContext.OnChange"/> gehängt, wenn Sync konfiguriert ist —
/// dort entsteht aus den ~27 Repository-Aufrufen genau ein verschlüsseltes Ereignis pro Aufruf.
/// </summary>
public class SyncEventPublisher(EventQueue queue, string deviceId, byte[] syncKey)
public class SyncEventPublisher(EventQueue queue, string deviceId, byte[] syncKey, AppLogger? logger = null)
{
public void Publish(string entityType, string entityId, string operation, object? payload)
{
var encrypted = payload is null ? "" : SyncCrypto.EncryptObject(payload, syncKey);
queue.Enqueue(deviceId, DeviceType.Desktop, entityType, entityId, operation, encrypted);
var evt = queue.Enqueue(deviceId, DeviceType.Desktop, entityType, entityId, operation, encrypted);
// Erfolgs-Protokollierung (nicht nur Fehler, siehe SyncEngine/EventApplier) — sonst lässt
// sich ohne zwei parallele Testgeräte nie nachvollziehen, ob eine lokale Änderung
// überhaupt in die Outbox gelangt ist, bevor Push/Pull überhaupt ins Spiel kommen.
logger?.Info($"Sync: Ereignis eingereiht (SequenceNr={evt.SequenceNr}) - {entityType} {operation} " +
$"EntityId={entityId}");
// Anhänge reisen nicht im JSON-Ereignis mit (würde den Kanal für Fotos/Scans aufblähen),
// sondern als eigener Binärtransfer über AttachmentSyncer — hier nur zur Warteliste hinzufügen.