Example #1
0
        private void InvokeGrouper(object source, ElapsedEventArgs e)
        {
            Timer timer = (Timer)source;
            List <GrouperDocumentEntry> entries = new List <GrouperDocumentEntry>();
            bool processAllDocuments            = ShouldProcessAllDocuments();

            if (processAllDocuments)
            {
                _lastFullProcessHour = DateTime.Now.Hour;
                entries.AddRange(_documentDb.GetAllEntriesAsync().GetAwaiter().GetResult());
            }
            else
            {
                // Get documents that changed since the last timer event.
                // It doesn't matter if we miss a document. It will be processed in the next full run
                DateTime start = DateTime.Now.AddMilliseconds(-_workInterval);
                entries.AddRange(_documentDb.GetEntriesByAgeAsync(start).GetAwaiter().GetResult());

                // Get documents that have a processing interval hint and
                // where the interval has passed.
                IEnumerable <GrouperDocumentEntry> entriesWithInterval =
                    _documentDb.GetEntriesByProcessingInterval(min: 1).GetAwaiter().GetResult();
                foreach (GrouperDocumentEntry entry in entriesWithInterval)
                {
                    if (_lastProcessedDictionary.TryGetValue(entry.Document.Id, out DateTime lastProcessed))
                    {
                        if (lastProcessed.AddMinutes(entry.Document.ProcessingInterval) < DateTime.Now)
                        {
                            entries.Add(entry);
                        }
                        // If it's not in the dictionary, process interval was added to the document
                        // after the service started and the document should be picked up by the
                        // document age check above (this includes both new and changed documents)
                    }
                }
            }
            foreach (GrouperDocumentEntry entry in entries)
            {
                DebugPrint("Processing group {0}", entry.GroupName);
                if (_stopRequested)
                {
                    return;
                }
                try
                {
                    GroupMemberDiff diff = _grouper.GetMemberDiffAsync(entry.Document).GetAwaiter().GetResult();
                    _grouper.UpdateGroupAsync(diff).GetAwaiter().GetResult();
                    if (entry.Document.ProcessingInterval > 0)
                    {
                        _lastProcessedDictionary[entry.Document.Id] = DateTime.Now;
                    }
                    DebugPrint("Processed group {0}. {1} added, {2} removed.", entry.GroupName, diff.Add.Count(), diff.Remove.Count());
                }
                catch (Exception ex)
                {
                    string message = ex.Message;
                    if (ex.InnerException != null)
                    {
                        message = ex.InnerException.Message;
                    }
                    WriteToLogDb(entry.Document, message, LogLevels.Error);
                    if (!(ex is GroupNotFoundException || ex is MemberNotFoundException || ex is ChangeRatioException))
                    {
                        WriteToEventLog(message, EventLogEntryType.Error);
                    }
                }
            }
            // There is a memory leak somewhere. Likely in Exo. So we tear down Grouper and build a new one after
            // every full run and see if that helps narrow down the leak.
            if (processAllDocuments)
            {
                SetupGrouper();
            }
            if (!_stopRequested)
            {
                timer.Enabled = true;
            }
        }