Пример #1
0
 public void UpdatePosition(EventPosition position)
 {
     if (position.PreparePosition <= _lastEventPosition.PreparePosition) // handle prepare only
         throw new InvalidOperationException(
             string.Format("Event at position {0} has been already processed", position));
     _lastEventPosition = position;
 }
Пример #2
0
 public void UpdateToZero()
 {
     var zero = new EventPosition(0, -1);
     if (_lastEventPosition != zero || _lastTag != null)
         throw new InvalidOperationException("Posistion tagger has be already updated");
     _lastTag = _positionTagger.MakeZeroCheckpointTag();
 }
 public TransactionFileReaderEventDistributionPoint(
     IPublisher publisher, Guid distibutionPointCorrelationId, EventPosition from)
     : base(publisher, distibutionPointCorrelationId)
 {
     if (publisher == null) throw new ArgumentNullException("publisher");
     _from = @from;
 }
 public CommittedEventDistributed(
     Guid correlationId, EventPosition position, string eventStreamId, int eventSequenceNumber,
     bool resolvedLinkTo, Event data)
     : this(correlationId, position, eventStreamId, eventSequenceNumber, eventStreamId, eventSequenceNumber,
         resolvedLinkTo, data, position.PreparePosition, 11.1f)
 {
 }
 public TransactionFileEventReader(IPublisher publisher, Guid distibutionPointCorrelationId, EventPosition @from, ITimeProvider timeProvider, bool stopOnEof = false, bool deliverEndOfTFPosition = true)
     : base(publisher, distibutionPointCorrelationId, stopOnEof)
 {
     if (publisher == null) throw new ArgumentNullException("publisher");
     _from = @from;
     _deliverEndOfTfPosition = deliverEndOfTFPosition;
     _timeProvider = timeProvider;
 }
 public TransactionFileReaderEventDistributionPoint(
     IPublisher publisher, Guid distibutionPointCorrelationId, EventPosition from, bool deliverEndOfTFPosition = true)
     : base(publisher, distibutionPointCorrelationId)
 {
     if (publisher == null) throw new ArgumentNullException("publisher");
     _from = @from;
     _deliverEndOfTfPosition = deliverEndOfTFPosition;
 }
Пример #7
0
        public bool ProcessEvent(
            EventPosition position, CheckpointTag eventPosition, string streamId, string eventType, string category1, Guid eventId,
            int sequenceNumber, string metadata, string data, out string newState, out EmittedEvent[] emittedEvents)
        {
            emittedEvents = null;
            newState = null;
            if (sequenceNumber != 0)
                return false; // not our event

            emittedEvents = new[] { new EmittedEvent(SystemStreams.StreamsStream, Guid.NewGuid(), SystemEventTypes.LinkTo, sequenceNumber + "@" + streamId, eventPosition, expectedTag: null) };

            return true;
        }
Пример #8
0
        public bool ProcessEvent(
            EventPosition position, string streamId, string eventType, string category1, Guid eventId,
            int sequenceNumber, string metadata, string data, out string newState, out EmittedEvent[] emittedEvents)
        {
            emittedEvents = null;
            newState = null;
            if (sequenceNumber != 0)
                return false; // not our event

            emittedEvents = new[]
                {new EmittedEvent("$streams", Guid.NewGuid(), "$>", sequenceNumber + "@" + streamId)};

            return true;
        }
 //NOTE: committed event with null event _data means - end of the source reached.
 // Current last available TF commit position is in _position.CommitPosition
 // TODO: separate message?
 public CommittedEventDistributed(
     Guid correlationId, EventPosition position, string positionStreamId, int positionSequenceNumber,
     string eventStreamId, int eventSequenceNumber, bool resolvedLinkTo, Event data,
     long? safeTransactionFileReaderJoinPosition, float progress)
 {
     _correlationId = correlationId;
     _data = data;
     _safeTransactionFileReaderJoinPosition = safeTransactionFileReaderJoinPosition;
     _progress = progress;
     _position = position;
     _positionStreamId = positionStreamId;
     _positionSequenceNumber = positionSequenceNumber;
     _eventStreamId = eventStreamId;
     _eventSequenceNumber = eventSequenceNumber;
     _resolvedLinkTo = resolvedLinkTo;
 }
        public bool ProcessEvent(
            EventPosition position, string streamId, string eventType, string category1, Guid eventId,
            int sequenceNumber, string metadata, string data, out string newState, out EmittedEvent[] emittedEvents)
        {
            emittedEvents = null;
            newState = null;
            if (sequenceNumber != 0)
                return false; // not our event
            var lastSlashPos = streamId.LastIndexOf(_separator);
            if (lastSlashPos < 0)
                return true; // handled but not interesting to us

            var category = streamId.Substring(0, lastSlashPos);

            emittedEvents = new[]
                {new EmittedEvent("$category" + _separator + category, Guid.NewGuid(), "StreamCreated", streamId)};

            return true;
        }
Пример #11
0
        public bool ProcessEvent(
            EventPosition position, CheckpointTag eventPosition, string streamId, string eventType, string category1,
            Guid eventId, int sequenceNumber, string metadata, string data, out string newState,
            out EmittedEvent[] emittedEvents)
        {
            emittedEvents = null;
            newState = null;
            if (streamId.StartsWith(_indexStreamPrefix))
                return false;
            if (eventType == "$>")
                return false;

            emittedEvents = new[]
                {
                    new EmittedEvent(
                        _indexStreamPrefix + eventType, Guid.NewGuid(), "$>", sequenceNumber + "@" + streamId,
                        eventPosition, expectedTag: null)
                };

            return true;
        }
Пример #12
0
        public ProjectionSubscription(
            Guid projectionCorrelationId, CheckpointTag from,
            IHandle<ProjectionMessage.Projections.CommittedEventReceived> eventHandler,
            IHandle<ProjectionMessage.Projections.CheckpointSuggested> checkpointHandler,
            CheckpointStrategy checkpointStrategy, long? checkpointUnhandledBytesThreshold)
        {
            if (eventHandler == null) throw new ArgumentNullException("eventHandler");
            if (checkpointHandler == null) throw new ArgumentNullException("checkpointHandler");
            if (checkpointStrategy == null) throw new ArgumentNullException("checkpointStrategy");
            _eventHandler = eventHandler;
            _checkpointHandler = checkpointHandler;
            _checkpointStrategy = checkpointStrategy;
            _checkpointUnhandledBytesThreshold = checkpointUnhandledBytesThreshold;
            _projectionCorrelationId = projectionCorrelationId;
            _lastPassedOrCheckpointedEventPosition = from.Position;

            _eventFilter = checkpointStrategy.EventFilter;

            _positionTagger = checkpointStrategy.PositionTagger;
            _positionTracker = new PositionTracker(_positionTagger);
            _positionTracker.UpdateByCheckpointTagInitial(from);
        }
Пример #13
0
        /// <summary>
        ///   Receives a batch of <see cref="EventData" /> from the Event Hub partition.
        /// </summary>
        ///
        /// <param name="maximumMessageCount">The maximum number of messages to receive in this batch.</param>
        /// <param name="maximumWaitTime">The maximum amount of time to wait to build up the requested message count for the batch; if not specified, the per-try timeout specified by the retry policy will be used.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        /// <returns>The batch of <see cref="EventData" /> from the Event Hub partition this consumer is associated with.  If no events are present, an empty set is returned.</returns>
        ///
        public override async Task <IReadOnlyList <EventData> > ReceiveAsync(int maximumMessageCount,
                                                                             TimeSpan?maximumWaitTime,
                                                                             CancellationToken cancellationToken)
        {
            Argument.AssertNotClosed(_closed, nameof(AmqpConsumer));
            Argument.AssertAtLeast(maximumMessageCount, 1, nameof(maximumMessageCount));

            var receivedEventCount = 0;
            var failedAttemptCount = 0;
            var tryTimeout         = RetryPolicy.CalculateTryTimeout(0);
            var waitTime           = (maximumWaitTime ?? tryTimeout);
            var link              = default(ReceivingAmqpLink);
            var retryDelay        = default(TimeSpan?);
            var amqpMessages      = default(IEnumerable <AmqpMessage>);
            var receivedEvents    = default(List <EventData>);
            var lastReceivedEvent = default(EventData);

            var stopWatch = ValueStopwatch.StartNew();

            try
            {
                while ((!cancellationToken.IsCancellationRequested) && (!_closed))
                {
                    try
                    {
                        // Creation of the link happens without explicit knowledge of the cancellation token
                        // used for this operation; validate the token state before attempting link creation and
                        // again after the operation completes to provide best efforts in respecting it.

                        EventHubsEventSource.Log.EventReceiveStart(EventHubName, ConsumerGroup, PartitionId);
                        cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                        link = await ReceiveLink.GetOrCreateAsync(UseMinimum(ConnectionScope.SessionTimeout, tryTimeout)).ConfigureAwait(false);

                        cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                        var messagesReceived = await Task.Factory.FromAsync
                                               (
                            (callback, state) => link.BeginReceiveMessages(maximumMessageCount, waitTime, callback, state),
                            (asyncResult) => link.EndReceiveMessages(asyncResult, out amqpMessages),
                            TaskCreationOptions.RunContinuationsAsynchronously
                                               ).ConfigureAwait(false);

                        cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                        // If event messages were received, then package them for consumption and
                        // return them.

                        if ((messagesReceived) && (amqpMessages != null))
                        {
                            receivedEvents ??= new List <EventData>();

                            foreach (AmqpMessage message in amqpMessages)
                            {
                                link.DisposeDelivery(message, true, AmqpConstants.AcceptedOutcome);
                                receivedEvents.Add(MessageConverter.CreateEventFromMessage(message));
                                message.Dispose();
                            }

                            receivedEventCount = receivedEvents.Count;

                            if (receivedEventCount > 0)
                            {
                                lastReceivedEvent = receivedEvents[receivedEventCount - 1];

                                if (lastReceivedEvent.Offset > long.MinValue)
                                {
                                    CurrentEventPosition = EventPosition.FromOffset(lastReceivedEvent.Offset, false);
                                }

                                if (TrackLastEnqueuedEventProperties)
                                {
                                    LastReceivedEvent = lastReceivedEvent;
                                }
                            }

                            return(receivedEvents);
                        }

                        // No events were available.

                        return(EmptyEventSet);
                    }
                    catch (EventHubsException ex) when(ex.Reason == EventHubsException.FailureReason.ServiceTimeout)
                    {
                        // Because the timeout specified with the request is intended to be the maximum
                        // amount of time to wait for events, a timeout isn't considered an error condition,
                        // rather a sign that no events were available in the requested period.

                        return(EmptyEventSet);
                    }
                    catch (Exception ex)
                    {
                        Exception activeEx = ex.TranslateServiceException(EventHubName);

                        // Determine if there should be a retry for the next attempt; if so enforce the delay but do not quit the loop.
                        // Otherwise, bubble the exception.

                        ++failedAttemptCount;
                        retryDelay = RetryPolicy.CalculateRetryDelay(activeEx, failedAttemptCount);

                        if ((retryDelay.HasValue) && (!ConnectionScope.IsDisposed) && (!cancellationToken.IsCancellationRequested))
                        {
                            EventHubsEventSource.Log.EventReceiveError(EventHubName, ConsumerGroup, PartitionId, activeEx.Message);
                            await Task.Delay(UseMinimum(retryDelay.Value, waitTime.CalculateRemaining(stopWatch.GetElapsedTime())), cancellationToken).ConfigureAwait(false);

                            tryTimeout = RetryPolicy.CalculateTryTimeout(failedAttemptCount);
                        }
                        else if (ex is AmqpException)
                        {
                            ExceptionDispatchInfo.Capture(activeEx).Throw();
                        }
                        else
                        {
                            throw;
                        }
                    }
                }

                // If no value has been returned nor exception thrown by this point,
                // then cancellation has been requested.

                throw new TaskCanceledException();
            }
            catch (TaskCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                EventHubsEventSource.Log.EventReceiveError(EventHubName, ConsumerGroup, PartitionId, ex.Message);
                throw;
            }
            finally
            {
                EventHubsEventSource.Log.EventReceiveComplete(EventHubName, ConsumerGroup, PartitionId, receivedEventCount);
            }
        }
