internal static void Update(BubbleGroup group, bool optimized = true, Action optimizedChainFinished = null) { if (optimized) { UpdateName(@group, () => { UpdateGroupLegibleID(@group, () => { UpdatePartyParticipants(@group, () => { if (optimizedChainFinished != null) { optimizedChainFinished(); } else { BubbleGroupEvents.RaiseRefreshed(@group); BubbleGroupEvents.RaiseBubblesUpdated(@group); BubbleGroupEvents.RaiseInformationUpdated(@group); } }); }); }); } else { UpdateName(@group); UpdateGroupLegibleID(@group); UpdatePartyParticipants(@group); } }
internal static async void UpdateGroupLegibleID(BubbleGroup bubbleGroup, Action finished = null) { var service = bubbleGroup.Service; if (!ServiceManager.IsRunning(service)) { return; } try { await service.GetBubbleGroupLegibleId(bubbleGroup, legibleID => { bubbleGroup.LegibleId = legibleID; if (finished == null) { BubbleGroupEvents.RaiseRefreshed(bubbleGroup); } else { finished(); } }); } catch (Exception ex) { Utils.DebugPrint("Error updating bubble group legible ID: " + service.Information.ServiceName + " - " + bubbleGroup.Address + ": " + ex); if (finished != null) { finished(); } } }
public static void SetNotQueuedToFailures(BubbleGroup group) { var groups = BubbleGroupManager.GetInner(@group).Where(x => !x.PartiallyLoaded && (x.Service.QueuedBubblesParameters != null && x.Service.QueuedBubblesParameters.SendingBubblesToFailOnServiceStart != null && x.Service.QueuedBubblesParameters.SendingBubblesToFailOnServiceStart.Any())); var failed = new List <Tuple <BubbleGroup, VisualBubble> >(); foreach (var innerGroup in groups) { foreach (var bubble in innerGroup) { if (bubble.Direction == Bubble.BubbleDirection.Outgoing && bubble.Status == Bubble.BubbleStatus.Waiting) { if (innerGroup .Service.QueuedBubblesParameters.SendingBubblesToFailOnServiceStart .FirstOrDefault(x => x == bubble.GetType()) != null) { failed.Add(new Tuple <BubbleGroup, VisualBubble>(innerGroup, bubble)); } } } } if (!failed.Any()) { return; } var somethingUpdated = false; var failuresGroupedByBubbleGroup = failed.GroupBy(x => x.Item1); foreach (var failureGroup in failuresGroupedByBubbleGroup) { var groupOfBubbles = failureGroup.First().Item1; var bubbles = failureGroup.Select(x => x.Item2).ToArray(); foreach (var bubble in bubbles) { bubble.Status = Bubble.BubbleStatus.Failed; } BubbleGroupDatabase.UpdateBubble(groupOfBubbles, bubbles, groupOfBubbles.Bubbles.Count + 100); // 100 is really a tolerance here (just in case) foreach (var bubble in bubbles) { BubbleGroupEvents.RaiseBubbleFailed(bubble, groupOfBubbles); } somethingUpdated = true; } if (somethingUpdated) { BubbleGroupEvents.RaiseBubblesUpdated(@group); BubbleGroupEvents.RaiseRefreshed(@group); } }
public static bool UpdateUnknownPartyParticipant(BubbleGroup bubbleGroup, string participantAddress, Action onAdded = null) { var service = bubbleGroup.Service; if (!ServiceManager.IsRunning(service)) { return(false); } if (string.IsNullOrWhiteSpace(participantAddress)) { return(false); } if (bubbleGroup.FailedUnknownParticipants.FirstOrDefault(x => bubbleGroup.Service.BubbleGroupComparer(x, participantAddress)) != null) { return(false); } try { service.GetBubbleGroupUnknownPartyParticipant(bubbleGroup, participantAddress, participant => { if (participant != null) { var contains = bubbleGroup.Participants.FirstOrDefault(x => bubbleGroup.Service.BubbleGroupComparer(x.Address, participantAddress)) != null; if (!contains) { participant.Unknown = true; bubbleGroup.Participants.Add(participant); } } else { bubbleGroup.FailedUnknownParticipants.Add(participantAddress); } if (onAdded != null) { onAdded(); } BubbleGroupEvents.RaiseRefreshed(bubbleGroup); BubbleGroupEvents.RaiseBubblesUpdated(bubbleGroup); }); } catch (Exception ex) { Utils.DebugPrint("Error getting unknown bubble group participant: " + service.Information.ServiceName + ": " + ex.Message); return(false); } return(true); }
public static void UpdateStatus(VisualBubble b, Bubble.BubbleStatus status, BubbleGroup group, bool updateBubbleGroupBubbles = true) { b.Status = status; BubbleGroupDatabase.UpdateBubble(@group, b); if (updateBubbleGroupBubbles) { BubbleGroupEvents.RaiseBubblesUpdated(@group); } BubbleGroupEvents.RaiseRefreshed(@group); }
public static void UpdateStatus(VisualBubble[] bubbles, Bubble.BubbleStatus status, BubbleGroup group, bool updateBubbleGroupBubbles = true) { foreach (var bubble in bubbles) { bubble.Status = status; } BubbleGroupDatabase.UpdateBubble(@group, bubbles); if (updateBubbleGroupBubbles) { BubbleGroupEvents.RaiseBubblesUpdated(@group); } BubbleGroupEvents.RaiseRefreshed(@group); }
internal static async void UpdateName(BubbleGroup bubbleGroup, Action finished = null) { var service = bubbleGroup.Service; if (!ServiceManager.IsRunning(service)) { return; } try { await service.GetBubbleGroupName(bubbleGroup, title => { bubbleGroup.IsTitleSetFromService = true; if (string.IsNullOrWhiteSpace(title)) { Utils.DebugPrint("Update name title is null (rejecting): " + service.Information.ServiceName + " - " + bubbleGroup.Address); } else { bubbleGroup.Title = title; } if (finished == null) { BubbleGroupEvents.RaiseRefreshed(bubbleGroup); BubbleGroupEvents.RaiseInformationUpdated(bubbleGroup); } else { finished(); } }); } catch (Exception ex) { Utils.DebugPrint("Error updating bubble group name: " + service.Information.ServiceName + " - " + bubbleGroup.Address + ": " + ex); if (finished != null) { finished(); } } }
private static void SetUnread(BubbleGroup group, bool unread, bool updateUi = true, bool skipSendReadBubble = false, bool onlySetIfServiceRunning = true) { var unifiedGroup = @group as UnifiedBubbleGroup; if (unifiedGroup != null) { foreach (var innerGroup in unifiedGroup.Groups) { SetUnread(innerGroup, false, skipSendReadBubble); } } Action @do = () => { var updatedSomething = BubbleGroupSettingsManager.GetUnread(@group); BubbleGroupSettingsManager.SetUnread(@group, unread); if (unifiedGroup == null) { if (!skipSendReadBubble) { if (@group.Service.Information.DoesSupport(typeof(ReadBubble)) && ServiceManager.IsRunning(@group.Service)) { BubbleManager.Send(new ReadBubble(Time.GetNowUnixTimestamp(), Bubble.BubbleDirection.Outgoing, @group.Service, @group.Address, null, Time.GetNowUnixTimestamp(), @group.IsParty, updatedSomething)); } } } if (updateUi) { BubbleGroupEvents.RaiseRefreshed(@group); } }; if (onlySetIfServiceRunning && ServiceManager.IsRunning(@group.Service)) { @do(); } else if (!onlySetIfServiceRunning) { @do(); } }
private static void SetUnread(BubbleGroup group, bool unread, bool updateUi = true, bool skipSendReadBubble = false, bool onlySetIfServiceRunning = true) { var unifiedGroup = @group as UnifiedBubbleGroup; if (unifiedGroup != null) { foreach (var innerGroup in unifiedGroup.Groups) { SetUnread(innerGroup, unread, false, skipSendReadBubble, onlySetIfServiceRunning); } } var currentlyUnread = BubbleGroupSettingsManager.GetUnread(@group); if ((onlySetIfServiceRunning && ServiceManager.IsRunning(@group.Service)) || !onlySetIfServiceRunning) { BubbleGroupSettingsManager.SetUnread(@group, unread); if (unifiedGroup == null) { if (!skipSendReadBubble) { if (@group.Service.Information.DoesSupport(typeof(ReadBubble)) && ServiceManager.IsRunning(@group.Service)) { var readBubble = new ReadBubble(Time.GetNowUnixTimestamp(), Bubble.BubbleDirection.Outgoing, @group.Service, @group.Address, null, Time.GetNowUnixTimestamp(), @group.IsParty, currentlyUnread); if (@group.IsExtendedParty) { readBubble.ExtendedParty = true; } BubbleManager.Send(readBubble); } } } if (updateUi) { BubbleGroupEvents.RaiseRefreshed(@group); } } else { BubbleGroupSettingsManager.SetUnreadOffline(@group, unread); } }
public static void Update(Service service, bool optimized = true) { const int Interval = 5; var updateCounter = 0; var groupsDoneCounter = 0; var groups = BubbleGroupManager.FindAll(service); var updateCounterThreshold = groups.Count / Interval; foreach (var group in groups) { Action chainFinished = null; if (groups.Count >= Interval) { chainFinished = () => { Action <bool> doUpdate = singleton => { BubbleGroupEvents.RaiseRefreshed(groups); BubbleGroupEvents.RaiseBubblesUpdated(groups); BubbleGroupEvents.RaiseInformationUpdated(groups); }; groupsDoneCounter++; if (groupsDoneCounter % Interval == 0) { updateCounter++; doUpdate(false); } // do the remainder one by one ... else if (updateCounter >= updateCounterThreshold) { doUpdate(true); } }; } Update(@group, optimized, chainFinished); } }
internal static void UpdateName(BubbleGroup bubbleGroup, Action finished = null) { var service = bubbleGroup.Service; if (!ServiceManager.IsRunning(service)) { return; } try { service.GetBubbleGroupName(bubbleGroup, title => { bubbleGroup.IsTitleSetFromService = true; bubbleGroup.Title = title; if (finished == null) { BubbleGroupEvents.RaiseRefreshed(bubbleGroup); BubbleGroupEvents.RaiseInformationUpdated(bubbleGroup); } else { finished(); } }); } catch (Exception ex) { Utils.DebugPrint("Error updating bubble group name: " + service.Information.ServiceName + ": " + ex.Message); if (finished != null) { finished(); } } }
public static Task <List <Receipt> > Send(string[] serviceNames, bool scheduled = false) { return(Task <List <Receipt> > .Factory.StartNew(() => { //PROCESS: 1) find all bubbles under serviceNames in db // 2) relate db entries to bubbles loaded into memory by Disa // 3) parallel send bubbles based respective to service // 4) delete all successful bubbles out of db lock (_sendLock) { var nowUnixTimestamp = Time.GetNowUnixTimestamp(); var possibleBubblesFromDatabase = new List <Entry>(); lock (_dbLock) { using (var db = new SqlDatabase <Entry>(Location)) { foreach (var possibleBubble in db.Store.Where(x => serviceNames.Contains(x.ServiceName)).Reverse()) { if (!InsertBubble.IsSending(possibleBubble.Guid)) { possibleBubblesFromDatabase.Add(possibleBubble); } } } } var possibleBubblesInDisa = new List <Tuple <Entry, VisualBubble> >(); foreach (var bubbleGroup in BubbleGroupManager.BubbleGroupsNonUnified) { var hasPossibleBubble = possibleBubblesFromDatabase.FirstOrDefault(x => x.BubbleGroupGuid != null && x.BubbleGroupGuid == bubbleGroup.ID) != null; if (!hasPossibleBubble) { continue; } if (bubbleGroup.PartiallyLoaded) { BubbleGroupFactory.LoadFullyIfNeeded(bubbleGroup); } var bubblesToSetToFail = new List <Tuple <Entry, VisualBubble> >(); foreach (var bubble in bubbleGroup.Bubbles) { if (bubble.Status != Bubble.BubbleStatus.Waiting) { continue; } if (bubble.Direction != Bubble.BubbleDirection.Outgoing) { continue; } var possibleBubbleFromDatabase = possibleBubblesFromDatabase.FirstOrDefault(x => x.Guid == bubble.ID); if (possibleBubbleFromDatabase != null) { // older than 10 minutes, fail if (bubble.Time < (nowUnixTimestamp - 600)) { bubble.Status = Bubble.BubbleStatus.Failed; bubblesToSetToFail.Add(Tuple.Create(possibleBubbleFromDatabase, bubble)); continue; } possibleBubblesInDisa.Add(new Tuple <Entry, VisualBubble>(possibleBubbleFromDatabase, bubble)); } } if (bubblesToSetToFail.Any()) { BubbleGroupDatabase.UpdateBubble(bubbleGroup, bubblesToSetToFail.Select(x => x.Item2).ToArray(), 100); Remove(bubblesToSetToFail.Select(x => x.Item1).ToArray()); foreach (var bubble in bubblesToSetToFail) { BubbleGroupEvents.RaiseBubbleFailed(bubble.Item2, bubbleGroup); } BubbleGroupEvents.RaiseBubblesUpdated(bubbleGroup); BubbleGroupEvents.RaiseRefreshed(bubbleGroup); } } var sent = new List <Tuple <Entry, bool> >(); var possibleBubblesInDisaByService = possibleBubblesInDisa.GroupBy(x => x.Item1.ServiceName); Parallel.ForEach(possibleBubblesInDisaByService, possibleBubblesInService => { var failed = false; foreach (var possibleBubble in possibleBubblesInService) { if (failed) { sent.Add(new Tuple <Entry, bool>(possibleBubble.Item1, false)); continue; } Utils.DebugPrint(">>>>>>>>>>> Sending queued bubble on " + possibleBubble.Item2.Service.Information.ServiceName + "!"); var sendBubbleTask = BubbleManager.Send(possibleBubble.Item2, true); sendBubbleTask.Wait(); if (sendBubbleTask.Result) { Utils.DebugPrint(">>>>>>>>> Successfully sent queued bubble on " + possibleBubble.Item2.Service.Information.ServiceName + "!"); sent.Add(new Tuple <Entry, bool>(possibleBubble.Item1, true)); lock (_dbLock) { using (var db = new SqlDatabase <Entry>(Location)) { db.Remove(possibleBubble.Item1); } } Utils.Delay(100).Wait(); } else { Utils.DebugPrint(">>>>>>>>> Failed to send queued bubble on " + possibleBubble.Item2.Service.Information.ServiceName + "!"); sent.Add(new Tuple <Entry, bool>(possibleBubble.Item1, false)); failed = true; // fail the entire chain for this service from here on out so messages aren't sent out of order } } }); var receipts = sent.Select(x => new Receipt(x.Item1.Guid, x.Item2)).ToList(); if (!scheduled) { if (receipts.FirstOrDefault(x => !x.Success) != null) { ScheduleReSend(serviceNames); } else { var needToSendAgain = serviceNames.Where(x => BubbleQueueManager.HasQueuedBubbles(x, true, true)).ToArray(); if (needToSendAgain.Any()) { Send(needToSendAgain); } } } SanityCheckup(); return receipts; } })); }
public static void SetNotQueuedToFailures(BubbleGroup group) { var nowUnixTimeStamp = Time.GetNowUnixTimestamp(); var groups = BubbleGroupManager.GetInner(@group).Where(x => (x.Service.QueuedBubblesParameters != null && x.Service.QueuedBubblesParameters.BubblesNotToQueue != null && x.Service.QueuedBubblesParameters.BubblesNotToQueue.Any())); if (!groups.Any()) { return; } foreach (var innerGroup in groups) { if (HasNotQueued(innerGroup)) { if (innerGroup.PartiallyLoaded) { BubbleGroupFactory.LoadFullyIfNeeded(innerGroup); } var bubblesSetToFailed = new List <VisualBubble>(); foreach (var bubble in innerGroup.Bubbles) { if (bubble.Direction == Bubble.BubbleDirection.Outgoing && bubble.Status == Bubble.BubbleStatus.Waiting) { if (innerGroup .Service.QueuedBubblesParameters.BubblesNotToQueue .FirstOrDefault(x => x == bubble.GetType()) != null) { var failBubble = innerGroup .Service.QueuedBubblesParameters.SendingBubblesToFailOnServiceStart .FirstOrDefault(x => x == bubble.GetType()) != null; // Older than 10 minutes, fail it regardless. if (!failBubble && bubble.Time < (nowUnixTimeStamp - 600)) { failBubble = true; } if (failBubble) { RemoveNotQueued(bubble); bubble.Status = Bubble.BubbleStatus.Failed; bubblesSetToFailed.Add(bubble); } } } } if (bubblesSetToFailed.Any()) { BubbleGroupDatabase.UpdateBubble(innerGroup, bubblesSetToFailed.ToArray(), 100); foreach (var bubble in bubblesSetToFailed) { BubbleGroupEvents.RaiseBubbleFailed(bubble, innerGroup); } BubbleGroupEvents.RaiseBubblesUpdated(innerGroup); BubbleGroupEvents.RaiseRefreshed(innerGroup); } } } NotQueuedSanityCheckup(); }