Exemple #1
0
        /// <inheritdoc/>
        public async Task <SubscriptionResponse> HandleSubscription(SubscriptionId subscriptionId)
        {
            if (_subscriptions.TryGetConsentFor(subscriptionId, out var consentId))
            {
                _logger.Trace("Already subscribed to subscription {SubscriptionId}", subscriptionId);
                return(new SuccessfulSubscriptionResponse(consentId));
            }

            _logger.Trace("Getting microservice address");
            if (!TryGetMicroserviceAddress(subscriptionId.ProducerMicroserviceId, out var microserviceAddress))
            {
                var message = $"There is no microservice configuration for the producer microservice {subscriptionId.ProducerMicroserviceId}.";
                _logger.Warning(message);
                return(new FailedSubscriptionResponse(new Failure(SubscriptionFailures.MissingMicroserviceConfiguration, message)));
            }

            return(await _policy.Execute(
                       async _ =>
            {
                var client = CreateClient(microserviceAddress, _cancellationToken);
                var receivedResponse = await Subscribe(client, subscriptionId, microserviceAddress, _cancellationToken).ConfigureAwait(false);
                var response = HandleSubscriptionResponse(receivedResponse, client.ConnectResponse, subscriptionId);
                if (response.Success)
                {
                    StartProcessingEventHorizon(response.ConsentId, subscriptionId, microserviceAddress, client);
                }
                return response;
            }, _cancellationToken).ConfigureAwait(false));
        }
Exemple #2
0
        async Task <IProcessingResult> Process(CommittedEvent @event, CancellationToken cancellationToken)
        {
            _logger.Trace(
                "Processing Event {EventType} from Event Horizon in Scope {Scope} from Microservice {ProducerMicroservice} and Tenant {ProducerTenant}",
                @event.Type.Id,
                Scope,
                _subscriptionId.ProducerMicroserviceId,
                _subscriptionId.ProducerTenantId);

            await _policy.Execute(
                cancellationToken => _receivedEventsWriter.Write(@event, _consentId, Scope, cancellationToken),
                cancellationToken).ConfigureAwait(false);

            return(new SuccessfulProcessing());
        }
Exemple #3
0
 Task Subscribe(TenantId consumer, Subscription subscription)
 => _policy.Execute(
     async(cancellationToken) =>
 {
     _logger.Trace(
         "Attempting to subscribe to events from {Partition} in {Stream} of {ProducerTenant} in {Microservice} for {ConsumerTenant} into {Scope}",
         subscription.Partition,
         subscription.Stream,
         subscription.Tenant,
         subscription.Microservice,
         consumer,
         subscription.Scope);
     var response = await _subscriptions.Subscribe(consumer, subscription, cancellationToken).ConfigureAwait(false);
     if (!response.Success)
     {
         throw new FailedToSubscribeToEventHorizon(
             response.Failure.Reason,
             consumer,
             subscription.Microservice,
             subscription.Tenant,
             subscription.Stream,
             subscription.Partition);
     }
     else
     {
         _logger.Debug(
             "Successfully subscribed to events from {Partition} in {Stream} of {ProducerTenant} in {Microservice} for {ConsumerTenant} into {Scope} approved by {Consent}",
             subscription.Partition,
             subscription.Stream,
             subscription.Tenant,
             subscription.Microservice,
             consumer,
             subscription.Scope,
             response.Consent);
     }
 },
     CancellationToken.None);
Exemple #4
0
 /// <inheritdoc/>
 public Task Persist(IStreamProcessorId streamProcessorId, IStreamProcessorState streamProcessorState, CancellationToken cancellationToken) =>
 _policy.Execute(cancellationToken => _repository.Persist(streamProcessorId, streamProcessorState, cancellationToken), cancellationToken);
Exemple #5
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);
        }
Exemple #6
0
 /// <summary>
 /// Fetches the Event that is should be processed next.
 /// </summary>
 /// <param name="currentState">The current <see cref="IStreamProcessorState" />.</param>
 /// <param name="cancellationToken">The <see cref="CancellationToken" />.</param>
 /// <returns>A <see cref="Task" /> that, when resolved, returns the <see cref="StreamEvent" />.</returns>
 protected Task <StreamEvent> FetchNextEventToProcess(IStreamProcessorState currentState, CancellationToken cancellationToken) =>
 _fetchEventToProcessPolicy.Execute(cancellationToken => _eventsFetcher.Fetch(currentState.Position, cancellationToken), cancellationToken);