Пример #14
0
        public async Task ReceiverIdentifier()
        {
            await using (var scope = await EventHubScope.CreateAsync(2))
            {
                var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName);
                var ehClient         = EventHubClient.CreateFromConnectionString(connectionString);
                var receivers        = new List <PartitionReceiver>();

                try
                {
                    for (int i = 0; i < 5; i++)
                    {
                        TestUtility.Log($"Creating receiver {i}");
                        var newReceiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, "1", EventPosition.FromStart(),
                                                                  new ReceiverOptions()
                        {
                            Identifier = $"receiver{i}"
                        });

                        // Issue a receive call so link will become active.
                        await newReceiver.ReceiveAsync(10);

                        receivers.Add(newReceiver);
                    }

                    try
                    {
                        // Attempt to create 6th receiver. This should fail.
                        var failReceiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, "1", EventPosition.FromStart());
                        await failReceiver.ReceiveAsync(10);

                        throw new InvalidOperationException("6th receiver should have encountered QuotaExceededException.");
                    }
                    catch (QuotaExceededException ex)
                    {
                        TestUtility.Log($"Received expected exception {ex.GetType()}: {ex.Message}");
                        foreach (var receiver in receivers)
                        {
                            Assert.True(ex.Message.Contains(receiver.Identifier), $"QuotaExceededException message is missing receiver identifier '{receiver.Identifier}'");
                        }
                    }
                }
                finally
                {
                    // Close all receivers.
                    foreach (var receiver in receivers)
                    {
                        await Task.WhenAll(
                            receiver.CloseAsync(),
                            ehClient.CloseAsync());
                    }
                }
            }
        }
Пример #15
0
        public bool CanJoinAt(EventPosition firstAvailableTransactionFileEvent, CheckpointTag eventCheckpointTag)
        {
            //NOTE: here the committed event MUST pass the projection subscription source filter as it was sent to us by specialized event
            // distribution point.  MakeCheckpointTag fails otherwise.

            var result = _checkpointStrategy.IsCheckpointTagAfterEventPosition(
                eventCheckpointTag, firstAvailableTransactionFileEvent);

            if (result)
                _logger.Trace(
                    "Projection subscription '{0}' can join distribution at '{1}' when the first available event is '{2}'",
                    _projectionCorrelationId, eventCheckpointTag, firstAvailableTransactionFileEvent);

            return result;
        }
Пример #16
0
 public IPartitionReceiver CreateEpochReceiver(string consumerGroupName, string partitionId, EventPosition eventPosition, string offset, long epoch, ReceiverOptions receiverOptions)
 {
     return(new PartitionReceiverWrapper(this.inner.CreateEpochReceiver(consumerGroupName, partitionId, eventPosition, epoch, receiverOptions)));
 }
Пример #17
0
        async Task PartitionKeyValidation()
        {
            int NumberOfMessagesToSend = 100;
            var partitionOffsets       = new Dictionary <string, string>();

            // Discover the end of stream on each partition.
            TestUtility.Log("Discovering end of stream on each partition.");
            foreach (var partitionId in this.PartitionIds)
            {
                var lastEvent = await this.EventHubClient.GetPartitionRuntimeInformationAsync(partitionId);

                partitionOffsets.Add(partitionId, lastEvent.LastEnqueuedOffset);
                TestUtility.Log($"Partition {partitionId} has last message with offset {lastEvent.LastEnqueuedOffset}");
            }

            // Now send a set of messages with different partition keys.
            TestUtility.Log($"Sending {NumberOfMessagesToSend} messages.");
            Random rnd = new Random();

            for (int i = 0; i < NumberOfMessagesToSend; i++)
            {
                var partitionKey = rnd.Next(10);
                await this.EventHubClient.SendAsync(new EventData(Encoding.UTF8.GetBytes("Hello EventHub!")), partitionKey.ToString());
            }

            // It is time to receive all messages that we just sent.
            // Prepare partition key to partition map while receiving.
            // Validation: All messages of a partition key should be received from a single partition.
            TestUtility.Log("Starting to receive all messages from each partition.");
            var receiveTasks = new Dictionary <string, Task <List <EventData> > >();
            var receivers    = new List <PartitionReceiver>();

            foreach (var partitionId in this.PartitionIds)
            {
                var receiver = this.EventHubClient.CreateReceiver(
                    PartitionReceiver.DefaultConsumerGroupName,
                    partitionId,
                    EventPosition.FromOffset(partitionOffsets[partitionId]));

                receivers.Add(receiver);
                receiveTasks.Add(partitionId, ReceiveAllMessages(receiver));
            }

            int totalReceived = 0;
            var partitionMap  = new Dictionary <string, string>();

            try
            {
                foreach (var receiveTask in receiveTasks)
                {
                    var partitionId           = receiveTask.Key;
                    var messagesFromPartition = await receiveTask.Value;
                    totalReceived += messagesFromPartition.Count;

                    TestUtility.Log($"Received {messagesFromPartition.Count} messages from partition {partitionId}.");
                    foreach (var ed in messagesFromPartition)
                    {
                        var pk = ed.SystemProperties.PartitionKey;
                        if (partitionMap.ContainsKey(pk) && partitionMap[pk] != partitionId)
                        {
                            throw new Exception($"Received a message from partition {partitionId} with partition key {pk}, whereas the same key was observed on partition {partitionMap[pk]} before.");
                        }

                        partitionMap[pk] = partitionId;
                    }
                }
            }
            finally
            {
                foreach (var receiver in receivers)
                {
                    await receiver.CloseAsync();
                }
            }

            Assert.True(totalReceived == NumberOfMessagesToSend,
                        $"Didn't receive the same number of messages that we sent. Sent: {NumberOfMessagesToSend}, Received: {totalReceived}");
        }
Пример #18
0
        public async Task SendAndReceive()
        {
            string targetPartitionId = "0";

            TestUtility.Log("Creating Event Hub client");
            await using (var scope = await EventHubScope.CreateAsync(1))
            {
                var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName);
                var ehClient         = EventHubClient.CreateFromConnectionString(GetWebSocketConnectionString(connectionString));

                PartitionSender sender = null;
                try
                {
                    // Send single message
                    TestUtility.Log("Sending single event");
                    sender = ehClient.CreatePartitionSender(targetPartitionId);
                    var eventData = new EventData(Encoding.UTF8.GetBytes("This event will be transported via web-sockets"));
                    await sender.SendAsync(eventData);
                }
                finally
                {
                    await sender?.CloseAsync();
                }

                PartitionReceiver receiver = null;
                try
                {
                    // Receive single message.
                    TestUtility.Log("Receiving single event");
                    receiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, targetPartitionId, EventPosition.FromStart());
                    var msg = await receiver.ReceiveAsync(1);

                    Assert.True(msg != null, $"Failed to receive single event from partition {targetPartitionId}");
                }
                finally
                {
                    await receiver?.CloseAsync();
                }
            }
        }
 public RequiresEventPosition(EventPosition eventPosition)
 {
     _eventPosition = eventPosition;
     _eventService = ObjectFactory.GetInstance<IEventService>();
 }
