/// <summary> /// /// </summary> /// <param name="retryPolicy"></param> /// <param name="fromSequenceNumber"></param> /// <param name="messageCount"></param> /// <param name="sessionId"></param> /// <param name="receiveLinkName"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public override async Task <IEnumerable <ServiceBusMessage> > PeekAsync( ServiceBusRetryPolicy retryPolicy, long?fromSequenceNumber, int messageCount = 1, string sessionId = null, string receiveLinkName = null, CancellationToken cancellationToken = default) { RetriableContext context = new RetriableContext( ConnectionScope, new Stopwatch(), retryPolicy, EntityName, cancellationToken); return(await context.RunOperation( async() => await PeekInternal( context, fromSequenceNumber, messageCount, sessionId, receiveLinkName) .ConfigureAwait(false)) .ConfigureAwait(false)); }
/// <summary> /// /// </summary> /// <param name="fromSequenceNumber"></param> /// <param name="maxMessages"></param> /// <param name="cancellationToken"></param> /// <returns></returns> internal async IAsyncEnumerable <ServiceBusMessage> PeekRangeBySequenceInternal( long?fromSequenceNumber, int maxMessages = 1, [EnumeratorCancellation] CancellationToken cancellationToken = default) { RetriableContext context = CreateRetriableContext(cancellationToken); ReceivingAmqpLink openedLink = await context.RunOperation( async() => await Consumer.ReceiveLink.GetOrCreateAsync(context.TimeSpan) .ConfigureAwait(false)) .ConfigureAwait(false); var source = (Source)openedLink.Settings.Source; if (source.FilterSet.TryGetValue <string>(AmqpClientConstants.SessionFilterName, out var tempSessionId)) { // If one of the constructors not accepting a SessionId was used, the broker will determine which session to send messages from. SessionId = tempSessionId; } IAsyncEnumerable <ServiceBusMessage> ret = PeekRangeBySequenceInternal( fromSequenceNumber: fromSequenceNumber, maxMessages: maxMessages, sessionId: SessionId, cancellationToken: cancellationToken); await foreach (ServiceBusMessage msg in ret.ConfigureAwait(false)) { yield return(msg); } }
private async Task <IEnumerable <ServiceBusMessage> > PeekInternal( RetriableContext context, long?fromSequenceNumber, int messageCount = 1, string sessionId = null, string receiveLinkName = null) { AmqpRequestMessage amqpRequestMessage = AmqpRequestMessage.CreateRequest( ManagementConstants.Operations.PeekMessageOperation, context.TimeSpan, null); await AquireAccessTokenAsync(context.CancellationToken).ConfigureAwait(false); if (receiveLinkName != null) { // include associated link for service optimization amqpRequestMessage.AmqpMessage.ApplicationProperties.Map[ManagementConstants.Request.AssociatedLinkName] = receiveLinkName; } amqpRequestMessage.Map[ManagementConstants.Properties.FromSequenceNumber] = fromSequenceNumber ?? LastPeekedSequenceNumber + 1; amqpRequestMessage.Map[ManagementConstants.Properties.MessageCount] = messageCount; if (!string.IsNullOrWhiteSpace(sessionId)) { amqpRequestMessage.Map[ManagementConstants.Properties.SessionId] = sessionId; } RequestResponseAmqpLink link = await ManagementLink.GetOrCreateAsync( UseMinimum(ConnectionScope.SessionTimeout, context.TimeSpan.CalculateRemaining(context.Stopwatch.Elapsed))) .ConfigureAwait(false); context.CancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); // This is how Track 1 makes the request //var responseAmqpMessage = await Task.Factory.FromAsync( //(c, s) => link.BeginRequest( // amqpRequestMessage.AmqpMessage, // transactionId, // TimeSpan.FromSeconds(30), // c, s), //(a) => link.EndRequest(a), //this).ConfigureAwait(false); using AmqpMessage responseAmqpMessage = await link.RequestAsync( amqpRequestMessage.AmqpMessage, context.TimeSpan.CalculateRemaining(context.Stopwatch.Elapsed)) .ConfigureAwait(false); context.CancellationToken.ThrowIfCancellationRequested <TaskCanceledException>(); AmqpResponseMessage amqpResponseMessage = AmqpResponseMessage.CreateResponse(responseAmqpMessage); var messages = new List <ServiceBusMessage>(); //AmqpError.ThrowIfErrorResponse(responseAmqpMessage, EntityName); if (amqpResponseMessage.StatusCode == AmqpResponseStatusCode.OK) { ServiceBusMessage message = null; IEnumerable <AmqpMap> messageList = amqpResponseMessage.GetListValue <AmqpMap>(ManagementConstants.Properties.Messages); foreach (AmqpMap entry in messageList) { var payload = (ArraySegment <byte>)entry[ManagementConstants.Properties.Message]; var amqpMessage = AmqpMessage.CreateAmqpStreamMessage(new BufferListStream(new[] { payload }), true); message = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage, true); messages.Add(message); } if (message != null) { LastPeekedSequenceNumber = message.SystemProperties.SequenceNumber; } return(messages); } if (amqpResponseMessage.StatusCode == AmqpResponseStatusCode.NoContent || (amqpResponseMessage.StatusCode == AmqpResponseStatusCode.NotFound && Equals(AmqpClientConstants.MessageNotFoundError, amqpResponseMessage.GetResponseErrorCondition()))) { return(messages); } // TODO throw correct exception throw new Exception(); }