Example #1
0
 Task <(StreamProcessorState, FailingPartitionState)> ChangePositionInFailingPartition(
     IStreamProcessorId streamProcessorId,
     StreamProcessorState oldState,
     PartitionId partitionId,
     StreamPosition newPosition,
     DateTimeOffset lastFailed,
     CancellationToken cancellationToken) =>
Example #2
0
        /// <inheritdoc/>
        protected override async Task <IStreamProcessorState> OnSuccessfulProcessingResult(SuccessfulProcessing successfulProcessing, StreamEvent processedEvent, IStreamProcessorState currentState)
        {
            var oldState = currentState as StreamProcessorState;
            var newState = new StreamProcessorState(processedEvent.Position + 1, oldState.FailingPartitions, DateTimeOffset.UtcNow);
            await _streamProcessorStates.Persist(Identifier, newState, CancellationToken.None).ConfigureAwait(false);

            return(newState);
        }
Example #3
0
 Task <(StreamProcessorState, FailingPartitionState)> SetFailingPartitionState(
     IStreamProcessorId streamProcessorId,
     StreamProcessorState oldState,
     PartitionId partitionId,
     uint processingAttempts,
     TimeSpan retryTimeout,
     string reason,
     StreamPosition position,
     DateTimeOffset lastFailed,
     CancellationToken cancellationToken) =>
Example #4
0
        async Task <StreamProcessorState> RemoveFailingPartition(IStreamProcessorId streamProcessorId, StreamProcessorState oldState, PartitionId partition, CancellationToken cancellationToken)
        {
            var newFailingPartitions = oldState.FailingPartitions;

            newFailingPartitions.Remove(partition);
            var newState = new StreamProcessorState(oldState.Position, newFailingPartitions, oldState.LastSuccessfullyProcessed);

            oldState.FailingPartitions.Remove(partition);

            await PersistNewState(streamProcessorId, newState, cancellationToken).ConfigureAwait(false);

            return(newState);
        }
Example #5
0
        /// <inheritdoc/>
        protected override async Task <IStreamProcessorState> ProcessEvent(StreamEvent @event, IStreamProcessorState currentState, CancellationToken cancellationToken)
        {
            var streamProcessorState = currentState as StreamProcessorState;

            if (streamProcessorState.FailingPartitions.Keys.Contains(@event.Partition))
            {
                var newState = new StreamProcessorState(@event.Position + 1, streamProcessorState.FailingPartitions, streamProcessorState.LastSuccessfullyProcessed);
                await _streamProcessorStates.Persist(Identifier, newState, CancellationToken.None).ConfigureAwait(false);

                return(newState);
            }

            return(await base.ProcessEvent(@event, streamProcessorState, cancellationToken).ConfigureAwait(false));
        }
Example #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ScopedStreamProcessor"/> class.
 /// </summary>
 /// <param name="tenantId">The <see cref="TenantId"/>.</param>
 /// <param name="streamProcessorId">The <see cref="IStreamProcessorId" />.</param>
 /// <param name="initialState">The <see cref="StreamProcessorState" />.</param>
 /// <param name="processor">An <see cref="IEventProcessor" /> to process the event.</param>
 /// <param name="streamProcessorStates">The <see cref="IResilientStreamProcessorStateRepository" />.</param>
 /// <param name="eventsFromStreamsFetcher">The<see cref="ICanFetchEventsFromStream" />.</param>
 /// <param name="failingPartitions">The <see cref="IFailingPartitions" />.</param>
 /// <param name="eventsFetcherPolicy">The <see cref="IAsyncPolicyFor{T}" /> <see cref="ICanFetchEventsFromStream" />.</param>
 /// <param name="logger">An <see cref="ILogger" /> to log messages.</param>
 public ScopedStreamProcessor(
     TenantId tenantId,
     IStreamProcessorId streamProcessorId,
     StreamProcessorState initialState,
     IEventProcessor processor,
     IResilientStreamProcessorStateRepository streamProcessorStates,
     ICanFetchEventsFromPartitionedStream eventsFromStreamsFetcher,
     IFailingPartitions failingPartitions,
     IAsyncPolicyFor <ICanFetchEventsFromStream> eventsFetcherPolicy,
     ILogger <ScopedStreamProcessor> logger)
     : base(tenantId, streamProcessorId, initialState, processor, eventsFromStreamsFetcher, eventsFetcherPolicy, logger)
 {
     _streamProcessorStates = streamProcessorStates;
     _failingPartitions     = failingPartitions;
 }