Пример #20
0
        public async Task SendBatchWithPartitionKey()
        {
            string targetPartitionKey = "this is the partition key";

            var ehClient = EventHubClient.CreateFromConnectionString(TestUtility.EventHubsConnectionString);
            var receiver = default(PartitionReceiver);

            try
            {
                // Mark end of each partition so that we can start reading from there.
                var partitionIds = await this.GetPartitionsAsync(ehClient);

                var partitions = await TestUtility.DiscoverEndOfStreamForPartitionsAsync(ehClient, partitionIds);

                // Send a batch of 2 messages.
                using (var eventData1 = new EventData(Guid.NewGuid().ToByteArray()))
                    using (var eventData2 = new EventData(Guid.NewGuid().ToByteArray()))
                    {
                        await ehClient.SendAsync(new[] { eventData1, eventData2 }, targetPartitionKey);
                    }

                // Now find out the partition where our messages landed.
                var targetPartition = "";
                foreach (var pId in partitionIds)
                {
                    var pInfo = await ehClient.GetPartitionRuntimeInformationAsync(pId);

                    if (pInfo.LastEnqueuedOffset != partitions[pId])
                    {
                        targetPartition = pId;
                        TestUtility.Log($"Batch landed on partition {targetPartition}");
                    }
                }

                // Confirm that we identified the partition with our messages.
                Assert.True(targetPartition != "", "None of the partition offsets moved.");

                // Receive all messages from target partition.
                receiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, targetPartition, EventPosition.FromOffset(partitions[targetPartition]));
                var messages = await ReceiveAllMessagesAsync(receiver);

                // Validate 2 messages received.
                Assert.True(messages.Count == 2, $"Received {messages.Count} messages instead of 2.");

                // Validate both messages carry correct partition id.
                Assert.True(messages[0].SystemProperties.PartitionKey == targetPartitionKey,
                            $"First message returned partition key value '{messages[0].SystemProperties.PartitionKey}'");
                Assert.True(messages[1].SystemProperties.PartitionKey == targetPartitionKey,
                            $"Second message returned partition key value '{messages[1].SystemProperties.PartitionKey}'");
            }
            finally
            {
                await Task.WhenAll(
                    receiver?.CloseAsync(),
                    ehClient.CloseAsync());
            }
        }
Пример #21
0
            public override EventHubWrappers.IPartitionReceiver CreateEpochReceiver(string consumerGroupName, string partitionId, EventPosition eventPosition, long epoch, ReceiverOptions receiverOptions)
            {
                long startSeq = CalculateStartSeq(eventPosition);

                return(new TimeoutPartitionReceiverMock(partitionId, startSeq, this.token, this.csb.OperationTimeout));
            }
        public bool ProcessEvent(
            EventPosition position, CheckpointTag eventPosition, string streamId, string eventType, string category1, Guid eventId, int sequenceNumber, string metadata,
            string data, out string newState, out EmittedEvent[] emittedEvents)
        {
            emittedEvents = null;
            newState = null;
            if (streamId.StartsWith(_categoryStreamPrefix))
                return false;
            var lastSlashPos = streamId.LastIndexOf(_separator);
            if (lastSlashPos < 0)
                return true; // handled but not interesting to us

            var category = streamId.Substring(0, lastSlashPos);

            emittedEvents = new[]
                {
                    new EmittedEvent(
                        _categoryStreamPrefix + category, Guid.NewGuid(), "$>", sequenceNumber + "@" + streamId, eventPosition, expectedTag: null)
                };

            return true;
        }
Пример #23
0
 public void UpdateByCheckpointTag(CheckpointTag checkpointTag)
 {
     var zero = new EventPosition(0, -1);
     if (_lastEventPosition != zero || _lastTag != null)
         throw new InvalidOperationException("Posistion tagger has be already updated");
     _lastEventPosition = checkpointTag.Position;
     _lastTag = checkpointTag;
 }
Пример #24
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));
                }
            }
        }
        public override void Handle(ClientMessage.ReadAllEventsForwardCompleted message)
        {
            if (_disposed)
                return;
            if (!_eventsRequested)
                throw new InvalidOperationException("Read events has not been requested");
            if (_paused)
                throw new InvalidOperationException("Paused");
            _eventsRequested = false;

            if (message.Result.Events.Length == 0)
            {
                // the end
                if (_deliverEndOfTfPosition)
                    DeliverLastCommitPosition(_from);
                // allow joining heading distribution
                SendIdle();
                SendEof();
            }
            else
            {
                for (int index = 0; index < message.Result.Events.Length; index++)
                {
                    var @event = message.Result.Events[index];
                    DeliverEvent(@event, message.Result.TfEofPosition);
                }
                _from = message.Result.NextPos;
            }

            if (_disposed)
                return;

            if (_pauseRequested)
                _paused = true;
            else if (message.Result.Events.Length == 0)
                RequestEvents(delay: true);
            else
                _publisher.Publish(CreateTickMessage());

        }
Пример #26
0
        public bool ProcessEvent(
            EventPosition position, CheckpointTag eventPosition, string streamId, string eventType, string category, Guid eventId, int sequenceNumber,
            string metadata, string data, out string newState, out EmittedEvent[] emittedEvents)
        {
            if (_failOnProcessEvent)
            {
                throw new Exception("PROCESS_EVENT_FAILED");
            }
            _lastProcessedStreamId       = streamId;
            _lastProcessedEventType      = eventType;
            _lastProcessedEventId        = eventId;
            _lastProcessedSequencenumber = sequenceNumber;
            _lastProcessedMetadata       = metadata;
            _lastProcessedData           = data;

            _eventsProcessed++;
            switch (eventType)
            {
            case "skip_this_type":
                _loadedState  = newState = null;
                emittedEvents = null;
                return(false);

            case "handle_this_type":
                _loadedState  = newState = data;
                emittedEvents = null;
                return(true);

            case "append":
                _loadedState  = newState = _loadedState + data;
                emittedEvents = null;
                return(true);

            case "no_state_emit1_type":
                _loadedState  = newState = "";
                emittedEvents = new[]
                { new EmittedEvent(_emit1StreamId, Guid.NewGuid(), _emit1EventType, _emit1Data, eventPosition, null), };
                return(true);

            case "emit1_type":
                _loadedState  = newState = data;
                emittedEvents = new[] { new EmittedEvent(_emit1StreamId, Guid.NewGuid(), _emit1EventType, _emit1Data, eventPosition, null), };
                return(true);

            case "emit22_type":
                _loadedState  = newState = data;
                emittedEvents = new[]
                {
                    new EmittedEvent(_emit2StreamId, Guid.NewGuid(), _emit2EventType, _emit1Data, eventPosition, null),
                    new EmittedEvent(_emit2StreamId, Guid.NewGuid(), _emit2EventType, _emit2Data, eventPosition, null),
                };
                return(true);

            case "emit212_type":
                _loadedState  = newState = data;
                emittedEvents = new[]
                {
                    new EmittedEvent(_emit2StreamId, Guid.NewGuid(), _emit2EventType, _emit1Data, eventPosition, null),
                    new EmittedEvent(_emit1StreamId, Guid.NewGuid(), _emit1EventType, _emit2Data, eventPosition, null),
                    new EmittedEvent(_emit2StreamId, Guid.NewGuid(), _emit2EventType, _emit3Data, eventPosition, null),
                };
                return(true);

            case "emit12_type":
                _loadedState  = newState = data;
                emittedEvents = new[]
                {
                    new EmittedEvent(_emit1StreamId, Guid.NewGuid(), _emit1EventType, _emit1Data, eventPosition, null),
                    new EmittedEvent(_emit2StreamId, Guid.NewGuid(), _emit2EventType, _emit2Data, eventPosition, null),
                };
                return(true);

            default:
                throw new NotSupportedException();
            }
        }
Пример #27
0
 public void ConstructorRequiresTheConnectionScope()
 {
     Assert.That(() => new AmqpEventHubConsumer("theMostAwesomeHubEvar", "$DEFAULT", "0", EventPosition.FromSequenceNumber(123), new EventHubConsumerOptions(), null, Mock.Of <AmqpMessageConverter>(), Mock.Of <EventHubRetryPolicy>(), null), Throws.ArgumentNullException);
 }
