public RemotingResponse HandleRequest(IRequestHandlerContext context, RemotingRequest request)
 {
     var pullMessageRequest = _binarySerializer.Deserialize<PullMessageRequest>(request.Body);
     var messages = _messageService.GetMessages(
         pullMessageRequest.MessageQueue.Topic,
         pullMessageRequest.MessageQueue.QueueId,
         pullMessageRequest.QueueOffset,
         pullMessageRequest.PullMessageBatchSize);
     if (messages.Count() > 0)
     {
         var pullMessageResponse = new PullMessageResponse(messages);
         var responseData = _binarySerializer.Serialize(pullMessageResponse);
         return new RemotingResponse((int)PullStatus.Found, request.Sequence, responseData);
     }
     else
     {
         var pullRequest = new PullRequest(
             request.Sequence,
             pullMessageRequest,
             context,
             DateTime.Now,
             SuspendPullRequestMilliseconds,
             ExecutePullRequest,
             ExecutePullRequest,
             ExecuteReplacedPullRequest);
         _brokerController.SuspendedPullRequestManager.SuspendPullRequest(pullRequest);
         return null;
     }
 }
        public RemotingResponse HandleRequest(IRequestHandlerContext context, RemotingRequest remotingRequest)
        {
            var request = DeserializePullMessageRequest(remotingRequest.Body);
            var topic = request.MessageQueue.Topic;
            var queueId = request.MessageQueue.QueueId;
            var pullOffset = request.QueueOffset;

            //如果消费者第一次过来拉取消息,则计算下一个应该拉取的位置,并返回给消费者
            if (pullOffset < 0)
            {
                var nextConsumeOffset = GetNextConsumeOffset(topic, queueId, request.ConsumerGroup, request.ConsumeFromWhere);
                return BuildNextOffsetResetResponse(remotingRequest, nextConsumeOffset);
            }

            //尝试拉取消息
            var messages = _messageService.GetMessages(topic, queueId, pullOffset, request.PullMessageBatchSize);

            //如果消息存在,则返回消息
            if (messages.Count() > 0)
            {
                return BuildFoundResponse(remotingRequest, messages);
            }

            //消息不存在,如果挂起时间大于0,则挂起请求
            if (request.SuspendPullRequestMilliseconds > 0)
            {
                var pullRequest = new PullRequest(
                    remotingRequest,
                    request,
                    context,
                    DateTime.Now,
                    request.SuspendPullRequestMilliseconds,
                    ExecutePullRequest,
                    ExecutePullRequest,
                    ExecuteReplacedPullRequest);
                _suspendedPullRequestManager.SuspendPullRequest(pullRequest);
                return null;
            }

            var queueMinOffset = _queueService.GetQueueMinOffset(topic, queueId);
            var queueCurrentOffset = _queueService.GetQueueCurrentOffset(topic, queueId);

            if (pullOffset < queueMinOffset)
            {
                return BuildNextOffsetResetResponse(remotingRequest, queueMinOffset);
            }
            else if (pullOffset > queueCurrentOffset + 1)
            {
                return BuildNextOffsetResetResponse(remotingRequest, queueCurrentOffset + 1);
            }
            else
            {
                return BuildNoNewMessageResponse(remotingRequest);
            }
        }
        public RemotingResponse HandleRequest(IRequestHandlerContext context, RemotingRequest request)
        {
            var pullMessageRequest = _binarySerializer.Deserialize<PullMessageRequest>(request.Body);
            if (pullMessageRequest.QueueOffset < 0)
            {
                var lastConsumedQueueOffset = _offsetManager.GetQueueOffset(
                    pullMessageRequest.MessageQueue.Topic,
                    pullMessageRequest.MessageQueue.QueueId,
                    pullMessageRequest.ConsumerGroup);
                var queueCurrentOffset = _messageService.GetQueueCurrentOffset(
                    pullMessageRequest.MessageQueue.Topic,
                    pullMessageRequest.MessageQueue.QueueId);

                var nextQueueOffset = lastConsumedQueueOffset + 1;
                if (lastConsumedQueueOffset == -1)
                {
                    nextQueueOffset = queueCurrentOffset + 1;
                }

                var response = new PullMessageResponse(new QueueMessage[0], nextQueueOffset);
                var responseData = _binarySerializer.Serialize(response);
                return new RemotingResponse((int)PullStatus.NextOffsetReset, request.Sequence, responseData);
            }
            var messages = _messageService.GetMessages(
                pullMessageRequest.MessageQueue.Topic,
                pullMessageRequest.MessageQueue.QueueId,
                pullMessageRequest.QueueOffset,
                pullMessageRequest.PullMessageBatchSize);
            if (messages.Count() > 0)
            {
                var pullMessageResponse = new PullMessageResponse(messages);
                var responseData = _binarySerializer.Serialize(pullMessageResponse);
                return new RemotingResponse((int)PullStatus.Found, request.Sequence, responseData);
            }
            else
            {
                var pullRequest = new PullRequest(
                    request.Sequence,
                    pullMessageRequest,
                    context,
                    DateTime.Now,
                    _brokerController.Setting.SuspendPullRequestMilliseconds,
                    ExecutePullRequest,
                    ExecutePullRequest,
                    ExecuteReplacedPullRequest);
                _brokerController.SuspendedPullRequestManager.SuspendPullRequest(pullRequest);
                return null;
            }
        }
 private void ExecutePullRequest(PullRequest pullRequest)
 {
     var consumerGroup = _brokerController.ConsumerManager.GetConsumerGroup(pullRequest.PullMessageRequest.ConsumerGroup);
     if (consumerGroup != null && consumerGroup.IsConsumerChannelActive(pullRequest.RequestHandlerContext.Channel.RemotingAddress))
     {
         var pullMessageRequest = pullRequest.PullMessageRequest;
         var messages = _messageService.GetMessages(
             pullMessageRequest.MessageQueue.Topic,
             pullMessageRequest.MessageQueue.QueueId,
             pullMessageRequest.QueueOffset,
             pullMessageRequest.PullMessageBatchSize);
         var pullMessageResponse = new PullMessageResponse(messages);
         var responseData = _binarySerializer.Serialize(pullMessageResponse);
         var remotingResponse = new RemotingResponse(messages.Count() > 0 ? (int)PullStatus.Found : (int)PullStatus.NoNewMessage, pullRequest.RemotingRequestSequence, responseData);
         pullRequest.RequestHandlerContext.SendRemotingResponse(remotingResponse);
     }
 }
 public void SuspendPullRequest(PullRequest pullRequest)
 {
     var key = BuildKey(pullRequest.PullMessageRequest.MessageQueue.Topic, pullRequest.PullMessageRequest.MessageQueue.QueueId);
     var changed = false;
     var existingRequest = default(PullRequest);
     _queueRequestDict.AddOrUpdate(key, pullRequest, (x, request) =>
     {
         existingRequest = request;
         changed = true;
         return pullRequest;
     });
     if (changed && existingRequest != null)
     {
         var currentRequest = existingRequest;
         Task.Factory.StartNew(() => currentRequest.ReplacedAction(currentRequest));
     }
 }
        public void SuspendPullRequest(PullRequest pullRequest)
        {
            var pullMessageRequest = pullRequest.PullMessageRequest;
            var key = BuildKey(pullMessageRequest.MessageQueue.Topic, pullMessageRequest.MessageQueue.QueueId, pullMessageRequest.ConsumerGroup);
            var changed = false;
            var existingRequest = default(PullRequest);

            var currentPullRequest = _queueRequestDict.AddOrUpdate(key, x =>
            {
                _logger.DebugFormat("Added new PullRequest, Id:{0}, RequestSequence:{6}, SuspendStartTime:{1}, ConsumerGroup:{2}, Topic:{3}, QueueId:{4}, QueueOffset:{5}",
                    pullRequest.Id,
                    pullRequest.SuspendStartTime,
                    pullRequest.PullMessageRequest.ConsumerGroup,
                    pullRequest.PullMessageRequest.MessageQueue.Topic,
                    pullRequest.PullMessageRequest.MessageQueue.QueueId,
                    pullRequest.PullMessageRequest.QueueOffset,
                    pullRequest.RemotingRequestSequence);
                return pullRequest;
            }, (x, request) =>
            {
                existingRequest = request;
                changed = true;
                return pullRequest;
            });

            CheckNewMessageExist(key, currentPullRequest.PullMessageRequest.MessageQueue.Topic, currentPullRequest.PullMessageRequest.MessageQueue.QueueId, currentPullRequest.PullMessageRequest.QueueOffset);

            if (changed && existingRequest != null)
            {
                _logger.DebugFormat("Replaced existing PullRequest, new PullRequest Id:{0}, RequestSequence:{6}, SuspendStartTime:{1}, ConsumerGroup:{2}, Topic:{3}, QueueId:{4}, QueueOffset:{5}",
                    existingRequest.Id,
                    existingRequest.SuspendStartTime,
                    existingRequest.PullMessageRequest.ConsumerGroup,
                    existingRequest.PullMessageRequest.MessageQueue.Topic,
                    existingRequest.PullMessageRequest.MessageQueue.QueueId,
                    existingRequest.PullMessageRequest.QueueOffset,
                    pullRequest.RemotingRequestSequence);

                var currentRequest = existingRequest;
                _taskFactory.StartNew(() => currentRequest.ReplacedAction(currentRequest));
            }
        }
        public void SuspendPullRequest(PullRequest pullRequest)
        {
            var pullMessageRequest = pullRequest.PullMessageRequest;
            var key = BuildKey(pullMessageRequest.MessageQueue.Topic, pullMessageRequest.MessageQueue.QueueId, pullMessageRequest.ConsumerGroup);

            var existingRequest = default(PullRequest);
            var currentPullRequest = _queueRequestDict.AddOrUpdate(key, x =>
            {
                return pullRequest;
            }, (x, request) =>
            {
                existingRequest = request;
                return pullRequest;
            });

            if (existingRequest != null)
            {
                var currentRequest = existingRequest;
                _taskFactory.StartNew(() => currentRequest.ReplacedAction(currentRequest));
            }
        }
        public RemotingResponse HandleRequest(IRequestHandlerContext context, RemotingRequest remotingRequest)
        {
            if (BrokerController.Instance.IsCleaning)
            {
                return BuildBrokerIsCleaningResponse(remotingRequest);
            }

            var request = DeserializePullMessageRequest(remotingRequest.Body);
            var topic = request.MessageQueue.Topic;
            var tags = request.Tags;
            var queueId = request.MessageQueue.QueueId;
            var pullOffset = request.QueueOffset;

            //如果消费者第一次过来拉取消息,则计算下一个应该拉取的位置,并返回给消费者
            var nextConsumeOffset = 0L;
            if (pullOffset < 0)
            {
                nextConsumeOffset = GetNextConsumeOffset(topic, queueId, request.ConsumerGroup, request.ConsumeFromWhere);
                return BuildNextOffsetResetResponse(remotingRequest, nextConsumeOffset);
            }
            //如果用户人工指定了下次要拉取的位置,则返回该位置给消费者并清除该指定的位置
            else if (_offsetStore.TryFetchNextConsumeOffset(topic, queueId, request.ConsumerGroup, out nextConsumeOffset))
            {
                return BuildNextOffsetResetResponse(remotingRequest, nextConsumeOffset);
            }

            //尝试拉取消息
            var pullResult = PullMessages(topic, tags, queueId, pullOffset, request.PullMessageBatchSize);

            //处理消息拉取结果
            if (pullResult.Status == PullStatus.Found)
            {
                return BuildFoundResponse(remotingRequest, pullResult.Messages);
            }
            else if (pullResult.Status == PullStatus.NextOffsetReset)
            {
                return BuildNextOffsetResetResponse(remotingRequest, pullResult.NextBeginOffset);
            }
            else if (pullResult.Status == PullStatus.QueueNotExist)
            {
                return BuildQueueNotExistResponse(remotingRequest);
            }
            else if (pullResult.Status == PullStatus.NoNewMessage)
            {
                if (request.SuspendPullRequestMilliseconds > 0)
                {
                    var pullRequest = new PullRequest(
                        remotingRequest,
                        request,
                        context,
                        DateTime.Now,
                        request.SuspendPullRequestMilliseconds,
                        ExecutePullRequest,
                        ExecutePullRequest,
                        ExecuteNoNewMessagePullRequest,
                        ExecuteReplacedPullRequest);
                    _suspendedPullRequestManager.SuspendPullRequest(pullRequest);
                    return null;
                }
                return BuildNoNewMessageResponse(remotingRequest);
            }
            else
            {
                throw new Exception("Invalid pull result status.");
            }
        }
 private void SendRemotingResponse(PullRequest pullRequest, RemotingResponse remotingResponse)
 {
     pullRequest.RequestHandlerContext.SendRemotingResponse(remotingResponse);
 }
 private bool IsPullRequestValid(PullRequest pullRequest)
 {
     try
     {
         return _consumerManager.IsConsumerActive(pullRequest.PullMessageRequest.ConsumerGroup, pullRequest.PullMessageRequest.ConsumerId);
     }
     catch (ObjectDisposedException)
     {
         return false;
     }
 }
 private void ExecuteReplacedPullRequest(PullRequest pullRequest)
 {
     if (!IsPullRequestValid(pullRequest))
     {
         return;
     }
     SendRemotingResponse(pullRequest, BuildIgnoredResponse(pullRequest.RemotingRequest));
 }
        private void ExecutePullRequest(PullRequest pullRequest)
        {
            if (!IsPullRequestValid(pullRequest))
            {
                return;
            }

            var pullMessageRequest = pullRequest.PullMessageRequest;
            var topic = pullMessageRequest.MessageQueue.Topic;
            var queueId = pullMessageRequest.MessageQueue.QueueId;
            var pullOffset = pullMessageRequest.QueueOffset;
            var pullResult = PullMessages(topic, pullMessageRequest.Tags, queueId, pullOffset, pullMessageRequest.PullMessageBatchSize);
            var remotingRequest = pullRequest.RemotingRequest;

            if (pullResult.Status == PullStatus.Found)
            {
                SendRemotingResponse(pullRequest, BuildFoundResponse(pullRequest.RemotingRequest, pullResult.Messages));
            }
            else if (pullResult.Status == PullStatus.NextOffsetReset)
            {
                SendRemotingResponse(pullRequest, BuildNextOffsetResetResponse(remotingRequest, pullResult.NextBeginOffset));
            }
            else if (pullResult.Status == PullStatus.QueueNotExist)
            {
                SendRemotingResponse(pullRequest, BuildQueueNotExistResponse(remotingRequest));
            }
            else if (pullResult.Status == PullStatus.NoNewMessage)
            {
                SendRemotingResponse(pullRequest, BuildNoNewMessageResponse(pullRequest.RemotingRequest));
            }
        }
 private void ExecuteNoNewMessagePullRequest(PullRequest pullRequest)
 {
     if (!IsPullRequestValid(pullRequest))
     {
         return;
     }
     SendRemotingResponse(pullRequest, BuildNoNewMessageResponse(pullRequest.RemotingRequest));
 }
 private void ExecuteReplacedPullRequest(PullRequest pullRequest)
 {
     var consumerGroup = _brokerController.ConsumerManager.GetConsumerGroup(pullRequest.PullMessageRequest.ConsumerGroup);
     if (consumerGroup != null && consumerGroup.IsConsumerChannelActive(pullRequest.RequestHandlerContext.Channel.RemotingAddress))
     {
         var responseData = _binarySerializer.Serialize(new PullMessageResponse(new QueueMessage[0]));
         var remotingResponse = new RemotingResponse((int)PullStatus.Ignored, pullRequest.RemotingRequestSequence, responseData);
         pullRequest.RequestHandlerContext.SendRemotingResponse(remotingResponse);
     }
 }
 private bool IsPullRequestValid(PullRequest pullRequest)
 {
     var consumerGroup = _consumerManager.GetConsumerGroup(pullRequest.PullMessageRequest.ConsumerGroup);
     return consumerGroup != null && consumerGroup.IsConsumerActive(pullRequest.RequestHandlerContext.Connection.RemotingEndPoint.ToString());
 }
        private void ExecutePullRequest(PullRequest pullRequest)
        {
            if (!IsPullRequestValid(pullRequest))
            {
                return;
            }

            var pullMessageRequest = pullRequest.PullMessageRequest;
            var topic = pullMessageRequest.MessageQueue.Topic;
            var queueId = pullMessageRequest.MessageQueue.QueueId;
            var pullOffset = pullMessageRequest.QueueOffset;

            var messages = _messageService.GetMessages(topic, queueId, pullOffset, pullMessageRequest.PullMessageBatchSize);

            if (messages.Count() > 0)
            {
                SendRemotingResponse(pullRequest, BuildFoundResponse(pullRequest.RemotingRequest, messages));
                return;
            }

            var queueMinOffset = _queueService.GetQueueMinOffset(topic, queueId);
            var queueCurrentOffset = _queueService.GetQueueCurrentOffset(topic, queueId);

            if (pullOffset < queueMinOffset)
            {
                SendRemotingResponse(pullRequest, BuildNextOffsetResetResponse(pullRequest.RemotingRequest, queueMinOffset));
            }
            else if (pullOffset > queueCurrentOffset + 1)
            {
                SendRemotingResponse(pullRequest, BuildNextOffsetResetResponse(pullRequest.RemotingRequest, queueCurrentOffset + 1));
            }
            else
            {
                SendRemotingResponse(pullRequest, BuildNoNewMessageResponse(pullRequest.RemotingRequest));
            }
        }