init 1.0.0
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
using LiteDB;
|
||||
using LehrerApp.Sync.Models;
|
||||
|
||||
namespace LehrerApp.Sync;
|
||||
|
||||
/// <summary>
|
||||
/// Lokale Event-Queue in LiteDB. Puffert Events bis sie
|
||||
/// erfolgreich zum Server gepusht wurden.
|
||||
/// </summary>
|
||||
public class EventQueue : IDisposable
|
||||
{
|
||||
private readonly LiteDatabase _db;
|
||||
private readonly ILiteCollection<SyncEvent> _queue;
|
||||
private readonly ILiteCollection<SyncMeta> _meta;
|
||||
private readonly ILiteCollection<ConflictEntry> _conflicts;
|
||||
private long _currentSeq;
|
||||
|
||||
public EventQueue(string path)
|
||||
{
|
||||
_db = new LiteDatabase(path);
|
||||
_queue = _db.GetCollection<SyncEvent>("queue");
|
||||
_meta = _db.GetCollection<SyncMeta>("meta");
|
||||
_conflicts = _db.GetCollection<ConflictEntry>("conflicts");
|
||||
_queue.EnsureIndex(x => x.SequenceNr);
|
||||
_currentSeq = _meta.FindById("seq")?.Value ?? 0;
|
||||
}
|
||||
|
||||
public SyncEvent Enqueue(string deviceId, DeviceType deviceType,
|
||||
string entityType, string entityId, string operation, string payload)
|
||||
{
|
||||
var evt = new SyncEvent
|
||||
{
|
||||
DeviceId = deviceId,
|
||||
DeviceType = deviceType,
|
||||
Timestamp = DateTime.UtcNow,
|
||||
SequenceNr = ++_currentSeq,
|
||||
EntityType = entityType,
|
||||
EntityId = entityId,
|
||||
Operation = operation,
|
||||
Payload = payload,
|
||||
};
|
||||
_queue.Insert(evt);
|
||||
_meta.Upsert(new SyncMeta { Id = "seq", Value = _currentSeq });
|
||||
return evt;
|
||||
}
|
||||
|
||||
public List<SyncEvent> GetPending(int max = 200) =>
|
||||
_queue.Find(Query.All(nameof(SyncEvent.SequenceNr))).Take(max).ToList();
|
||||
public int PendingCount() => _queue.Count();
|
||||
public void Acknowledge(IEnumerable<Guid> ids) { foreach (var id in ids) _queue.Delete(id); }
|
||||
public long GetLastServerSeq() => _meta.FindById("serverSeq")?.Value ?? 0;
|
||||
public void SetLastServerSeq(long nr) => _meta.Upsert(new SyncMeta { Id = "serverSeq", Value = nr });
|
||||
public DateTime? GetLastSyncAt() => _meta.FindById("lastSync")?.Timestamp;
|
||||
public void SetLastSyncAt(DateTime dt) =>
|
||||
_meta.Upsert(new SyncMeta { Id = "lastSync", Value = 0, Timestamp = dt });
|
||||
public void AddConflict(ConflictEntry c) => _conflicts.Insert(c);
|
||||
public List<ConflictEntry> GetUnreviewed() => _conflicts.Find(c => !c.Reviewed).ToList();
|
||||
public int ConflictCount() => _conflicts.Count(c => !c.Reviewed);
|
||||
public void Dispose() => _db.Dispose();
|
||||
}
|
||||
|
||||
public class ConflictEntry
|
||||
{
|
||||
public Guid Id { get; init; } = Guid.NewGuid();
|
||||
public DateTime DetectedAt { get; init; } = DateTime.UtcNow;
|
||||
public SyncEvent LocalEvent { get; init; } = null!;
|
||||
public SyncEvent RemoteEvent { get; init; } = null!;
|
||||
public string Resolution { get; init; } = "";
|
||||
public bool Reviewed { get; set; }
|
||||
}
|
||||
|
||||
internal class SyncMeta
|
||||
{
|
||||
public string Id { get; set; } = "";
|
||||
public long Value { get; set; }
|
||||
public DateTime? Timestamp { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user