コード例 #1
0
        private void BeginStatePartitionLoad(
            ProjectionMessage.Projections.CommittedEventReceived @event, Action loadCompleted)
        {
            string statePartition = _checkpointStrategy.StatePartitionSelector.GetStatePartition(@event);

            if (statePartition == "") // root is always cached
            {
                loadCompleted();
                return;
            }
            string state = _partitionStateCache.TryGetAndLockPartitionState(
                statePartition, _checkpointStrategy.PositionTagger.MakeCheckpointTag(@event));

            if (state != null)
            {
                loadCompleted();
            }
            else
            {
                string partitionStateStreamName = MakePartitionStateStreamName(statePartition);
                _readDispatcher.Publish(
                    new ClientMessage.ReadEventsBackwards(
                        Guid.NewGuid(), new SendToThisEnvelope(this), partitionStateStreamName, -1, 1,
                        resolveLinks: false),
                    m => OnLoadStatePartitionCompleted(statePartition, @event, m, loadCompleted));
            }
        }
コード例 #2
0
        private void FinilizeCommittedEventProcessing(ProjectionMessage.Projections.CommittedEventReceived message)
        {
            if (message.Data == null)
            {
                throw new NotSupportedException();
            }
            if (_state == State.Faulted || _state == State.FaultedStopping)
            {
                return;
            }
            EnsureState(State.Running);
            //TODO: move to separate projection method and cache result in work item
            bool passedFilter = EventPassesFilter(message);

            if (passedFilter)
            {
                _lastProcessedEventPosition.Update(message);
                _eventsProcessedAfterRestart++;
            }
            else
            {
                if (EventPassesSourceFilter(message))
                {
                    _lastProcessedEventPosition.Update(message);
                }
                else
                {
                    _lastProcessedEventPosition.UpdatePosition(message.Position);
                }
            }
        }
コード例 #3
0
        public void Handle(ProjectionMessage.Projections.CommittedEventReceived message)
        {
            Guid projectionId;

            if (_stopped)
            {
                return;
            }
            if (_headingEventDistributionPoint.Handle(message))
            {
                return;
            }
            if (!_distributionPointSubscriptions.TryGetValue(message.CorrelationId, out projectionId))
            {
                return; // unsubscribed
            }
            if (TrySubscribeHeadingDistributionPoint(message, projectionId))
            {
                return;
            }
            if (message.Data != null) // means notification about the end of the stream/source
            {
                _projections[projectionId].Handle(message);
            }
        }
コード例 #4
0
        internal void BeginStatePartitionLoad(
            ProjectionMessage.Projections.CommittedEventReceived @event, Action loadCompleted)
        {
            string statePartition = _checkpointStrategy.StatePartitionSelector.GetStatePartition(@event);

            if (statePartition == "") // root is always cached
            {
                loadCompleted();
                return;
            }
            string state = _partitionStateCache.TryGetAndLockPartitionState(statePartition, @event.CheckpointTag);

            if (state != null)
            {
                loadCompleted();
            }
            else
            {
                string partitionStateStreamName = MakePartitionStateStreamName(statePartition);
                _readRequestsInProgress++;
                _readDispatcher.Publish(
                    new ClientMessage.ReadStreamEventsBackward(
                        Guid.NewGuid(), _readDispatcher.Envelope, partitionStateStreamName, -1, 1, resolveLinks: false),
                    m => OnLoadStatePartitionCompleted(statePartition, @event, m, loadCompleted));
            }
        }
コード例 #5
0
 private void DistributeMessage(ProjectionMessage.Projections.CommittedEventReceived message)
 {
     foreach (var subscriber in _headSubscribers.Values)
     {
         subscriber.Handle(message);
     }
 }
コード例 #6
0
 public CommittedEventWorkItem(
     CoreProjection projection, ProjectionMessage.Projections.CommittedEventReceived message, string partition)
     : base(projection, message.EventStreamId)
 {
     _message   = message;
     _partition = partition;
 }
コード例 #7
0
 public CommittedEventWorkItem(
     CoreProjection projection, ProjectionMessage.Projections.CommittedEventReceived message, string partition)
     : base(projection, message.EventStreamId)
 {
     _message = message;
     _partition = partition;
 }
コード例 #8
0
        public void Update(ProjectionMessage.Projections.CommittedEventReceived comittedEvent)
        {
            var newTag = _positionTagger.MakeCheckpointTag(comittedEvent);

            UpdateByCheckpointTagForward(newTag);
            UpdatePosition(comittedEvent.Position);
        }