Пример #28
0
        private static async Task MainAsync()
        {
            Console.WriteLine("Connecting to event hub...");
            var eventHubClient =
                EventHubClient.CreateFromConnectionString(connectionString);

            var runtimeInformation = await eventHubClient.GetRuntimeInformationAsync();

            var partitionReceivers = runtimeInformation.PartitionIds.Select(partitionId =>
                                                                            eventHubClient.CreateReceiver("wired_brain_coffee_console_direct", partitionId, EventPosition.FromStart())).ToList();

            Console.WriteLine("Waiting for incoming events...");

            foreach (var partitionReceiver in partitionReceivers)
            {
                partitionReceiver.SetReceiveHandler(
                    new WiredBrainCoffeePartitionReceiveHandler(partitionReceiver.PartitionId));
            }

            Console.WriteLine($"Press any key to shut down");
            Console.ReadLine();
            await eventHubClient.CloseAsync();
        }
        /// <summary>
        ///   Retrieves a list of all the checkpoints in a data store for a given namespace, Event Hub and consumer group.
        /// </summary>
        ///
        /// <param name="fullyQualifiedNamespace">The fully qualified Event Hubs namespace the ownership are associated with.  This is likely to be similar to <c>{yournamespace}.servicebus.windows.net</c>.</param>
        /// <param name="eventHubName">The name of the specific Event Hub the ownership are associated with, relative to the Event Hubs namespace that contains it.</param>
        /// <param name="consumerGroup">The name of the consumer group the ownership are associated with.</param>
        /// <param name="cancellationToken">A <see cref="CancellationToken" /> instance to signal the request to cancel the operation.</param>
        ///
        /// <returns>An enumerable containing all the existing checkpoints for the associated Event Hub and consumer group.</returns>
        ///
        public override async Task <IEnumerable <EventProcessorCheckpoint> > ListCheckpointsAsync(string fullyQualifiedNamespace,
                                                                                                  string eventHubName,
                                                                                                  string consumerGroup,
                                                                                                  CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();
            ListCheckpointsStart(fullyQualifiedNamespace, eventHubName, consumerGroup);

            async Task <List <EventProcessorCheckpoint> > listCheckpointsAsync(CancellationToken listCheckpointsToken)
            {
                var prefix      = string.Format(CultureInfo.InvariantCulture, CheckpointPrefix, fullyQualifiedNamespace.ToLowerInvariant(), eventHubName.ToLowerInvariant(), consumerGroup.ToLowerInvariant());
                var checkpoints = new List <EventProcessorCheckpoint>();

                await foreach (BlobItem blob in ContainerClient.GetBlobsAsync(traits: BlobTraits.Metadata, prefix: prefix, cancellationToken: listCheckpointsToken).ConfigureAwait(false))
                {
                    var partitionId      = blob.Name.Substring(prefix.Length);
                    var startingPosition = default(EventPosition?);
                    var offset           = default(long?);
                    var sequenceNumber   = default(long?);

                    if (blob.Metadata.TryGetValue(BlobMetadataKey.Offset, out var str) && long.TryParse(str, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
                    {
                        offset           = result;
                        startingPosition = EventPosition.FromOffset(result, false);
                    }
                    else if (blob.Metadata.TryGetValue(BlobMetadataKey.SequenceNumber, out str) && long.TryParse(str, NumberStyles.Integer, CultureInfo.InvariantCulture, out result))
                    {
                        sequenceNumber   = result;
                        startingPosition = EventPosition.FromSequenceNumber(result, false);
                    }

                    // If either the offset or the sequence number was not populated,
                    // this is not a valid checkpoint.

                    if (startingPosition.HasValue)
                    {
                        checkpoints.Add(new BlobStorageCheckpoint
                        {
                            FullyQualifiedNamespace = fullyQualifiedNamespace,
                            EventHubName            = eventHubName,
                            ConsumerGroup           = consumerGroup,
                            PartitionId             = partitionId,
                            StartingPosition        = startingPosition.Value,
                            Offset         = offset,
                            SequenceNumber = sequenceNumber
                        });
                    }
                    else
                    {
                        InvalidCheckpointFound(partitionId, fullyQualifiedNamespace, eventHubName, consumerGroup);
                    }
                }

                return(checkpoints);
            };

            async Task <List <EventProcessorCheckpoint> > listLegacyCheckpointsAsync(List <EventProcessorCheckpoint> existingCheckpoints, CancellationToken listCheckpointsToken)
            {
                // Legacy checkpoints are not normalized to lowercase
                var legacyPrefix = string.Format(CultureInfo.InvariantCulture, LegacyCheckpointPrefix, fullyQualifiedNamespace, eventHubName, consumerGroup);
                var checkpoints  = new List <EventProcessorCheckpoint>();

                await foreach (BlobItem blob in ContainerClient.GetBlobsAsync(prefix: legacyPrefix, cancellationToken: listCheckpointsToken).ConfigureAwait(false))
                {
                    // Skip new checkpoints and empty blobs
                    if (blob.Properties.ContentLength == 0)
                    {
                        continue;
                    }

                    var partitionId = blob.Name.Substring(legacyPrefix.Length);

                    // Check whether there is already a checkpoint for this partition id
                    if (existingCheckpoints.Any(existingCheckpoint => string.Equals(existingCheckpoint.PartitionId, partitionId, StringComparison.Ordinal)))
                    {
                        continue;
                    }

                    var startingPosition = default(EventPosition?);

                    BlobBaseClient blobClient = ContainerClient.GetBlobClient(blob.Name);
                    using var memoryStream = new MemoryStream();
                    await blobClient.DownloadToAsync(memoryStream, listCheckpointsToken).ConfigureAwait(false);

                    TryReadLegacyCheckpoint(
                        memoryStream.GetBuffer().AsSpan(0, (int)memoryStream.Length),
                        out long?offset,
                        out long?sequenceNumber);

                    if (offset.HasValue)
                    {
                        startingPosition = EventPosition.FromOffset(offset.Value, false);
                    }
                    else if (sequenceNumber.HasValue)
                    {
                        startingPosition = EventPosition.FromSequenceNumber(sequenceNumber.Value, false);
                    }

                    if (startingPosition.HasValue)
                    {
                        checkpoints.Add(new BlobStorageCheckpoint
                        {
                            FullyQualifiedNamespace = fullyQualifiedNamespace,
                            EventHubName            = eventHubName,
                            ConsumerGroup           = consumerGroup,
                            PartitionId             = partitionId,
                            StartingPosition        = startingPosition.Value,
                            Offset         = offset,
                            SequenceNumber = sequenceNumber
                        });
                    }
                    else
                    {
                        InvalidCheckpointFound(partitionId, fullyQualifiedNamespace, eventHubName, consumerGroup);
                    }
                }

                return(checkpoints);
            };

            List <EventProcessorCheckpoint> checkpoints = null;

            try
            {
                checkpoints = await ApplyRetryPolicy(listCheckpointsAsync, cancellationToken).ConfigureAwait(false);

                if (InitializeWithLegacyCheckpoints)
                {
                    checkpoints.AddRange(await ApplyRetryPolicy(ct => listLegacyCheckpointsAsync(checkpoints, ct), cancellationToken).ConfigureAwait(false));
                }
                return(checkpoints);
            }
            catch (RequestFailedException ex) when(ex.ErrorCode == BlobErrorCode.ContainerNotFound)
            {
                ListCheckpointsError(fullyQualifiedNamespace, eventHubName, consumerGroup, ex);
                throw new RequestFailedException(BlobsResourceDoesNotExist);
            }
            catch (Exception ex)
            {
                ListCheckpointsError(fullyQualifiedNamespace, eventHubName, consumerGroup, ex);
                throw;
            }
            finally
            {
                ListCheckpointsComplete(fullyQualifiedNamespace, eventHubName, consumerGroup, checkpoints?.Count ?? 0);
            }
        }
Пример #30
0
        public async Task InvalidProxy()
        {
            // Send call should fail.
            await Assert.ThrowsAsync <WebSocketException>(async() =>
            {
                await using (var scope = await EventHubScope.CreateAsync(2))
                {
                    var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName);
                    var ehClient         = EventHubClient.CreateFromConnectionString(GetWebSocketConnectionString(connectionString));
                    ehClient.WebProxy    = new WebProxy("http://1.2.3.4:9999");
                    var edToFail         = new EventData(Encoding.UTF8.GetBytes("This is a sample event."));
                    await ehClient.SendAsync(edToFail);
                }
            });



            // Receive call should fail.
            await Assert.ThrowsAsync <WebSocketException>(async() =>
            {
                await using (var scope = await EventHubScope.CreateAsync(2))
                {
                    var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName);
                    var ehClient         = EventHubClient.CreateFromConnectionString(GetWebSocketConnectionString(connectionString));
                    ehClient.WebProxy    = new WebProxy("http://1.2.3.4:9999");
                    await ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, "0", EventPosition.FromStart()).ReceiveAsync(1);
                }
            });



            // Management link call should fail.
            await Assert.ThrowsAsync <WebSocketException>(async() =>
            {
                await using (var scope = await EventHubScope.CreateAsync(2))
                {
                    var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName);
                    var ehClient         = EventHubClient.CreateFromConnectionString(GetWebSocketConnectionString(connectionString));
                    ehClient.WebProxy    = new WebProxy("http://1.2.3.4:9999");
                    await ehClient.GetRuntimeInformationAsync();
                }
            });



            // Send/receive should work fine w/o proxy.
            await using (var scope = await EventHubScope.CreateAsync(2))
            {
                var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName);
                var ehNoProxyClient  = EventHubClient.CreateFromConnectionString(GetWebSocketConnectionString(connectionString));
                var eventData        = new EventData(Encoding.UTF8.GetBytes("This is a sample event."));
            }
        }
        private void DeliverEvent(ResolvedEventRecord @event, long lastCommitPosition)
        {
            EventRecord positionEvent = (@event.Link ?? @event.Event);
            var receivedPosition = new EventPosition(@event.CommitPosition, positionEvent.LogPosition);
            if (_from > receivedPosition)
                throw new Exception(
                    string.Format(
                        "ReadFromTF returned events in incorrect order.  Last known position is: {0}.  Received position is: {1}",
                        _from, receivedPosition));

            _publisher.Publish(
                new ProjectionCoreServiceMessage.CommittedEventDistributed(
                    _distibutionPointCorrelationId, receivedPosition, positionEvent.EventStreamId,
                    positionEvent.EventNumber, @event.Event.EventStreamId, @event.Event.EventNumber, @event.Link != null,
                    new Event(
                        @event.Event.EventId, @event.Event.EventType, (@event.Event.Flags & PrepareFlags.IsJson) != 0,
                        @event.Event.Data, @event.Event.Metadata), receivedPosition.PreparePosition, 100.0f * positionEvent.LogPosition / lastCommitPosition));
        }
Пример #32
0
        /// <summary>
        /// Creates an PartitionReceiver from the given connection sting and partition key.
        /// The Reliable Dictionaries are used to create a receiver from wherever the service last left off,
        /// or from the current date/time if it's the first time the service is coming up.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="consumerGroup"></param>
        /// <param name="servicePartitionKey"></param>
        /// <param name="epochDictionary"></param>
        /// <param name="offsetDictionary"></param>
        /// <returns>PartitionReceiver</returns>
        private async Task <PartitionReceiver> ConnectToIoTHubAsync(
            EventHubClient client,
            string consumerGroup,
            long servicePartitionKey,
            IReliableDictionary <string, long> epochDictionary,
            IReliableDictionary <string, string> offsetDictionary)
        {
            // This gives each partition its own dedicated TCP connection to IoT Hub.
            var eventHubRuntimeInfo = await client.GetRuntimeInformationAsync();

            PartitionReceiver partitionReceiver;

            // Get an IoT Hub partition ID that corresponds to this partition's low key.
            // This assumes that this service has a partition count 'n' that is equal to the IoT Hub partition count and a partition range of 0..n-1.
            // For example, given an IoT Hub with 32 partitions, this service should be created with:
            // partition count = 32
            // partition range = 0..31
            string eventHubPartitionId = eventHubRuntimeInfo.PartitionIds[servicePartitionKey];

            using (var tx = this.StateManager.CreateTransaction())
            {
                ConditionalValue <string> offsetResult = await offsetDictionary.TryGetValueAsync(tx, "offset", LockMode.Default);

                ConditionalValue <long> epochResult = await epochDictionary.TryGetValueAsync(tx, "epoch", LockMode.Update);

                long newEpoch = epochResult.HasValue
                    ? epochResult.Value + 1
                    : 0;

                if (offsetResult.HasValue)
                {
                    // continue where the service left off before the last failover or restart.
                    ServiceEventSource.Current.ServiceMessage(
                        this.Context,
                        "Creating EventHub listener on partition {0} with offset {1}",
                        eventHubPartitionId,
                        offsetResult.Value);

                    partitionReceiver = client.CreateEpochReceiver(consumerGroup, eventHubPartitionId, EventPosition.FromOffset(offsetResult.Value), newEpoch);
                }
                else
                {
                    // first time this service is running so there is no offset value yet.
                    // start with the current time.
                    ServiceEventSource.Current.ServiceMessage(
                        this.Context,
                        "Creating EventHub listener on partition {0} with offset {1}",
                        eventHubPartitionId,
                        DateTime.UtcNow);

                    partitionReceiver = client.CreateEpochReceiver(consumerGroup, eventHubPartitionId, EventPosition.FromEnqueuedTime(DateTime.UtcNow), newEpoch);
                }

                // epoch is recorded each time the service fails over or restarts.
                await epochDictionary.SetAsync(tx, "epoch", newEpoch);

                await tx.CommitAsync();
            }

            return(partitionReceiver);
        }
