예제 #1
0
        async Task <bool> Subscribe(
            IReverseCallClient <EventHorizonConsumerToProducerMessage, EventHorizonProducerToConsumerMessage, ConsumerSubscriptionRequest, Contracts.SubscriptionResponse, ConsumerRequest, ConsumerResponse> reverseCallClient,
            SubscriptionId subscriptionId,
            MicroserviceAddress microserviceAddress,
            CancellationToken cancellationToken)
        {
            _logger.Debug(
                "Tenant '{ConsumerTenantId}' is subscribing to events from tenant '{ProducerTenantId}' in microservice '{ProducerMicroserviceId}' on address '{Host}:{Port}'",
                subscriptionId.ConsumerTenantId,
                subscriptionId.ProducerTenantId,
                subscriptionId.ProducerMicroserviceId,
                microserviceAddress.Host,
                microserviceAddress.Port);
            var tryGetStreamProcessorState = await _streamProcessorStates.TryGetFor(subscriptionId, cancellationToken).ConfigureAwait(false);

            var publicEventsPosition = tryGetStreamProcessorState.Result?.Position ?? StreamPosition.Start;

            return(await reverseCallClient.Connect(
                       new ConsumerSubscriptionRequest
            {
                PartitionId = subscriptionId.PartitionId.ToProtobuf(),
                StreamId = subscriptionId.StreamId.ToProtobuf(),
                StreamPosition = publicEventsPosition.Value,
                TenantId = subscriptionId.ProducerTenantId.ToProtobuf()
            }, cancellationToken).ConfigureAwait(false));
        }
예제 #2
0
 void StartProcessingEventHorizon(
     ConsentId consentId,
     SubscriptionId subscriptionId,
     MicroserviceAddress microserviceAddress,
     IReverseCallClient <EventHorizonConsumerToProducerMessage, EventHorizonProducerToConsumerMessage, ConsumerSubscriptionRequest, Contracts.SubscriptionResponse, ConsumerRequest, ConsumerResponse> reverseCallClient)
 {
     Task.Run(async() =>
     {
         try
         {
             await ReadEventsFromEventHorizon(consentId, subscriptionId, reverseCallClient).ConfigureAwait(false);
             throw new Todo();     // TODO: This is a hack to get the policy going. Remove this when we can have policies on return values
         }
         catch (Exception ex)
         {
             _logger.Debug(ex, "Reconnecting to event horizon with subscription {subscriptionId}", subscriptionId);
             await _policy.Execute(
                 async _ =>
             {
                 reverseCallClient    = CreateClient(microserviceAddress, _cancellationToken);
                 var receivedResponse = await Subscribe(reverseCallClient, subscriptionId, microserviceAddress, _cancellationToken).ConfigureAwait(false);
                 var response         = HandleSubscriptionResponse(receivedResponse, reverseCallClient.ConnectResponse, subscriptionId);
                 if (!response.Success)
                 {
                     throw new Todo();                            // TODO: This is a hack to get the policy going. Remove this when we can have policies on return values
                 }
                 await ReadEventsFromEventHorizon(response.ConsentId, subscriptionId, reverseCallClient).ConfigureAwait(false);
                 throw new Todo();         // TODO: This is a hack to get the policy going. Remove this when we can have policies on return values
             }, _cancellationToken).ConfigureAwait(false);
         }
     });
 }
예제 #3
0
        async Task ReadEventsFromEventHorizon(
            ConsentId consentId,
            SubscriptionId subscriptionId,
            IReverseCallClient <EventHorizonConsumerToProducerMessage, EventHorizonProducerToConsumerMessage, ConsumerSubscriptionRequest, Contracts.SubscriptionResponse, ConsumerRequest, ConsumerResponse> reverseCallClient)
        {
            _logger.Information("Successfully connected event horizon with {subscriptionId}. Waiting for events to process", subscriptionId);
            var queue         = new AsyncProducerConsumerQueue <StreamEvent>();
            var eventsFetcher = new EventsFromEventHorizonFetcher(queue);

            using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_cancellationToken);
            var tasks = new List <Task>();

            try
            {
                _subscriptions.TrySubscribe(
                    consentId,
                    subscriptionId,
                    new EventProcessor(consentId, subscriptionId, _eventHorizonEventsWriter, _eventProcessorPolicy, _logger),
                    eventsFetcher,
                    linkedTokenSource.Token,
                    out var outputtedStreamProcessor);
                using var streamProcessor = outputtedStreamProcessor;
                await streamProcessor.Initialize().ConfigureAwait(false);

                tasks.Add(Task.Run(async() =>
                {
                    await reverseCallClient.Handle(
                        (request, cancellationToken) => HandleConsumerRequest(subscriptionId, queue, request, cancellationToken),
                        linkedTokenSource.Token).ConfigureAwait(false);
                    linkedTokenSource.Cancel();
                }));
                tasks.Add(streamProcessor.Start());
            }
            catch (Exception ex)
            {
                linkedTokenSource.Cancel();
                _logger.Warning(ex, "Error occurred while initializing Subscription: {subscriptionId}", subscriptionId);
                return;
            }

            var finishedTask = await Task.WhenAny(tasks).ConfigureAwait(false);

            if (!linkedTokenSource.IsCancellationRequested)
            {
                linkedTokenSource.Cancel();
            }
            if (TryGetException(tasks, out var exception))
            {
                linkedTokenSource.Cancel();
                _logger.Warning(exception, "Error occurred while processing Subscription: {subscriptionId}", subscriptionId);
            }

            await Task.WhenAll(tasks).ConfigureAwait(false);
        }
예제 #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="EventHorizonConnection" /> class.
 /// </summary>
 /// <param name="executionContext">The <see cref="ExecutionContext"/>.</param>
 /// <param name="reverseCallClient">The reverse call client.</param>
 /// <param name="metrics">The system for collecting metrics.</param>
 /// <param name="logger">The logger.</param>
 public EventHorizonConnection(
     ExecutionContext executionContext,
     IReverseCallClient <ConsumerSubscriptionRequest, Contracts.SubscriptionResponse, ConsumerRequest, ConsumerResponse> reverseCallClient,
     IMetricsCollector metrics,
     ILogger logger)
 {
     _executionContext  = executionContext;
     _reverseCallClient = reverseCallClient;
     _metrics           = metrics;
     _logger            = logger;
 }