public async Task<IEnumerable<AppointmentId>> DeleteAnnouncedEventsIfDuplicates(Predicate<AppointmentId> canBeDeleted)
{
var appointmentIdsWithIdenticalHashCode = GetAppointmentIdsWithIdenticalHashCode();
if (appointmentIdsWithIdenticalHashCode.Length == 0)
return new AppointmentId[0];
var deletedEntityIds = new List<AppointmentId>();
foreach (var ids in appointmentIdsWithIdenticalHashCode)
{
var appointments = await GetAppointmentsWithId(ids);
try
{
if (appointments.Length > 1)
{
var appointmentsToDelete = (
from appointmentWithId in appointments
let data = GetDuplicationRelevantData(appointmentWithId.Item2.Inner)
group new {Appointment = appointmentWithId, CanBeDeleted = canBeDeleted(appointmentWithId.Item1)} by data // group by duplication relevant data (hashes can collide)
into groupedByData
where groupedByData.Count() > 1 // take only the groups containing duplicates found by data comparison
let appointmentToKeep = groupedByData.FirstOrDefault(a => !a.CanBeDeleted) ?? groupedByData.First() // if all can be deleted, one has to be left untouched
from appointmentPair in groupedByData.Where(a => a.CanBeDeleted && a != appointmentToKeep).Select(a => new {Keep = appointmentToKeep, Delete = a})
select appointmentPair
).ToArray();
foreach (var appointmentPair in appointmentsToDelete)
{
s_logger.Info($"Deleting duplicate of '{appointmentPair.Keep.Appointment.Item2.Inner.EntryID}'");
var appointmentToDelete = appointmentPair.Delete.Appointment;
appointmentToDelete.Item2.Inner.Delete();
deletedEntityIds.Add(appointmentToDelete.Item1);
_hashesById.Remove(appointmentToDelete.Item1);
}
}
}
finally
{
_outlookRepository.Cleanup(appointments.Select(a => a.Item2));
}
}
return deletedEntityIds;
}