Пример #33
0
        public async Task PartitionReceiverEpochReceive()
        {
            TestUtility.Log("Testing EpochReceiver semantics");

            await using (var scope = await EventHubScope.CreateAsync(2))
            {
                var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName);
                var ehClient         = EventHubClient.CreateFromConnectionString(connectionString);
                var epochReceiver1   = ehClient.CreateEpochReceiver(PartitionReceiver.DefaultConsumerGroupName, "1", EventPosition.FromStart(), 1);
                var epochReceiver2   = ehClient.CreateEpochReceiver(PartitionReceiver.DefaultConsumerGroupName, "1", EventPosition.FromStart(), 2);
                try
                {
                    // Read the events from Epoch 1 Receiver until we're at the end of the stream
                    TestUtility.Log("Starting epoch 1 receiver");
                    IEnumerable <EventData> events;
                    do
                    {
                        events = await epochReceiver1.ReceiveAsync(10);

                        var count = events?.Count() ?? 0;
                    }while (events != null);

                    TestUtility.Log("Starting epoch 2 receiver");
                    var epoch2ReceiveTask = epochReceiver2.ReceiveAsync(10);

                    DateTime stopTime = DateTime.UtcNow.AddSeconds(30);
                    do
                    {
                        events = await epochReceiver1.ReceiveAsync(10);

                        var count = events?.Count() ?? 0;
                        TestUtility.Log($"Epoch 1 receiver got {count} event(s)");
                    }while (DateTime.UtcNow < stopTime);

                    throw new InvalidOperationException("Epoch 1 receiver should have encountered an exception by now!");
                }
                catch (ReceiverDisconnectedException disconnectedException)
                {
                    TestUtility.Log($"Received expected exception {disconnectedException.GetType()}: {disconnectedException.Message}");

                    try
                    {
                        await epochReceiver1.ReceiveAsync(10);

                        throw new InvalidOperationException("Epoch 1 receiver should throw ReceiverDisconnectedException here too!");
                    }
                    catch (ReceiverDisconnectedException e)
                    {
                        TestUtility.Log($"Received expected exception {e.GetType()}");
                    }
                }
                finally
                {
                    await Task.WhenAll(
                        epochReceiver1.CloseAsync(),
                        epochReceiver2.CloseAsync(),
                        ehClient.CloseAsync());
                }
            }
        }
Пример #34
0
 /// <summary>
 /// Creates a new Checkpoint for a particular partition ID.
 /// </summary>
 /// <param name="partitionId">The partition ID for the checkpoint</param>
 public Checkpoint(string partitionId)
     : this(partitionId, EventPosition.FromStart().Offset, 0)
 {
 }
Пример #35
0
        public async Task CreateEpochReceiverAfterNonEpochReceiver()
        {
            await using (var scope = await EventHubScope.CreateAsync(2))
            {
                var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName);
                var ehClient         = EventHubClient.CreateFromConnectionString(connectionString);
                var nonEpochReceiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, "1", EventPosition.FromStart());
                var epochReceiver    = ehClient.CreateEpochReceiver(PartitionReceiver.DefaultConsumerGroupName, "1", EventPosition.FromStart(), 1);

                try
                {
                    TestUtility.Log("Starting nonepoch receiver");
                    await nonEpochReceiver.ReceiveAsync(10);

                    await Task.Delay(TimeSpan.FromSeconds(10));

                    TestUtility.Log("Starting epoch receiver");
                    await epochReceiver.ReceiveAsync(10);

                    await Task.Delay(TimeSpan.FromSeconds(10));

                    try
                    {
                        TestUtility.Log("Restarting nonepoch receiver, this should fail");
                        await nonEpochReceiver.ReceiveAsync(10);

                        throw new InvalidOperationException("Non-Epoch receiver should have encountered an exception by now!");
                    }
                    catch (ReceiverDisconnectedException ex) when(ex.Message.Contains("non-epoch receiver is not allowed"))
                    {
                        TestUtility.Log($"Received expected exception {ex.GetType()}: {ex.Message}");
                    }
                }
                finally
                {
                    await Task.WhenAll(
                        epochReceiver.CloseAsync(),
                        nonEpochReceiver.CloseAsync(),
                        ehClient.CloseAsync());
                }
            }
        }
Пример #36
0
        public async Task CreateReceiverWithInclusiveSequenceNumber()
        {
            var receiver = default(PartitionReceiver);

            await using (var scope = await EventHubScope.CreateAsync(1))
            {
                var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName);
                var ehClient         = EventHubClient.CreateFromConnectionString(connectionString);

                try
                {
                    // Randomly pick one of the available partitons.
                    var partitions = await this.GetPartitionsAsync(ehClient);

                    var partitionId = partitions[new Random().Next(partitions.Length)];
                    TestUtility.Log($"Randomly picked partition {partitionId}");

                    await TestUtility.SendToPartitionAsync(ehClient, partitionId, $"{partitionId} event.");

                    // Find out where to start reading on the partition.
                    var pInfo = await ehClient.GetPartitionRuntimeInformationAsync(partitionId);

                    // Send a message which is expected to go to the end of stream.
                    // We are expecting to receive this message as well.
                    await TestUtility.SendToPartitionAsync(ehClient, partitionId, $"{partitionId} event.");

                    // Create a new receiver which will start reading from the last message on the stream.
                    TestUtility.Log($"Creating a new receiver with sequence number {pInfo.LastEnqueuedSequenceNumber}");
                    receiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, partitionId, EventPosition.FromSequenceNumber(pInfo.LastEnqueuedSequenceNumber, true));
                    var receivedMessages = await receiver.ReceiveAsync(100);

                    // We should have received only 1 message from this call.
                    Assert.True(receivedMessages.Count() == 2, $"Didn't receive 2 messages. Received {receivedMessages.Count()} messages(s).");

                    // Next receive on this partition shouldn't return any more messages.
                    receivedMessages = await receiver.ReceiveAsync(100, TimeSpan.FromSeconds(15));

                    Assert.True(receivedMessages == null, $"Received messages at the end.");
                }
                finally
                {
                    await Task.WhenAll(
                        receiver.CloseAsync(),
                        ehClient.CloseAsync());
                }
            }
        }
 private void DeliverLastCommitPosition(EventPosition lastPosition)
 {
     if (_stopOnEof)
         return;
     _publisher.Publish(
         new ProjectionCoreServiceMessage.CommittedEventDistributed(
             _distibutionPointCorrelationId, default(EventPosition), null, int.MinValue,
             null, int.MinValue, false, null, lastPosition.PreparePosition, 100.0f)); //TODO: check was is passed here
 }
Пример #38
0
        public async Task CloseSenderClient()
        {
            var ehClient  = EventHubClient.CreateFromConnectionString(TestUtility.EventHubsConnectionString);
            var pSender   = ehClient.CreatePartitionSender("0");
            var pReceiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, "0", EventPosition.FromStart());

            try
            {
                TestUtility.Log("Sending single event to partition 0");
                using (var eventData = new EventData(Encoding.UTF8.GetBytes("Hello EventHub!")))
                {
                    await pSender.SendAsync(eventData);

                    TestUtility.Log("Closing partition sender");
                    await pSender.CloseAsync();
                }

                await Assert.ThrowsAsync <ObjectDisposedException>(async() =>
                {
                    TestUtility.Log("Sending another event to partition 0 on the closed sender, this should fail");
                    using (var eventData = new EventData(Encoding.UTF8.GetBytes("Hello EventHub!")))
                    {
                        await pSender.SendAsync(eventData);
                    }
                });
            }
            finally
            {
                await Task.WhenAll(
                    pReceiver.CloseAsync(),
                    ehClient.CloseAsync());
            }
        }
 private void ValidateEventOrder(ProjectionCoreServiceMessage.CommittedEventDistributed message)
 {
     if (_lastEventPosition >= message.Position)
         throw new InvalidOperationException(
             string.Format(
                 "Invalid committed event order.  Last: '{0}' Received: '{1}'", _lastEventPosition,
                 message.Position));
     _lastEventPosition = message.Position;
 }
