private List <DeviceEventContainer> OrganizeEventsByDevice(string entityType, string entityId, IEnumerable <ModelEvent> newEvents) { List <DeviceEventContainer> containerList = new List <DeviceEventContainer>(); var deviceGroups = newEvents.GroupBy(e => e.DeviceID); foreach (var device in deviceGroups) { DeviceEventContainer deviceContainer = new DeviceEventContainer(); deviceContainer.EntityType = entityType; deviceContainer.EntityID = entityId; deviceContainer.DeviceID = device.Key; deviceContainer.ConflictResolutionEvents = device.Where(e => e is ConflictResolutionEvent).Select(e => (ConflictResolutionEvent)e).ToList(); // ignoredEvents contains the IDs of all previously ignored events as well HashSet <Guid> ignoredEvents = new HashSet <Guid>(deviceContainer.ConflictResolutionEvents.SelectMany(c => c.EventsToIgnore)); var eventsWithoutResolution = device.Where(e => !(e is ConflictResolutionEvent)); deviceContainer.DeviceEvents = eventsWithoutResolution.Where(e => !ignoredEvents.Contains(e.EventID)).OrderBy(e => e.EventVector).ToList(); deviceContainer.PreviouslyIgnoredEvents = eventsWithoutResolution.Where(e => ignoredEvents.Contains(e.EventID)).OrderBy(e => e.EventVector).ToList(); deviceContainer.MaxVectorClock = deviceContainer.DeviceEvents.OrderBy(e => e.EventVector).LastOrDefault()?.EventVector; deviceContainer.MaxVectorClockIncludingResolutions = device.OrderBy(e => e.EventVector).Last().EventVector; containerList.Add(deviceContainer); } return(containerList); }
private List <ConflictResolutionEvent> ResolveConflict(string entityType, string entityId, List <DeviceEventContainer> deviceEvents, VectorClock internalVector) { //First get a list of exisiting conflict resolutions List <ConflictResolutionEvent> resolutionEvents = new List <ConflictResolutionEvent>(); resolutionEvents.AddRange(deviceEvents.SelectMany(e => e.ConflictResolutionEvents)); List <Guid> eventsToIgnore = new List <Guid>(); DeviceEventContainer deviceWithlastAction = null; //Null means the current device has the last action VectorClock mostRecentVector = internalVector; foreach (var device in deviceEvents) { if (device.MaxVectorClock == null && device.DeviceEvents.Count == 0) { continue; //All events were ignored and no new events to consider } if (mostRecentVector.CompareTo(device.MaxVectorClock) == -1) { deviceWithlastAction = device; mostRecentVector = device.MaxVectorClock; } else { eventsToIgnore.AddRange(device.DeviceEvents.Select(e => e.EventID)); } } if (deviceWithlastAction != null) { //Ignore the current device events var vectors = EventStore.GetEntityEventVectors(entityType, entityId); foreach (var vector in vectors) { if (vector.Vector.CompareVectors(deviceWithlastAction.MaxVectorClock) == VectorClock.ComparisonResult.Simultaneous) { eventsToIgnore.Add(vector.EventID); } } } if (eventsToIgnore.Count > 0) { resolutionEvents.Add(new ConflictResolutionEvent(entityType, entityId, eventsToIgnore)); } return(resolutionEvents); }