/// <summary> /// Checks if any of the activities expired. /// If so, it deletes them. /// </summary> public async Task CheckExpiredActivitiesAsync() { log.Trace("()"); DateTime now = DateTime.UtcNow; List <byte[]> imagesToDelete = new List <byte[]>(); using (UnitOfWork unitOfWork = new UnitOfWork()) { // Disable change tracking for faster multiple deletes. unitOfWork.Context.ChangeTracker.AutoDetectChangesEnabled = false; // Find and delete expired primary activities. DatabaseLock lockObject = UnitOfWork.PrimaryActivityLock; await unitOfWork.AcquireLockAsync(lockObject); try { List <PrimaryActivity> expiredActivities = (await unitOfWork.PrimaryActivityRepository.GetAsync(i => i.ExpirationTime < now, null, true)).ToList(); if (expiredActivities.Count > 0) { log.Debug("There are {0} expired primary activities.", expiredActivities.Count); foreach (PrimaryActivity activity in expiredActivities) { unitOfWork.PrimaryActivityRepository.Delete(activity); log.Debug("Activity ID {0}, owner ID '{1}' expired and will be deleted.", activity.ActivityId, activity.OwnerIdentityId.ToHex()); } await unitOfWork.SaveThrowAsync(); log.Debug("{0} expired primary activities were deleted.", expiredActivities.Count); } else { log.Debug("No expired primary activities found."); } } catch (Exception e) { log.Error("Exception occurred: {0}", e.ToString()); } unitOfWork.ReleaseLock(lockObject); // Find and delete expired neighbor activities. lockObject = UnitOfWork.NeighborActivityLock; await unitOfWork.AcquireLockAsync(lockObject); try { List <NeighborActivity> expiredActivities = (await unitOfWork.NeighborActivityRepository.GetAsync(i => i.ExpirationTime < now, null, true)).ToList(); if (expiredActivities.Count > 0) { log.Debug("There are {0} expired neighbor activities.", expiredActivities.Count); foreach (NeighborActivity activity in expiredActivities) { unitOfWork.NeighborActivityRepository.Delete(activity); log.Debug("Activity ID {0}, owner ID '{1}' expired and will be deleted.", activity.ActivityId, activity.OwnerIdentityId.ToHex()); } await unitOfWork.SaveThrowAsync(); log.Debug("{0} expired neighbor activities were deleted.", expiredActivities.Count); } else { log.Debug("No expired neighbor activities found."); } } catch (Exception e) { log.Error("Exception occurred: {0}", e.ToString()); } unitOfWork.ReleaseLock(lockObject); } log.Trace("(-)"); }
/// <summary> /// Checks if any of the neighbors expired. /// If so, it starts the process of their removal. /// </summary> public async Task CheckExpiredNeighborsAsync() { log.Trace("()"); // If a neighbor server's LastRefreshTime is lower than this limit, it is expired. DateTime limitLastRefreshTime = DateTime.UtcNow.AddSeconds(-Config.Configuration.NeighborExpirationTimeSeconds); using (UnitOfWork unitOfWork = new UnitOfWork()) { bool success = false; DatabaseLock[] lockObjects = new DatabaseLock[] { UnitOfWork.NeighborLock, UnitOfWork.NeighborhoodActionLock }; using (IDbContextTransaction transaction = await unitOfWork.BeginTransactionWithLockAsync(lockObjects)) { try { List <Neighbor> expiredNeighbors = (await unitOfWork.NeighborRepository.GetAsync(n => n.LastRefreshTime < limitLastRefreshTime, null, true)).ToList(); if (expiredNeighbors.Count > 0) { log.Debug("There are {0} expired neighbors.", expiredNeighbors.Count); foreach (Neighbor neighbor in expiredNeighbors) { // This action will cause our proximity server to erase all activities of the neighbor that has been removed. NeighborhoodAction action = new NeighborhoodAction() { ServerId = neighbor.NeighborId, Timestamp = DateTime.UtcNow, Type = NeighborhoodActionType.RemoveNeighbor, TargetActivityId = null, TargetActivityOwnerId = null, AdditionalData = null }; await unitOfWork.NeighborhoodActionRepository.InsertAsync(action); } await unitOfWork.SaveThrowAsync(); transaction.Commit(); } else { log.Debug("No expired neighbors found."); } success = true; } catch (Exception e) { log.Error("Exception occurred: {0}", e.ToString()); } if (!success) { log.Warn("Rolling back transaction."); unitOfWork.SafeTransactionRollback(transaction); } unitOfWork.ReleaseLock(lockObjects); } } log.Trace("(-)"); }
/// <summary> /// Removes neighborhood actions whose target servers do not exist in our database. /// </summary> /// <returns>true if the function succeeds, false otherwise.</returns> private bool DeleteInvalidNeighborhoodActions() { log.Info("()"); bool res = false; using (UnitOfWork unitOfWork = new UnitOfWork()) { DatabaseLock[] lockObjects = new DatabaseLock[] { UnitOfWork.NeighborLock, UnitOfWork.FollowerLock, UnitOfWork.NeighborhoodActionLock }; unitOfWork.AcquireLock(lockObjects); try { List <byte[]> neighborIds = unitOfWork.NeighborRepository.Get().Select(n => n.NeighborId).ToList(); HashSet <byte[]> neighborIdsHashSet = new HashSet <byte[]>(neighborIds, StructuralEqualityComparer <byte[]> .Default); List <byte[]> followerIds = unitOfWork.FollowerRepository.Get().Select(f => f.FollowerId).ToList(); HashSet <byte[]> followerIdsHashSet = new HashSet <byte[]>(followerIds, StructuralEqualityComparer <byte[]> .Default); List <NeighborhoodAction> actions = unitOfWork.NeighborhoodActionRepository.Get().ToList(); bool saveDb = false; foreach (NeighborhoodAction action in actions) { bool actionValid = false; if (action.IsActivityAction()) { // Action's serverId should be our follower. actionValid = followerIdsHashSet.Contains(action.ServerId); } else { // Action's serverId should be our neighbor. actionValid = neighborIdsHashSet.Contains(action.ServerId); } if (!actionValid) { log.Debug("Removing invalid action ID {0}, type {1}, server ID '{2}'.", action.Id, action.Type, action.ServerId.ToHex()); unitOfWork.NeighborhoodActionRepository.Delete(action); saveDb = true; } } if (saveDb) { res = unitOfWork.Save(); } else { log.Debug("No invalid neighborhood actions found."); res = true; } } catch (Exception e) { log.Error("Exception occurred: {0}", e.ToString()); } unitOfWork.ReleaseLock(lockObjects); } log.Info("(-):{0}", res); return(res); }