Example #7
0
        /// <inheritdoc/>
        public async Task <IStreamProcessorState> AddFailingPartitionFor(
            IStreamProcessorId streamProcessorId,
            StreamProcessorState oldState,
            StreamPosition failedPosition,
            PartitionId partition,
            DateTimeOffset retryTime,
            string reason,
            CancellationToken cancellationToken)
        {
            var failingPartition  = new FailingPartitionState(failedPosition, retryTime, reason, 1, DateTimeOffset.UtcNow);
            var failingPartitions = new Dictionary <PartitionId, FailingPartitionState>(oldState.FailingPartitions)
            {
                [partition] = failingPartition
            };
            var newState = new StreamProcessorState(failedPosition + 1, failingPartitions, oldState.LastSuccessfullyProcessed);

            await PersistNewState(streamProcessorId, newState, cancellationToken).ConfigureAwait(false);

            return(newState);
        }
Example #8
0
        /// <inheritdoc/>
        public async Task <IStreamProcessorState> CatchupFor(
            IStreamProcessorId streamProcessorId,
            StreamProcessorState streamProcessorState,
            CancellationToken cancellationToken)
        {
            if (streamProcessorState.FailingPartitions.Count > 0)
            {
                streamProcessorState = (await _streamProcessorStates.TryGetFor(streamProcessorId, cancellationToken)
                                        .ConfigureAwait(false)).Result as StreamProcessorState;
            }

            var failingPartitionsList = streamProcessorState.FailingPartitions.ToList();

            foreach (var kvp in failingPartitionsList)
            {
                var partition             = kvp.Key;
                var failingPartitionState = kvp.Value;
                if (ShouldRetryProcessing(failingPartitionState))
                {
                    while (ShouldProcessNextEventInPartition(failingPartitionState.Position, streamProcessorState.Position))
                    {
                        var tryGetEvent = await _eventsFetcherPolicy.Execute(
                            cancellationToken => _eventsFromStreamsFetcher.FetchInPartition(partition, failingPartitionState.Position, cancellationToken),
                            cancellationToken).ConfigureAwait(false);

                        if (!tryGetEvent.Success)
                        {
                            break;
                        }
                        var streamEvent = tryGetEvent.Result;
                        if (streamEvent.Partition != partition)
                        {
                            throw new StreamEventInWrongPartition(streamEvent, partition);
                        }
                        if (!ShouldProcessNextEventInPartition(streamEvent.Position, streamProcessorState.Position))
                        {
                            break;
                        }
                        if (!ShouldRetryProcessing(failingPartitionState))
                        {
                            break;
                        }

                        var processingResult = await RetryProcessingEvent(
                            failingPartitionState,
                            streamEvent.Event,
                            partition,
                            cancellationToken).ConfigureAwait(false);

                        if (processingResult.Succeeded)
                        {
                            (streamProcessorState, failingPartitionState) = await ChangePositionInFailingPartition(
                                streamProcessorId,
                                streamProcessorState,
                                partition,
                                streamEvent.Position + 1,
                                failingPartitionState.LastFailed,
                                cancellationToken).ConfigureAwait(false);
                        }
                        else if (processingResult.Retry)
                        {
                            (streamProcessorState, failingPartitionState) = await SetFailingPartitionState(
                                streamProcessorId,
                                streamProcessorState,
                                partition,
                                failingPartitionState.ProcessingAttempts + 1,
                                processingResult.RetryTimeout,
                                processingResult.FailureReason,
                                streamEvent.Position,
                                DateTimeOffset.UtcNow,
                                cancellationToken).ConfigureAwait(false);
                        }
                        else
                        {
                            (streamProcessorState, failingPartitionState) = await SetFailingPartitionState(
                                streamProcessorId,
                                streamProcessorState,
                                partition,
                                failingPartitionState.ProcessingAttempts + 1,
                                DateTimeOffset.MaxValue,
                                processingResult.FailureReason,
                                streamEvent.Position,
                                DateTimeOffset.UtcNow,
                                cancellationToken).ConfigureAwait(false);
                        }
                    }

                    if (ShouldRetryProcessing(failingPartitionState))
                    {
                        streamProcessorState = await RemoveFailingPartition(streamProcessorId, streamProcessorState, partition, cancellationToken).ConfigureAwait(false);
                    }
                }
            }

            return(streamProcessorState);
        }