public void SimpleEventsAndPersistingRightAway()
        {
            var startEvent1 = GetStartEvent(1);
            var endEvent1   = GetEndEvent(1);

            _persister.AddStartEvent(startEvent1);
            _persister.AddEndEvent(endEvent1); // This is complete event and should be persisted right away

            var startEvent2 = GetStartEvent(2);

            startEvent2.StartFile = "some_other_file.log";
            var endEvent2 = GetEndEvent(2);

            _persister.AddStartEvent(startEvent2);
            _persister.AddEndEvent(endEvent2); // This is complete, but should not be merged right away because file paths are different

            var startEvent3 = GetStartEvent(3);

            _persister.AddStartEvent(startEvent3); // This is incomplete event, so it will be persisted only after drain

            var jobWriter = _writerFactory.GetOneWriterAndVerifyOthersAreEmpty <BackgrounderJob>("BackgrounderJobs", 4);

            jobWriter.ReceivedObjects.Count.Should().Be(1);
            var fullEvent1     = (BackgrounderJob)jobWriter.ReceivedObjects[0];
            var combinedEvent1 = CopyValues(startEvent1, endEvent1);

            fullEvent1.Should().BeEquivalentTo(combinedEvent1);

            _persister.DrainEvents();

            jobWriter.ReceivedObjects.Count.Should().Be(3);
            var fullEvent2     = (BackgrounderJob)jobWriter.ReceivedObjects[1];
            var combinedEvent2 = CopyValues(startEvent2, endEvent2);

            fullEvent2.Should().BeEquivalentTo(combinedEvent2);
            var partialEvent = (BackgrounderJob)jobWriter.ReceivedObjects[2];

            partialEvent.Should().BeEquivalentTo(startEvent3);
        }
        public void ParseAndPersistLine(LogLine logLine, string logLineText)
        {
            if (logLineText == null || logLine == null)
            {
                _processingNotificationsCollector.ReportError($"{nameof(BackgrounderEventParser)} received null log line or log string", logLine, nameof(BackgrounderPlugin));
                return;
            }

            var backgrounderId = GetBackgrounderId(logLine);

            var lineMatch = NewBackgrounderRegex.Match(logLineText);

            if (!lineMatch.Success)
            {
                _processingNotificationsCollector.ReportError($"Failed to process string as Backgrounder event. This is expected for logs prior to 10.4", logLine, nameof(BackgrounderPlugin));
                return;
            }

            var errorEvent = ParseErrorMessage(lineMatch, logLine);

            if (errorEvent != null)
            {
                _backgrounderEventPersister.AddErrorEvent(errorEvent);
                return;
            }

            if (!int.TryParse(lineMatch.Groups["job_id"].Value, out var jobId))
            {
                return; // We only allow error messages to not have job id
            }

            var startEvent = TryMatchStartMessage(lineMatch, logLine, backgrounderId, jobId);

            if (startEvent != null)
            {
                _backgrounderEventPersister.AddStartEvent(startEvent);
                return;
            }

            var endEvent = TryMatchEndMessage(lineMatch, logLine, jobId);

            if (endEvent != null)
            {
                _backgrounderEventPersister.AddEndEvent(endEvent);
                return;
            }

            var extractJobDetails = TryMatchExtractJobDetails(lineMatch, jobId, logLine);

            if (extractJobDetails != null)
            {
                _backgrounderEventPersister.AddExtractJobDetails(extractJobDetails);
                return;
            }

            var subscriptionJobDetails = TryMatchSubscriptionJobDetails(lineMatch, jobId);

            if (subscriptionJobDetails != null)
            {
                _backgrounderEventPersister.AddSubscriptionJobDetails(subscriptionJobDetails);
                return;
            }
        }