Пример #40
0
        public bool ProcessEvent(
            EventPosition position, string streamId, string eventType, string category, Guid eventId, int sequenceNumber,
            string metadata, string data, out string newState, out EmittedEvent[] emittedEvents)
        {
            if (_failOnProcessEvent)
                throw new Exception("PROCESS_EVENT_FAILED");
            _lastProcessedStreamId = streamId;
            _lastProcessedEventType = eventType;
            _lastProcessedEventId = eventId;
            _lastProcessedSequencenumber = sequenceNumber;
            _lastProcessedMetadata = metadata;
            _lastProcessedData = data;

            _eventsProcessed++;
            switch (eventType)
            {
                case "skip_this_type":
                    _loadedState = newState = null;
                    emittedEvents = null;
                    return false;
                case "handle_this_type":
                    _loadedState = newState = data;
                    emittedEvents = null;
                    return true;
                case "append":
                    _loadedState = newState = _loadedState + data;
                    emittedEvents = null;
                    return true;
                case "no_state_emit1_type":
                    _loadedState = newState = "";
                    emittedEvents = new[]
                        {new EmittedEvent(_emit1StreamId, Guid.NewGuid(), _emit1EventType, _emit1Data),};
                    return true;
                case "emit1_type":
                    _loadedState = newState = data;
                    emittedEvents = new[]
                        {new EmittedEvent(_emit1StreamId, Guid.NewGuid(), _emit1EventType, _emit1Data),};
                    return true;
                case "emit22_type":
                    _loadedState = newState = data;
                    emittedEvents = new[]
                        {
                            new EmittedEvent(_emit2StreamId, Guid.NewGuid(), _emit2EventType, _emit1Data),
                            new EmittedEvent(_emit2StreamId, Guid.NewGuid(), _emit2EventType, _emit2Data),
                        };
                    return true;
                case "emit212_type":
                    _loadedState = newState = data;
                    emittedEvents = new[]
                        {
                            new EmittedEvent(_emit2StreamId, Guid.NewGuid(), _emit2EventType, _emit1Data),
                            new EmittedEvent(_emit1StreamId, Guid.NewGuid(), _emit1EventType, _emit2Data),
                            new EmittedEvent(_emit2StreamId, Guid.NewGuid(), _emit2EventType, _emit3Data),
                        };
                    return true;
                case "emit12_type":
                    _loadedState = newState = data;
                    emittedEvents = new[]
                        {
                            new EmittedEvent(_emit1StreamId, Guid.NewGuid(), _emit1EventType, _emit1Data),
                            new EmittedEvent(_emit2StreamId, Guid.NewGuid(), _emit2EventType, _emit2Data),
                        };
                    return true;
                default:
                    throw new NotSupportedException();
            }
        }
 private void CacheRecentMessage(ProjectionMessage.Projections.CommittedEventReceived message)
 {
     _lastMessages.Enqueue(message);
     if (_lastMessages.Count > _eventCacheSize)
     {
         _lastMessages.Dequeue();
     }
     var lastAvailableCommittedevent = _lastMessages.Peek();
     _subscribeFromPosition = lastAvailableCommittedevent.Position;
 }
Пример #42
0
 public void ConstructorRequiresTheOptions()
 {
     Assert.That(() => new AmqpEventHubConsumer("theMostAwesomeHubEvar", "$DEFAULT", "0", EventPosition.FromOffset(1), null, Mock.Of <AmqpConnectionScope>(), Mock.Of <AmqpMessageConverter>(), Mock.Of <EventHubRetryPolicy>(), new LastEnqueuedEventProperties("hub", "0")), Throws.ArgumentNullException);
 }
 private CommittedEventReceived(
     Guid correlationId, Guid subscriptionId, EventPosition position, CheckpointTag checkpointTag,
     string positionStreamId, int positionSequenceNumber, string eventStreamId, int eventSequenceNumber,
     string eventCategory, bool resolvedLinkTo, ResolvedEvent data, float progress,
     long subscriptionMessageSequenceNumber)
     : base(subscriptionId, checkpointTag, progress, subscriptionMessageSequenceNumber)
 {
     if (data == null) throw new ArgumentNullException("data");
     _data = data;
     _position = position;
     _positionStreamId = positionStreamId;
     _positionSequenceNumber = positionSequenceNumber;
     _eventStreamId = eventStreamId;
     _eventSequenceNumber = eventSequenceNumber;
     _eventCategory = eventCategory;
     _resolvedLinkTo = resolvedLinkTo;
 }
Пример #44
0
        public async Task CreateReceiverWithSequenceNumber()
        {
            var receiver = default(PartitionReceiver);

            await using (var scope = await EventHubScope.CreateAsync(1))
            {
                var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName);
                var ehClient         = EventHubClient.CreateFromConnectionString(connectionString);

                try
                {
                    // Randomly pick one of the available partitons.
                    var partitions = await this.GetPartitionsAsync(ehClient);

                    var partitionId = partitions[new Random().Next(partitions.Length)];
                    TestUtility.Log($"Randomly picked partition {partitionId}");

                    // Send and receive a message to identify the end of stream.
                    var pInfo = await ehClient.GetPartitionRuntimeInformationAsync(partitionId);

                    // Send a new message which is expected to go to the end of stream.
                    // We are expecting to receive only this message.
                    var eventSent = new EventData(new byte[1]);
                    eventSent.Properties["stamp"] = Guid.NewGuid().ToString();
                    await ehClient.CreatePartitionSender(partitionId).SendAsync(eventSent);

                    // Create a new receiver which will start reading from the last message on the stream.
                    TestUtility.Log($"Creating a new receiver with sequence number {pInfo.LastEnqueuedSequenceNumber}");
                    receiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, partitionId, EventPosition.FromSequenceNumber(pInfo.LastEnqueuedSequenceNumber));
                    var receivedMessages = await receiver.ReceiveAsync(100);

                    // We should have received only 1 message from this call.
                    Assert.True(receivedMessages.Count() == 1, $"Didn't receive 1 message. Received {receivedMessages.Count()} messages(s).");

                    // Check stamp.
                    Assert.True(receivedMessages.Single().Properties["stamp"].ToString() == eventSent.Properties["stamp"].ToString()
                                , "Stamps didn't match on the message sent and received!");

                    TestUtility.Log("Received correct message as expected.");

                    // Next receive on this partition shouldn't return any more messages.
                    receivedMessages = await receiver.ReceiveAsync(100, TimeSpan.FromSeconds(15));

                    Assert.True(receivedMessages == null, $"Received messages at the end.");
                }
                finally
                {
                    await Task.WhenAll(
                        receiver.CloseAsync(),
                        ehClient.CloseAsync());
                }
            }
        }
 private CommittedEventReceived(
     Guid correlationId, Guid subscriptionId, EventPosition position, string eventStreamId,
     int eventSequenceNumber, string eventCategory, bool resolvedLinkTo, ResolvedEvent data, float progress,
     long subscriptionMessageSequenceNumber)
     : this(
         correlationId, subscriptionId, position,
         CheckpointTag.FromPosition(position.CommitPosition, position.PreparePosition), eventStreamId,
         eventSequenceNumber, eventStreamId, eventSequenceNumber, eventCategory, resolvedLinkTo, data,
         progress, subscriptionMessageSequenceNumber)
 {
 }
Пример #46
0
        public async Task PartitionReceiverReceiveBatch()
        {
            const int MaxBatchSize = 5;

            TestUtility.Log("Receiving Events via PartitionReceiver.ReceiveAsync(BatchSize)");
            const string partitionId = "0";

            await using (var scope = await EventHubScope.CreateAsync(1))
            {
                var connectionString  = TestUtility.BuildEventHubsConnectionString(scope.EventHubName);
                var ehClient          = EventHubClient.CreateFromConnectionString(connectionString);
                var partitionSender   = ehClient.CreatePartitionSender(partitionId);
                var partitionReceiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, partitionId, EventPosition.FromEnqueuedTime(DateTime.UtcNow.AddMinutes(-10)));

                try
                {
                    int eventCount = 20;
                    TestUtility.Log($"Sending {eventCount} events to Partition {partitionId}");
                    var sendEvents = new List <EventData>(eventCount);
                    for (int i = 0; i < eventCount; i++)
                    {
                        sendEvents.Add(new EventData(Encoding.UTF8.GetBytes($"Hello EventHub! Message {i}")));
                    }
                    await partitionSender.SendAsync(sendEvents);

                    int maxReceivedBatchSize = 0;
                    while (true)
                    {
                        IEnumerable <EventData> partition1Events = await partitionReceiver.ReceiveAsync(MaxBatchSize);

                        int receivedEventCount = partition1Events != null?partition1Events.Count() : 0;

                        TestUtility.Log($"Received {receivedEventCount} event(s)");

                        if (partition1Events == null)
                        {
                            break;
                        }

                        maxReceivedBatchSize = Math.Max(maxReceivedBatchSize, receivedEventCount);
                    }

                    Assert.True(maxReceivedBatchSize == MaxBatchSize, $"A max batch size of {MaxBatchSize} events was not honored! Actual {maxReceivedBatchSize}.");
                }
                finally
                {
                    await Task.WhenAll(
                        partitionReceiver.CloseAsync(),
                        partitionSender.CloseAsync(),
                        ehClient.CloseAsync());
                }
            }
        }
 public static CommittedEventReceived Sample(
     Guid correlationId, Guid subscriptionId, EventPosition position, string eventStreamId,
     int eventSequenceNumber, bool resolvedLinkTo, ResolvedEvent data, long subscriptionMessageSequenceNumber)
 {
     return new CommittedEventReceived(
         correlationId, subscriptionId, position, eventStreamId, eventSequenceNumber, null, resolvedLinkTo, data, 77.7f,
         subscriptionMessageSequenceNumber);
 }
Пример #48
0
        public async Task CreateReceiverWithEndOfStream()
        {
            var receiver        = default(PartitionReceiver);
            var partitionSender = default(PartitionSender);

            await using (var scope = await EventHubScope.CreateAsync(1))
            {
                var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName);
                var ehClient         = EventHubClient.CreateFromConnectionString(connectionString);

                try
                {
                    // Randomly pick one of the available partitons.
                    var partitions = await this.GetPartitionsAsync(ehClient);

                    var partitionId = partitions[new Random().Next(partitions.Length)];
                    TestUtility.Log($"Randomly picked partition {partitionId}");

                    partitionSender = ehClient.CreatePartitionSender(partitionId);

                    // Send couple of messages before creating an EndOfStream receiver.
                    // We are not expecting to receive these messages would be sent before receiver creation.
                    for (int i = 0; i < 10; i++)
                    {
                        var ed = new EventData(new byte[1]);
                        await partitionSender.SendAsync(ed);
                    }

                    // Create a new receiver which will start reading from the end of the stream.
                    TestUtility.Log($"Creating a new receiver with offset EndOFStream");
                    receiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, partitionId, EventPosition.FromEnd());

                    // Attemp to receive the message. This should return only 1 message.
                    var receiveTask = receiver.ReceiveAsync(100);

                    // Send a new message which is expected to go to the end of stream.
                    // We are expecting to receive only this message.
                    // Wait 5 seconds before sending to avoid race.
                    await Task.Delay(5000);

                    var eventToReceive = new EventData(new byte[1]);
                    eventToReceive.Properties["stamp"] = Guid.NewGuid().ToString();
                    await partitionSender.SendAsync(eventToReceive);

                    // Complete asyncy receive task.
                    var receivedMessages = await receiveTask;

                    // We should have received only 1 message from this call.
                    Assert.True(receivedMessages.Count() == 1, $"Didn't receive 1 message. Received {receivedMessages.Count()} messages(s).");

                    // Check stamp.
                    Assert.True(receivedMessages.Single().Properties["stamp"].ToString() == eventToReceive.Properties["stamp"].ToString()
                                , "Stamps didn't match on the message sent and received!");

                    TestUtility.Log("Received correct message as expected.");

                    // Next receive on this partition shouldn't return any more messages.
                    receivedMessages = await receiver.ReceiveAsync(100, TimeSpan.FromSeconds(15));

                    Assert.True(receivedMessages == null, $"Received messages at the end.");
                }
                finally
                {
                    await Task.WhenAll(
                        partitionSender.CloseAsync(),
                        receiver.CloseAsync(),
                        ehClient.CloseAsync());
                }
            }
        }
