public bool SyncChannelsByPeriod(VideoReg video, DateInterval interval) { var cts = new CancellationTokenSource(); var task = new Task(() => { using (var ftp = FtpLoader.Start(video.FtpSettings)) { try { // Загружаем данные за необходимый интревал // video.BrigadeCode, video.ChannelFolder, channelFolder string localRoot = Path.Combine(channelFolder, video.BrigadeCode.ToString()); ftp.DownloadFilesByInterval(interval, video.ChannelFolder, localRoot, cts); } catch (OperationCanceledException e) { logger.Info(e, $"{video.BrigadeCode} [{interval}] operation canseled"); } catch (Exception e) { logger.Error(e); } } // Сннимаем задачу из списка задач lock (tasksLock) { tasks.RemoveAll(t => t.BrigadeCode == video.BrigadeCode && t.Interval == interval); } }, cts.Token); ChannelTask newTask = new ChannelTask { BrigadeCode = video.BrigadeCode, Interval = interval, Task = task, Cts = cts }; lock (tasksLock) { // Проверем выполняется ли в данный момент аналогичная задача если да то не надо ее дублировать ChannelTask oldTask = tasks.FirstOrDefault(x => x.BrigadeCode == video.BrigadeCode && x.Interval == interval); if (oldTask != null) { logger.Warn($"SyncChannelsByPeriod({video.BrigadeCode}, {interval}) [EXECUTION-MISS]"); return(false); } // Ставим задачу на выполнение tasks.Add(newTask); newTask.Task.Start(); } logger.Info($"SyncChannelsByPeriod({video.BrigadeCode}, {interval}) [EXECUTION]"); return(true); }
public static async Task <Statistics> GetCache(SocketGuild guild, IUserMessage statusMsg, bool reloadCache = false) { var loadedMessages = 0; Direction searchDir = Direction.Before; // Initialize cache if not present if (_cache == null || reloadCache) { _cache = new Statistics(guild); } else { searchDir = Direction.After; } Dictionary <ITextChannel, ChannelTask> tasks = new Dictionary <ITextChannel, ChannelTask>(); // Get all channels and create tasks to read all messages foreach (var channel in guild.Channels) { if (channel is ITextChannel textChannel) { ChannelTask task = new ChannelTask(guild.Emotes); if (searchDir == Direction.Before) { task._task = textChannel.GetMessagesAsync(limit: _messagesInBatch).FlattenAsync(); } else if (_cache._newestMessageInCache.ContainsKey(textChannel.Id)) { task._task = textChannel.GetMessagesAsync(_cache._newestMessageInCache[textChannel.Id], searchDir, limit: _messagesInBatch).FlattenAsync(); } else { continue; } tasks.Add(textChannel, task); Console.WriteLine($"[{DateTime.Now.ToString()}] Added task {textChannel.Name} ({tasks.Count})"); System.Threading.Thread.Sleep(200); } } while (tasks.Any()) { var completedList = tasks.Where(task => task.Value._task.IsCompleted).ToList(); foreach (var task in completedList) { if (task.Value._task.IsFaulted) { tasks.Remove(task.Key); continue; } var messages = task.Value._task.Result; _cache._messages[task.Key.Id].AddRange(messages); if (messages.Any()) { if (!_cache._newestMessageInCache.ContainsKey(task.Key.Id)) { _cache._newestMessageInCache[task.Key.Id] = messages.First(); } if (searchDir == Direction.Before && _cache._newestMessageInCache[task.Key.Id].Timestamp < messages.First().Timestamp) { _cache._newestMessageInCache[task.Key.Id] = messages.First(); } else if (searchDir == Direction.After && _cache._newestMessageInCache[task.Key.Id].Timestamp < messages.Last().Timestamp) { _cache._newestMessageInCache[task.Key.Id] = messages.Last(); } } foreach (var message in messages) { foreach (var emote in new Dictionary <string, EmoteUsage>(task.Value._localEmoteStats)) { var emoteString = emote.Key; if (!task.Value._localEmoteStats.ContainsKey(emoteString)) { task.Value._localEmoteStats[emoteString] = new EmoteUsage(); } task.Value._localEmoteStats[emoteString]._messages += message.Content.CountStrings(emoteString); foreach (var embed in message.Embeds) { if (embed.Title != null) { task.Value._localEmoteStats[emoteString]._embeds += embed.Title.CountStrings(emoteString); } if (embed.Description != null) { task.Value._localEmoteStats[emoteString]._embeds += embed.Description.CountStrings(emoteString); } if (embed.Footer.HasValue) { task.Value._localEmoteStats[emoteString]._embeds += embed.Footer.Value.Text.CountStrings(emoteString); } foreach (var embedField in embed.Fields) { if (embedField.Name != null) { task.Value._localEmoteStats[emoteString]._embeds += embedField.Name.CountStrings(emoteString); } if (embedField.Value != null) { task.Value._localEmoteStats[emoteString]._embeds += embedField.Value.CountStrings(emoteString); } } } foreach (var reaction in message.Reactions) { if (reaction.Key.ToString() == emote.Key.ToString()) { if (!task.Value._localEmoteStats.ContainsKey(reaction.Key.ToString())) { task.Value._localEmoteStats[reaction.Key.ToString()] = new EmoteUsage(); } task.Value._localEmoteStats[reaction.Key.ToString()]._reactions += reaction.Value.ReactionCount; } } } } if (messages.Any()) { task.Value._oldestLoadedMessage = messages.Last(); } task.Value._messagesLoaded += messages.Count(); loadedMessages += task.Value._messagesLoaded - task.Value._lastMessagesLoaded; if (task.Value._messagesLoaded == task.Value._lastMessagesLoaded + _messagesInBatch) { task.Value._lastMessagesLoaded = task.Value._messagesLoaded; Console.WriteLine($"[{DateTime.Now.ToString()}] Updated task {task.Key.Name} ({task.Value._messagesLoaded}) - [{task.Value._oldestLoadedMessage.Timestamp.ToString()}], tasks: {tasks.Count}"); if (searchDir == Direction.Before) { task.Value._task = task.Key.GetMessagesAsync(task.Value._oldestLoadedMessage, searchDir, limit: _messagesInBatch).FlattenAsync(); } else { task.Value._task = task.Key.GetMessagesAsync(_cache._newestMessageInCache[task.Key.Id], searchDir, limit: _messagesInBatch).FlattenAsync(); } System.Threading.Thread.Sleep(200); } else { foreach (var emote in task.Value._localEmoteStats) { if (!_cache._emotesUsage.ContainsKey(emote.Key)) { _cache._emotesUsage[emote.Key] = new EmoteUsage(); } _cache._emotesUsage[emote.Key] += emote.Value; } tasks.Remove(task.Key); Console.WriteLine($"[{DateTime.Now.ToString()}] Updated task {task.Key.Name} ({task.Value._messagesLoaded}), tasks: {tasks.Count}"); } } if (completedList.Any()) { var newEmbed = new EmbedBuilder { Title = statusMsg.Embeds.First().Title, Description = $"Przeanalizowano: {loadedMessages} wiadomości\n" + $"Pozostało kanałów: {tasks.Count}" }; await statusMsg.ModifyAsync(x => x.Embed = newEmbed.Build()); } } return(_cache); }