コード例 #9
0
 public override CheckpointTag MakeCheckpointTag(ProjectionMessage.Projections.CommittedEventReceived comittedEvent)
 {
     if (comittedEvent.PositionStreamId != _stream)
     {
         throw new InvalidOperationException(string.Format("Invalid stream '{0}'.  Expected stream is '{1}'", comittedEvent.EventStreamId, _stream));
     }
     return(CheckpointTag.FromStreamPosition(comittedEvent.PositionStreamId, comittedEvent.PositionSequenceNumber, comittedEvent.Position.PreparePosition));
 }
コード例 #10
0
 public CommittedEventWorkItem(
     CoreProjection projection, ProjectionMessage.Projections.CommittedEventReceived message,
     string partition, CheckpointTag tag)
     : base(message.EventStreamId)
 {
     _projection = projection;
     _message    = message;
     _partition  = partition;
     _tag        = tag;
 }
コード例 #11
0
 private bool ProcessEventByHandler(
     string partition, ProjectionMessage.Projections.CommittedEventReceived message, out string newState,
     out EmittedEvent[] emittedEvents)
 {
     SetHandlerState(partition);
     return(_projectionStateHandler.ProcessEvent(
                message.Position, message.EventStreamId, message.Data.EventType,
                _eventFilter.GetCategory(message.PositionStreamId), message.Data.EventId, message.EventSequenceNumber,
                Encoding.UTF8.GetString(message.Data.Metadata), Encoding.UTF8.GetString(message.Data.Data), out newState,
                out emittedEvents));
 }
コード例 #12
0
        private void CacheRecentMessage(ProjectionMessage.Projections.CommittedEventReceived message)
        {
            _lastMessages.Enqueue(message);
            if (_lastMessages.Count > _eventCacheSize)
            {
                _lastMessages.Dequeue();
            }
            var lastAvailableCommittedevent = _lastMessages.Peek();

            _subscribeFromPosition = lastAvailableCommittedevent.Position;
        }
コード例 #13
0
        private void ProcessCommittedEvent(
            CommittedEventWorkItem committedEventWorkItem, ProjectionMessage.Projections.CommittedEventReceived message,
            string partition)
        {
            if (message.Data == null)
            {
                throw new NotSupportedException();
            }

            EnsureState(State.Running);
            InternalProcessCommittedEvent(committedEventWorkItem, partition, message);
        }
コード例 #14
0
 private void ProcessEventFaulted(ProjectionMessage.Projections.CommittedEventReceived message, Exception ex)
 {
     _faultedReason =
         string.Format(
             "The {0} projection failed to process an event.\r\nHandler: {1}\r\nEvent Position: {2}\r\n\r\nMessage:\r\n\r\n{3}",
             _name, GetHandlerTypeName(), message.Position, ex.Message);
     if (_logger != null)
     {
         _logger.ErrorException(ex, _faultedReason);
     }
     GoToState(State.FaultedStopping);
 }
コード例 #15
0
 internal void FinalizeEventProcessing(
     List <EmittedEvent[]> scheduledWrites,
     ProjectionMessage.Projections.CommittedEventReceived committedEventReceived)
 {
     if (committedEventReceived.Data == null)
     {
         throw new NotSupportedException();
     }
     if (_state != State.Faulted && _state != State.FaultedStopping)
     {
         EnsureState(State.Running);
         //TODO: move to separate projection method and cache result in work item
         var checkpointTag = committedEventReceived.CheckpointTag;
         _checkpointManager.EventProcessed(GetProjectionState(), scheduledWrites, checkpointTag);
     }
 }