Пример #49
0
 public bool IsCheckpointTagAfterEventPosition(CheckpointTag checkpointTag, EventPosition position)
 {
     if (_streams == null || _streams.Count == 0)
     {
         return checkpointTag.Position >= position;
     }
     else if (_streams != null && _streams.Count == 1)
     {
         return checkpointTag.PreparePosition >= position.CommitPosition;
     }
     else if (_categories != null && _categories.Count == 1)
     {
         return checkpointTag.PreparePosition >= position.CommitPosition;
     }
     else
         throw new NotSupportedException();
 }
Пример #50
0
        public async Task CloseReceiverClient()
        {
            await using (var scope = await EventHubScope.CreateAsync(1))
            {
                var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName);
                var ehClient         = EventHubClient.CreateFromConnectionString(connectionString);
                var pSender          = ehClient.CreatePartitionSender("0");
                var pReceiver        = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, "0", EventPosition.FromStart());

                try
                {
                    TestUtility.Log("Sending single event to partition 0");
                    var eventData = new EventData(Encoding.UTF8.GetBytes("Hello EventHub!"));
                    await pSender.SendAsync(eventData);

                    TestUtility.Log("Receiving the event.");
                    var events = await pReceiver.ReceiveAsync(1);

                    Assert.True(events != null && events.Count() == 1, "Failed to receive 1 event");
                }
                finally
                {
                    TestUtility.Log("Closing partition receiver");
                    await Task.WhenAll(
                        pReceiver.CloseAsync(),
                        ehClient.CloseAsync());
                }

                await Assert.ThrowsAsync <ObjectDisposedException>(async() =>
                {
                    TestUtility.Log("Receiving another event from partition 0 on the closed receiver, this should fail");
                    await pReceiver.ReceiveAsync(1);
                });
            }
        }
Пример #51
0
        /// <summary>
        ///   Starts running a task responsible for receiving and processing events in the context of a specified partition.
        /// </summary>
        ///
        /// <param name="partitionId">The identifier of the Event Hub partition the task is associated with.  Events will be read only from this partition.</param>
        /// <param name="startingPosition">The position within the partition where the task should begin reading events.</param>
        /// <param name="maximumReceiveWaitTime">The maximum amount of time to wait to for an event to be available before emitting an empty item; if <c>null</c>, empty items will not be published.</param>
        /// <param name="retryOptions">The set of options to use for determining whether a failed operation should be retried and, if so, the amount of time to wait between retry attempts.</param>
        /// <param name="trackLastEnqueuedEventInformation">Indicates whether or not the task should request information on the last enqueued event on the partition associated with a given event, and track that information as events are received.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        /// <returns>The running task that is currently receiving and processing events in the context of the specified partition.</returns>
        ///
        protected virtual Task RunPartitionProcessingAsync(string partitionId,
                                                           EventPosition startingPosition,
                                                           TimeSpan?maximumReceiveWaitTime,
                                                           RetryOptions retryOptions,
                                                           bool trackLastEnqueuedEventInformation,
                                                           CancellationToken cancellationToken = default)
        {
            // TODO: should the retry options used here be the same for the abstract RetryPolicy property?

            Argument.AssertNotNullOrEmpty(partitionId, nameof(partitionId));
            Argument.AssertNotNull(retryOptions, nameof(retryOptions));

            return(Task.Run(async() =>
            {
                // TODO: should we double check if a previous run already exists and close it?  We have a race condition.  Maybe we should throw in case another task exists.

                var cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                var taskCancellationToken = cancellationSource.Token;

                ActivePartitionProcessorTokenSources[partitionId] = cancellationSource;

                // Context is set to default if operation fails.  This shouldn't fail unless the user tries processing
                // a partition they don't own.

                PartitionContexts.TryGetValue(partitionId, out var context);

                var options = new EventHubConsumerClientOptions
                {
                    RetryOptions = retryOptions,
                    TrackLastEnqueuedEventInformation = trackLastEnqueuedEventInformation
                };

                await using var connection = CreateConnection();

                await using (var consumer = new EventHubConsumerClient(ConsumerGroup, connection, options))
                {
                    await foreach (var partitionEvent in consumer.ReadEventsFromPartitionAsync(partitionId, startingPosition, maximumReceiveWaitTime, taskCancellationToken))
                    {
                        using DiagnosticScope diagnosticScope = EventDataInstrumentation.ClientDiagnostics.CreateScope(DiagnosticProperty.EventProcessorProcessingActivityName);
                        diagnosticScope.AddAttribute("kind", "server");

                        if (diagnosticScope.IsEnabled &&
                            partitionEvent.Data != null &&
                            EventDataInstrumentation.TryExtractDiagnosticId(partitionEvent.Data, out string diagnosticId))
                        {
                            diagnosticScope.AddLink(diagnosticId);
                        }

                        diagnosticScope.Start();

                        try
                        {
                            await ProcessEventAsync(partitionEvent, context).ConfigureAwait(false);
                        }
                        catch (Exception eventProcessingException)
                        {
                            diagnosticScope.Failed(eventProcessingException);
                            throw;
                        }
                    }
                }
            }));
        }
Пример #52
0
        public void InitializeHandlerArgs()
        {
            #region Snippet:EventHubs_Processor_Sample03_InitializeHandlerArgs

#if SNIPPET
            var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>";
            var blobContainerName       = "<< NAME OF THE BLOB CONTAINER >>";

            var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>";
            var eventHubName  = "<< NAME OF THE EVENT HUB >>";
            var consumerGroup = "<< NAME OF THE EVENT HUB CONSUMER GROUP >>";
#else
            var storageConnectionString   = StorageTestEnvironment.Instance.StorageConnectionString;
            var blobContainerName         = "not-real";
            var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString;
            var eventHubName  = "fakeHub";
            var consumerGroup = "fakeConsumer";
#endif

            var storageClient = new BlobContainerClient(
                storageConnectionString,
                blobContainerName);

            var processor = new EventProcessorClient(
                storageClient,
                consumerGroup,
                eventHubsConnectionString,
                eventHubName);

            Task initializeEventHandler(PartitionInitializingEventArgs args)
            {
                try
                {
                    if (args.CancellationToken.IsCancellationRequested)
                    {
                        return(Task.CompletedTask);
                    }

                    Debug.WriteLine($"Initialize partition: { args.PartitionId }");

                    // If no checkpoint was found, start processing
                    // events enqueued now or in the future.

                    EventPosition startPositionWhenNoCheckpoint =
                        EventPosition.FromEnqueuedTime(DateTimeOffset.UtcNow);

                    args.DefaultStartingPosition = startPositionWhenNoCheckpoint;
                }
                catch
                {
                    // Take action to handle the exception.
                    // It is important that all exceptions are
                    // handled and none are permitted to bubble up.
                }

                return(Task.CompletedTask);
            }

            try
            {
                processor.PartitionInitializingAsync += initializeEventHandler;

                // Starting and stopping the processor are not
                // shown in this example.
            }
            finally
            {
                processor.PartitionInitializingAsync -= initializeEventHandler;
            }

            #endregion
        }
 private Task <PartitionReceiver> SetupFromEndOfStreamAsync(string consumerGroup, string partitionId)
 {
     return(Task.FromResult(_client.CreateReceiver(consumerGroup, partitionId, EventPosition.FromEnd())));
 }
 /// <summary>
 /// Initializes a new instance of the type
 /// </summary>
 /// <param name="containerName">The name of the container to use in logging operations</param>
 /// <param name="diagnosticsConfiguration">A diagnostics instance to use when instantiating the container</param>
 /// <param name="probeConfiguration">The availability and liveness probe configuration</param>
 /// <param name="startPosition">The event position to start processing if no checkpoint is found for the partition</param>
 protected LegacyProcessorBase(string containerName, DiagnosticsConfiguration diagnosticsConfiguration, IProbeConfiguration probeConfiguration, EventPosition startPosition) : base(containerName, probeConfiguration, diagnosticsConfiguration)
 {
     _loggerFactory                   = diagnosticsConfiguration.LoggerFactory;
     _startPosition                   = startPosition;
     _iterationCounter                = diagnosticsConfiguration.MetricFactory.CreateCounter("pro_iteration_counter", "Counts the number of iterations the demo container has performed.", false, new string[0]);
     _scaleEventCounter               = diagnosticsConfiguration.MetricFactory.CreateCounter("pro_scale_event_counter", "Counts the number of times a scale event has occurred.", false, new string[0]);
     _healthProbeCounter              = diagnosticsConfiguration.MetricFactory.CreateCounter("pro_health_counter", "Counts the number of times the liveness probe endpoint has been accessed since the start of the container.", false, new string[0]);
     _healthProbeFailureCounter       = diagnosticsConfiguration.MetricFactory.CreateCounter("pro_health_failure_counter", "Counts the number of times the liveness probe endpoint has been accessed and failed since the start of the container.", false, new string[0]);
     _availabilityProbeCounter        = diagnosticsConfiguration.MetricFactory.CreateCounter("pro_availability_counter", "Counts the number of times the readiness probe endpoint has been accessed since the start of the container.", false, new string[0]);
     _availabilityProbeFailureCounter = diagnosticsConfiguration.MetricFactory.CreateCounter("pro_availability_failure_counter", "Counts the number of times the readiness probe endpoint has been accessed and failed since the start of the container.", false, new string[0]);
 }
