Example #1
0
        public void Handle(ProjectionMessage.Projections.CommittedEventDistributed message)
        {
            if (message.Data == null)
            {
                throw new NotSupportedException();
            }

            // NOTE: we may receive here messages from heading event distribution point
            // and they may not pass out source filter.  Discard them first
            if (!_eventFilter.PassesSource(message.ResolvedLinkTo, message.PositionStreamId))
            {
                return;
            }
            var eventCheckpointTag = _positionTagger.MakeCheckpointTag(_positionTracker.LastTag, message);

            //TODO: when joining heading distribution point replayed events may cause invalid operation exception on comparison
            if (eventCheckpointTag <= _positionTracker.LastTag)
            {
                _logger.Trace(
                    "Skipping replayed event {0}@{1} at position {2}. the last processed event checkpoint tag is: {3}",
                    message.PositionSequenceNumber, message.PositionStreamId, message.Position, _positionTracker.LastTag);
                return;
            }
            _positionTracker.UpdateByCheckpointTagForward(eventCheckpointTag);
            if (_eventFilter.Passes(message.ResolvedLinkTo, message.PositionStreamId, message.Data.EventType))
            {
                _lastPassedOrCheckpointedEventPosition = message.Position;
                var convertedMessage =
                    ProjectionMessage.Projections.CommittedEventReceived.FromCommittedEventDistributed(message, eventCheckpointTag);
                _eventHandler.Handle(convertedMessage);
            }
            else
            {
                if (_checkpointUnhandledBytesThreshold != null &&
                    message.Position.CommitPosition - _lastPassedOrCheckpointedEventPosition.CommitPosition
                    > _checkpointUnhandledBytesThreshold)
                {
                    _lastPassedOrCheckpointedEventPosition = message.Position;
                    _checkpointHandler.Handle(
                        new ProjectionMessage.Projections.CheckpointSuggested(
                            _projectionCorrelationId, _positionTracker.LastTag));
                }
            }
        }
        protected void ProcessOne(ReaderSubscriptionMessage.CommittedEventDistributed message)
        {
            // NOTE: we may receive here messages from heading event distribution point
            // and they may not pass out source filter.  Discard them first
            var  roundedProgress = (float)Math.Round(message.Progress, 2);
            bool progressChanged = _progress != roundedProgress;

            _progress = roundedProgress;
            if (
                !_eventFilter.PassesSource(
                    message.Data.ResolvedLinkTo, message.Data.PositionStreamId, message.Data.EventType))
            {
                if (progressChanged)
                {
                    PublishProgress();
                }
                return;
            }

            // NOTE: after joining heading distribution point it delivers all cached events to the subscription
            // some of this events we may have already received. The delivered events may have different order
            // (in case of partially ordered cases multi-stream reader etc). We discard all the messages that are not
            // after the last available checkpoint tag

            //NOTE: older events can appear here when replaying events from the heading event reader
            //      or when event-by-type-index reader reads TF and both event and resolved-event appear as output

            if (!_positionTagger.IsMessageAfterCheckpointTag(_positionTracker.LastTag, message))
            {
/*
 *              _logger.Trace(
 *                  "Skipping replayed event {0}@{1} at position {2}. the last processed event checkpoint tag is: {3}",
 *                  message.PositionSequenceNumber, message.PositionStreamId, message.Position, _positionTracker.LastTag);
 */
                return;
            }
            var eventCheckpointTag = _positionTagger.MakeCheckpointTag(_positionTracker.LastTag, message);

            _positionTracker.UpdateByCheckpointTagForward(eventCheckpointTag);
            if (_eventFilter.Passes(
                    message.Data.ResolvedLinkTo, message.Data.PositionStreamId, message.Data.EventType,
                    message.Data.IsStreamDeletedEvent))
            {
                _lastPassedOrCheckpointedEventPosition = message.Data.Position.PreparePosition;
                var convertedMessage =
                    EventReaderSubscriptionMessage.CommittedEventReceived.FromCommittedEventDistributed(
                        message, eventCheckpointTag, _eventFilter.GetCategory(message.Data.PositionStreamId),
                        _subscriptionId, _subscriptionMessageSequenceNumber++);
                _publisher.Publish(convertedMessage);
                _eventsSinceLastCheckpointSuggested++;
                if (_checkpointProcessedEventsThreshold > 0 &&
                    _eventsSinceLastCheckpointSuggested >= _checkpointProcessedEventsThreshold)
                {
                    SuggestCheckpoint(message);
                }
            }
            else
            {
                if (_checkpointUnhandledBytesThreshold > 0 &&
                    (_lastPassedOrCheckpointedEventPosition != null &&
                     message.Data.Position.PreparePosition - _lastPassedOrCheckpointedEventPosition.Value
                     > _checkpointUnhandledBytesThreshold))
                {
                    SuggestCheckpoint(message);
                }
                else
                {
                    if (progressChanged)
                    {
                        PublishProgress();
                    }
                }
            }
            // initialize checkpointing based on first message
            if (_lastPassedOrCheckpointedEventPosition == null)
            {
                _lastPassedOrCheckpointedEventPosition = message.Data.Position.PreparePosition;
            }
        }
        protected void ProcessOne(ReaderSubscriptionMessage.CommittedEventDistributed message)
        {
            if (_eofReached)
            {
                return;                 // eof may be set by reach N events
            }
            // NOTE: we may receive here messages from heading event distribution point
            // and they may not pass out source filter.  Discard them first
            var  roundedProgress = (float)Math.Round(message.Progress, 1);
            bool progressChanged = _progress != roundedProgress;

            bool passesStreamSourceFilter = _eventFilter.PassesSource(message.Data.ResolvedLinkTo, message.Data.PositionStreamId, message.Data.EventType);
            bool passesEventFilter        = _eventFilter.Passes(message.Data.ResolvedLinkTo, message.Data.PositionStreamId, message.Data.EventType, message.Data.IsStreamDeletedEvent);
            bool isValid = !_enableContentTypeValidation || _eventFilter.PassesValidation(message.Data.IsJson, message.Data.Data);

            if (!isValid)
            {
                _logger.Verbose($"Event {message.Data.EventSequenceNumber}@{message.Data.EventStreamId} is not valid json. Data: ({message.Data.Data})");
            }

            CheckpointTag eventCheckpointTag = null;

            if (passesStreamSourceFilter)
            {
                // NOTE: after joining heading distribution point it delivers all cached events to the subscription
                // some of this events we may have already received. The delivered events may have different order
                // (in case of partially ordered cases multi-stream reader etc). We discard all the messages that are not
                // after the last available checkpoint tag

                //NOTE: older events can appear here when replaying events from the heading event reader
                //      or when event-by-type-index reader reads TF and both event and resolved-event appear as output
                if (!_positionTagger.IsMessageAfterCheckpointTag(_positionTracker.LastTag, message))
                {
                    return;
                }

                eventCheckpointTag = _positionTagger.MakeCheckpointTag(_positionTracker.LastTag, message);
                _positionTracker.UpdateByCheckpointTagForward(eventCheckpointTag);
            }

            var now            = _timeProvider.UtcNow;
            var timeDifference = now - _lastCheckpointTime;

            if (isValid && passesEventFilter)
            {
                Debug.Assert(passesStreamSourceFilter, "Event passes event filter but not source filter");
                Debug.Assert(eventCheckpointTag != null, "Event checkpoint tag is null");

                _lastPassedOrCheckpointedEventPosition = message.Data.Position.PreparePosition;
                var convertedMessage =
                    EventReaderSubscriptionMessage.CommittedEventReceived.FromCommittedEventDistributed(
                        message, eventCheckpointTag, _eventFilter.GetCategory(message.Data.PositionStreamId),
                        _subscriptionId, _subscriptionMessageSequenceNumber++);
                _publisher.Publish(convertedMessage);
                _eventsSinceLastCheckpointSuggestedOrStart++;
                if (_checkpointProcessedEventsThreshold > 0 &&
                    timeDifference > _checkpointAfter &&
                    _eventsSinceLastCheckpointSuggestedOrStart >= _checkpointProcessedEventsThreshold &&
                    _lastCheckpointTag != _positionTracker.LastTag)
                {
                    SuggestCheckpoint(message);
                }
                if (_stopAfterNEvents > 0 && _eventsSinceLastCheckpointSuggestedOrStart >= _stopAfterNEvents)
                {
                    NEventsReached();
                }
            }
            else
            {
                if (_checkpointUnhandledBytesThreshold > 0 &&
                    timeDifference > _checkpointAfter &&
                    (_lastPassedOrCheckpointedEventPosition != null &&
                     message.Data.Position.PreparePosition - _lastPassedOrCheckpointedEventPosition.Value
                     > _checkpointUnhandledBytesThreshold) &&
                    _lastCheckpointTag != _positionTracker.LastTag)
                {
                    SuggestCheckpoint(message);
                }
                else if (progressChanged)
                {
                    PublishProgress(roundedProgress);
                }
            }

            // initialize checkpointing based on first message
            if (_lastPassedOrCheckpointedEventPosition == null)
            {
                _lastPassedOrCheckpointedEventPosition = message.Data.Position.PreparePosition;
            }
        }
        public void Handle(ProjectionCoreServiceMessage.CommittedEventDistributed message)
        {
            if (message.Data == null)
            {
                throw new NotSupportedException();
            }

            // NOTE: we may receive here messages from heading event distribution point
            // and they may not pass out source filter.  Discard them first
            var  roundedProgress = (float)Math.Round(message.Progress, 2);
            bool progressChanged = _progress != roundedProgress;

            _progress = roundedProgress;
            if (!_eventFilter.PassesSource(message.ResolvedLinkTo, message.PositionStreamId))
            {
                if (progressChanged)
                {
                    _progressHandler.Handle(
                        new ProjectionSubscriptionMessage.ProgressChanged(
                            _projectionCorrelationId, _positionTracker.LastTag, _progress,
                            _subscriptionMessageSequenceNumber++));
                }
                return;
            }
            // NOTE: after joining heading distribution point it delivers all cached events to the subscription
            // some of this events we may have already received. The delivered events may have different order
            // (in case of partially ordered cases multi-stream reader etc). We discard all the messages that are not
            // after the last available checkpoint tag
            if (!_positionTagger.IsMessageAfterCheckpointTag(_positionTracker.LastTag, message))
            {
                _logger.Trace(
                    "Skipping replayed event {0}@{1} at position {2}. the last processed event checkpoint tag is: {3}",
                    message.PositionSequenceNumber, message.PositionStreamId, message.Position, _positionTracker.LastTag);
                return;
            }
            var eventCheckpointTag = _positionTagger.MakeCheckpointTag(_positionTracker.LastTag, message);

            if (eventCheckpointTag <= _positionTracker.LastTag)
            {
                throw new Exception(
                          string.Format(
                              "Invalid checkpoint tag was built.  Tag '{0}' must be greater than '{1}'", eventCheckpointTag,
                              _positionTracker.LastTag));
            }
            _positionTracker.UpdateByCheckpointTagForward(eventCheckpointTag);
            if (_eventFilter.Passes(message.ResolvedLinkTo, message.PositionStreamId, message.Data.EventType))
            {
                _lastPassedOrCheckpointedEventPosition = message.Position;
                var convertedMessage =
                    ProjectionSubscriptionMessage.CommittedEventReceived.FromCommittedEventDistributed(
                        message, eventCheckpointTag, _eventFilter.GetCategory(message.PositionStreamId),
                        _subscriptionMessageSequenceNumber++);
                _eventHandler.Handle(convertedMessage);
            }
            else
            {
                if (_checkpointUnhandledBytesThreshold != null &&
                    message.Position.CommitPosition - _lastPassedOrCheckpointedEventPosition.CommitPosition
                    > _checkpointUnhandledBytesThreshold)
                {
                    _lastPassedOrCheckpointedEventPosition = message.Position;
                    _checkpointHandler.Handle(
                        new ProjectionSubscriptionMessage.CheckpointSuggested(
                            _projectionCorrelationId, _positionTracker.LastTag, message.Progress,
                            _subscriptionMessageSequenceNumber++));
                }
                else
                {
                    if (progressChanged)
                    {
                        _progressHandler.Handle(
                            new ProjectionSubscriptionMessage.ProgressChanged(
                                _projectionCorrelationId, _positionTracker.LastTag, _progress,
                                _subscriptionMessageSequenceNumber++));
                    }
                }
            }
        }