コード例 #16
0
        private void InternalProcessCommittedEvent(
            CommittedEventWorkItem committedEventWorkItem, string partition,
            ProjectionMessage.Projections.CommittedEventReceived message)
        {
            string newState = null;

            EmittedEvent[] emittedEvents = null;

            //TODO: not emitting (optimized) projection handlers can skip serializing state on each processed event
            bool hasBeenProcessed;

            try
            {
                hasBeenProcessed = ProcessEventByHandler(partition, message, out newState, out emittedEvents);
            }
            catch (Exception ex)
            {
                ProcessEventFaulted(
                    string.Format(
                        "The {0} projection failed to process an event.\r\nHandler: {1}\r\nEvent Position: {2}\r\n\r\nMessage:\r\n\r\n{3}",
                        _name, GetHandlerTypeName(), message.Position, ex.Message), ex);
                newState         = null;
                emittedEvents    = null;
                hasBeenProcessed = false;
            }
            newState = newState ?? "";
            if (hasBeenProcessed)
            {
                if (!ProcessEmittedEvents(committedEventWorkItem, emittedEvents))
                {
                    return;
                }

                if (_partitionStateCache.GetLockedPartitionState(partition) != newState)
                // ensure state actually changed
                {
                    var lockPartitionStateAt = partition != "" ? message.CheckpointTag : null;
                    _partitionStateCache.CacheAndLockPartitionState(partition, newState, lockPartitionStateAt);
                    if (_projectionConfig.PublishStateUpdates)
                    {
                        EmitStateUpdated(committedEventWorkItem, partition, newState);
                    }
                }
            }
        }
コード例 #17
0
        private void InternalProcessCommittedEvent(
            CommittedEventWorkItem committedEventWorkItem, string partition,
            ProjectionMessage.Projections.CommittedEventReceived message)
        {
            string newState = null;

            EmittedEvent[] emittedEvents = null;

            //TODO: not emitting (optimized) projection handlers can skip serializing state on each processed event
            bool hasBeenProcessed;

            try
            {
                bool passedFilter = EventPassesFilter(message);
                hasBeenProcessed = passedFilter &&
                                   ProcessEventByHandler(partition, message, out newState, out emittedEvents);
            }
            catch (Exception ex)
            {
                ProcessEventFaulted(message, ex);
                newState         = null;
                emittedEvents    = null;
                hasBeenProcessed = false;
            }
            newState = newState ?? "";
            if (hasBeenProcessed)
            {
                if (_projectionConfig.EmitEventEnabled)
                {
                    EmitEmittedEvents(committedEventWorkItem, emittedEvents);
                }
                if (_partitionStateCache.GetLockedPartitionState(partition) != newState)
                // ensure state actually changed
                {
                    var lockPartitionStateAt = partition != ""
                                                   ? _checkpointStrategy.PositionTagger.MakeCheckpointTag(message)
                                                   : null;
                    _partitionStateCache.CacheAndLockPartitionState(partition, newState, lockPartitionStateAt);
                    if (_projectionConfig.PublishStateUpdates)
                    {
                        EmitStateUpdated(committedEventWorkItem, partition, newState);
                    }
                }
            }
        }
コード例 #18
0
 public bool Handle(ProjectionMessage.Projections.CommittedEventReceived message)
 {
     if (message.CorrelationId != _distributionPointId)
     {
         return(false);
     }
     if (message.Data == null)
     {
         return(true);
     }
     CacheRecentMessage(message);
     DistributeMessage(message);
     if (_headSubscribers.Count == 0 && !_headDistributionPointPaused)
     {
         _headDistributionPoint.Pause();
         _headDistributionPointPaused = true;
     }
     return(true);
 }
コード例 #19
0
        private void OnLoadStatePartitionCompleted(
            string partition, ProjectionMessage.Projections.CommittedEventReceived committedEventReceived,
            ClientMessage.ReadStreamEventsBackwardCompleted message, Action loadCompleted)
        {
            _readRequestsInProgress--;
            var positionTag = committedEventReceived.CheckpointTag;

            if (message.Events.Length == 1)
            {
                EventRecord @event = message.Events[0].Event;
                if (@event.EventType == "StateUpdated")
                {
                    var checkpointTag = @event.Metadata.ParseJson <CheckpointTag>();
                    // always recovery mode? skip until state before current event
                    //TODO: skip event processing in case we know i has been already processed
                    CheckpointTag eventPositionTag = positionTag;
                    if (checkpointTag < eventPositionTag)
                    {
                        _partitionStateCache.CacheAndLockPartitionState(
                            partition, Encoding.UTF8.GetString(@event.Data), eventPositionTag);
                        loadCompleted();
                        EnsureTickPending();
                        return;
                    }
                }
            }
            if (message.NextEventNumber == -1)
            {
                _partitionStateCache.CacheAndLockPartitionState(partition, "", positionTag);
                loadCompleted();
                EnsureTickPending();
                return;
            }
            string partitionStateStreamName = MakePartitionStateStreamName(partition);

            _readRequestsInProgress++;
            _readDispatcher.Publish(
                new ClientMessage.ReadStreamEventsBackward(
                    Guid.NewGuid(), _readDispatcher.Envelope, partitionStateStreamName, message.NextEventNumber, 1,
                    resolveLinks: false),
                m => OnLoadStatePartitionCompleted(partition, committedEventReceived, m, loadCompleted));
        }