Пример #55
0
        public async Task ReadPartitionWaitTime()
        {
            await using var scope = await EventHubScope.CreateAsync(1);

            #region Snippet:EventHubs_Sample05_ReadPartitionWaitTime

            var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>";
            var eventHubName     = "<< NAME OF THE EVENT HUB >>";
            var consumerGroup    = EventHubConsumerClient.DefaultConsumerGroupName;
            /*@@*/
            /*@@*/ connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString;
            /*@@*/ eventHubName     = scope.EventHubName;

            var consumer = new EventHubConsumerClient(
                consumerGroup,
                connectionString,
                eventHubName);

            try
            {
                using CancellationTokenSource cancellationSource = new CancellationTokenSource();
                cancellationSource.CancelAfter(TimeSpan.FromSeconds(30));

                string        firstPartition   = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First();
                EventPosition startingPosition = EventPosition.Earliest;

                int loopTicks    = 0;
                int maximumTicks = 10;

                var options = new ReadEventOptions
                {
                    MaximumWaitTime = TimeSpan.FromSeconds(1)
                };

                await foreach (PartitionEvent partitionEvent in consumer.ReadEventsFromPartitionAsync(
                                   firstPartition,
                                   startingPosition,
                                   options))
                {
                    if (partitionEvent.Data != null)
                    {
                        string readFromPartition = partitionEvent.Partition.PartitionId;
                        byte[] eventBodyBytes    = partitionEvent.Data.EventBody.ToArray();

                        Debug.WriteLine($"Read event of length { eventBodyBytes.Length } from { readFromPartition }");
                    }
                    else
                    {
                        Debug.WriteLine("Wait time elapsed; no event was available.");
                    }

                    loopTicks++;

                    if (loopTicks >= maximumTicks)
                    {
                        break;
                    }
                }
            }
            catch (TaskCanceledException)
            {
                // This is expected if the cancellation token is
                // signaled.
            }
            finally
            {
                await consumer.CloseAsync();
            }

            #endregion
        }
Пример #56
0
        /// <summary>
        ///   Creates an AMQP link for use with receiving operations.
        /// </summary>
        ///
        /// <param name="connection">The active and opened AMQP connection to use for this link.</param>
        /// <param name="endpoint">The fully qualified endpoint to open the link for.</param>
        /// <param name="eventPosition">The position of the event in the partition where the link should be filtered to.</param>
        /// <param name="consumerOptions">The set of active options for the consumer that will make use of the link.</param>
        /// <param name="timeout">The timeout to apply when creating the link.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        /// <returns>A link for use for operations related to receiving events.</returns>
        ///
        protected virtual async Task <ReceivingAmqpLink> CreateReceivingLinkAsync(AmqpConnection connection,
                                                                                  Uri endpoint,
                                                                                  EventPosition eventPosition,
                                                                                  EventHubConsumerOptions consumerOptions,
                                                                                  TimeSpan timeout,
                                                                                  CancellationToken cancellationToken)
        {
            Argument.AssertNotDisposed(IsDisposed, nameof(AmqpConnectionScope));
            cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

            var session   = default(AmqpSession);
            var stopWatch = Stopwatch.StartNew();

            try
            {
                // Perform the initial authorization for the link.

                var authClaims        = new[] { EventHubsClaim.Listen };
                var authExpirationUtc = await RequestAuthorizationUsingCbsAsync(connection, TokenProvider, endpoint, endpoint.AbsoluteUri, endpoint.AbsoluteUri, authClaims, timeout.CalculateRemaining(stopWatch.Elapsed)).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                // Create and open the AMQP session associated with the link.

                var sessionSettings = new AmqpSessionSettings {
                    Properties = new Fields()
                };
                session = connection.CreateSession(sessionSettings);

                await OpenAmqpObjectAsync(session, timeout).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                // Create and open the link.

                var filters = new FilterSet();
                filters.Add(AmqpFilter.ConsumerFilterName, AmqpFilter.CreateConsumerFilter(AmqpFilter.BuildFilterExpression(eventPosition)));

                var linkSettings = new AmqpLinkSettings
                {
                    Role            = true,
                    TotalLinkCredit = (uint)consumerOptions.PrefetchCount,
                    AutoSendFlow    = consumerOptions.PrefetchCount > 0,
                    SettleType      = SettleMode.SettleOnSend,
                    Source          = new Source {
                        Address = endpoint.AbsolutePath, FilterSet = filters
                    },
                    Target = new Target {
                        Address = Guid.NewGuid().ToString()
                    }
                };

                linkSettings.AddProperty(AmqpProperty.EntityType, (int)AmqpProperty.Entity.ConsumerGroup);

                if (!string.IsNullOrEmpty(consumerOptions.Identifier))
                {
                    linkSettings.AddProperty(AmqpProperty.ConsumerIdentifier, consumerOptions.Identifier);
                }

                if (consumerOptions.OwnerLevel.HasValue)
                {
                    linkSettings.AddProperty(AmqpProperty.OwnerLevel, consumerOptions.OwnerLevel.Value);
                }

                if (consumerOptions.TrackLastEnqueuedEventInformation)
                {
                    linkSettings.DesiredCapabilities = new Multiple <AmqpSymbol>(new List <AmqpSymbol>
                    {
                        AmqpProperty.TrackLastEnqueuedEventInformation
                    });
                }

                var link = new ReceivingAmqpLink(linkSettings);
                linkSettings.LinkName = $"{ Id };{ connection.Identifier };{ session.Identifier };{ link.Identifier }";
                link.AttachTo(session);

                stopWatch.Stop();

                // Configure refresh for authorization of the link.

                var refreshTimer = default(Timer);

                var refreshHandler = CreateAuthorizationRefreshHandler
                                     (
                    connection,
                    link,
                    TokenProvider,
                    endpoint,
                    endpoint.AbsoluteUri,
                    endpoint.AbsoluteUri,
                    authClaims,
                    AuthorizationRefreshTimeout,
                    () => refreshTimer
                                     );

                refreshTimer = new Timer(refreshHandler, null, CalculateLinkAuthorizationRefreshInterval(authExpirationUtc), Timeout.InfiniteTimeSpan);

                // Track the link before returning it, so that it can be managed with the scope.

                BeginTrackingLinkAsActive(link, refreshTimer);
                return(link);
            }
            catch
            {
                // Aborting the session will perform any necessary cleanup of
                // the associated link as well.

                session?.Abort();
                throw;
            }
        }
Пример #57
0
        public async Task EventProcessorCanReceiveFromSpecifiedInitialEventPosition()
        {
            await using (EventHubScope scope = await EventHubScope.CreateAsync(2))
            {
                var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName);

                await using (var client = new EventHubClient(connectionString))
                {
                    int receivedEventsCount = 0;

                    // Send some events.

                    var            expectedEventsCount = 20;
                    var            dummyEvent          = new EventData(Encoding.UTF8.GetBytes("I'm dummy."));
                    DateTimeOffset enqueuedTime;

                    await using (EventHubProducer producer = client.CreateProducer())
                    {
                        // Send a few dummy events.  We are not expecting to receive these.

                        for (int i = 0; i < 30; i++)
                        {
                            await producer.SendAsync(dummyEvent);
                        }

                        // Wait a reasonable amount of time so the events are able to reach the service.

                        await Task.Delay(1000);

                        // Send the events we expect to receive.

                        enqueuedTime = DateTimeOffset.UtcNow;

                        for (int i = 0; i < expectedEventsCount; i++)
                        {
                            await producer.SendAsync(dummyEvent);
                        }
                    }

                    // Create the event processor manager to manage our event processors.

                    var eventProcessorManager = new EventProcessorManager
                                                (
                        EventHubConsumer.DefaultConsumerGroupName,
                        client,
                        options: new EventProcessorOptions {
                        InitialEventPosition = EventPosition.FromEnqueuedTime(enqueuedTime)
                    },
                        onProcessEvents: (partitionContext, events, cancellationToken) =>
                    {
                        // Make it a list so we can safely enumerate it.

                        var eventsList = new List <EventData>(events ?? Enumerable.Empty <EventData>());

                        if (eventsList.Count > 0)
                        {
                            Interlocked.Add(ref receivedEventsCount, eventsList.Count);
                        }
                    }
                                                );

                    eventProcessorManager.AddEventProcessors(1);

                    // Start the event processors.

                    await eventProcessorManager.StartAllAsync();

                    // Make sure the event processors have enough time to stabilize and receive events.

                    await eventProcessorManager.WaitStabilization();

                    // Stop the event processors.

                    await eventProcessorManager.StopAllAsync();

                    // Validate results.

                    Assert.That(receivedEventsCount, Is.EqualTo(expectedEventsCount));
                }
            }
        }
 public bool ProcessEvent(
     EventPosition position, CheckpointTag eventPosition, string streamId, string eventType, string category, Guid eventid,
     int sequenceNumber, string metadata, string data, out string newState, out EmittedEvent[] emittedEvents)
 {
     CheckDisposed();
     if (eventType == null)
         throw new ArgumentNullException("eventType");
     if (streamId == null)
         throw new ArgumentNullException("streamId");
     _eventPosition = eventPosition;
     _emittedEvents = null;
     _query.Push(
         data.Trim(), // trimming data passed to a JS
         new string[] {streamId, eventType, category ?? "", sequenceNumber.ToString(CultureInfo.InvariantCulture), metadata ?? "", position.PreparePosition.ToString()});
     newState = _query.GetState();
     emittedEvents = _emittedEvents == null ? null : _emittedEvents.ToArray();
     return true;
 }
Пример #59
0
 public bool CanJoinAt(EventPosition firstAvailableTransactionFileEvent, CheckpointTag eventCheckpointTag)
 {
     return eventCheckpointTag.PreparePosition >= firstAvailableTransactionFileEvent.CommitPosition;
 }