コード例 #20
0
 public void Handle(ProjectionMessage.Projections.CommittedEventReceived message)
 {
     EnsureState(
         State.Running | State.Paused | State.Stopping | State.Stopped | State.FaultedStopping | State.Faulted);
     try
     {
         if (_state == State.Running || _state == State.Paused)
         {
             CheckpointTag eventTag  = message.CheckpointTag;
             string        partition = _checkpointStrategy.StatePartitionSelector.GetStatePartition(message);
             var           committedEventWorkItem = new CommittedEventWorkItem(this, message, partition);
             _processingQueue.EnqueueTask(committedEventWorkItem, eventTag);
         }
         _processingQueue.ProcessEvent();
     }
     catch (Exception ex)
     {
         SetFaulted(ex);
     }
 }
コード例 #21
0
        private bool TrySubscribeHeadingDistributionPoint(ProjectionMessage.Projections.CommittedEventReceived message, Guid projectionId)
        {
            if (_pausedProjections.Contains(projectionId))
            {
                return(false);
            }

            var projectionSubscription = _projections[projectionId];

            if (!_headingEventDistributionPoint.TrySubscribe(
                    projectionId, projectionSubscription, projectionSubscription.MakeCheckpointTag(message)))
            {
                return(false);
            }

            Guid distributionPointId = message.CorrelationId;

            _distributionPoints[distributionPointId].Dispose();
            _distributionPoints.Remove(distributionPointId);
            _distributionPointSubscriptions.Remove(distributionPointId);
            _projectionDistributionPoints[projectionId] = Guid.Empty;
            return(true);
        }
コード例 #22
0
        public void Handle(ProjectionMessage.Projections.CommittedEventReceived message)
        {
            EnsureState(
                State.Running | State.Paused | State.Stopping | State.Stopped | State.FaultedStopping | State.Faulted);
            if (_state == State.Stopping || _state == State.Stopped || _state == State.FaultedStopping ||
                _state == State.Faulted)
            {
                return; // ignore remaining events
            }
            CheckpointTag eventTag = _checkpointStrategy.PositionTagger.MakeCheckpointTag(message);

            ValidateQueueingOrder(eventTag);
            string partition = _checkpointStrategy.StatePartitionSelector.GetStatePartition(message);

#if PROJECTIONS_ASSERTS
            if (!string.IsNullOrEmpty(partition))
            {
                int lastSequenceInParittion;
                if (_lastSequencesByPartition.TryGetValue(partition, out lastSequenceInParittion))
                {
                    if (message.EventSequenceNumber != lastSequenceInParittion + 1)
                    {
                        throw new Exception(
                                  string.Format(
                                      "Invalid event number sequence detected in parittion '{0}' Expected: {1} Received: {2}",
                                      message.EventStreamId, lastSequenceInParittion + 1, message.EventSequenceNumber));
                    }
                }
                _lastSequencesByPartition[partition] = message.EventSequenceNumber;
            }
#endif
            _pendingEvents.Enqueue(new CommittedEventWorkItem(this, message, partition, eventTag));
            if (_state == State.Running)
            {
                ProcessOneEvent();
            }
        }
コード例 #23
0
 public void Handle(ProjectionMessage.Projections.CommittedEventReceived message)
 {
     HandledMessages.Add(message);
 }
コード例 #24
0
 public override string GetStatePartition(ProjectionMessage.Projections.CommittedEventReceived @event)
 {
     return("");
 }
コード例 #25
0
 public abstract string GetStatePartition(ProjectionMessage.Projections.CommittedEventReceived @event);
コード例 #26
0
 private bool EventPassesSourceFilter(ProjectionMessage.Projections.CommittedEventReceived message)
 {
     //TODO: support category
     return(_eventFilter.PassesSource(message.ResolvedLinkTo, message.PositionStreamId));
 }
コード例 #27
0
 public virtual CheckpointTag MakeCheckpointTag(ProjectionMessage.Projections.CommittedEventReceived comittedEvent)
 {
     return(new CheckpointTag(comittedEvent.Position));
 }