| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include "DefaultMQPushConsumerImpl.h" |
| |
| #ifndef WIN32 |
| #include <signal.h> |
| #endif |
| |
| #include "CommunicationMode.h" |
| #include "ConsumeMsgService.h" |
| #include "protocol/body/ConsumerRunningInfo.h" |
| #include "FilterAPI.hpp" |
| #include "Logging.h" |
| #include "MQAdminImpl.h" |
| #include "MQClientAPIImpl.h" |
| #include "MQClientInstance.h" |
| #include "MQClientManager.h" |
| #include "MQProtos.h" |
| #include "NamespaceUtil.h" |
| #include "LocalFileOffsetStore.h" |
| #include "PullAPIWrapper.h" |
| #include "PullMessageService.hpp" |
| #include "PullSysFlag.h" |
| #include "RebalancePushImpl.h" |
| #include "RemoteBrokerOffsetStore.h" |
| #include "SocketUtil.h" |
| #include "UtilAll.h" |
| #include "Validators.h" |
| |
| static const long BROKER_SUSPEND_MAX_TIME_MILLIS = 1000 * 15; |
| static const long CONSUMER_TIMEOUT_MILLIS_WHEN_SUSPEND = 1000 * 30; |
| |
| namespace rocketmq { |
| |
| class DefaultMQPushConsumerImpl::AsyncPullCallback : public AutoDeletePullCallback { |
| public: |
| AsyncPullCallback(DefaultMQPushConsumerImplPtr pushConsumer, |
| PullRequestPtr request, |
| SubscriptionData* subscriptionData) |
| : default_mq_push_consumer_(pushConsumer), pull_request_(request), subscription_data_(subscriptionData) {} |
| |
| ~AsyncPullCallback() = default; |
| |
| void onSuccess(std::unique_ptr<PullResult> pull_result) override { |
| auto consumer = default_mq_push_consumer_.lock(); |
| if (nullptr == consumer) { |
| LOG_WARN_NEW("AsyncPullCallback::onSuccess: DefaultMQPushConsumerImpl is released."); |
| return; |
| } |
| |
| pull_result = consumer->pull_api_wrapper_->processPullResult(pull_request_->message_queue(), std::move(pull_result), |
| subscription_data_); |
| switch (pull_result->pull_status()) { |
| case FOUND: { |
| int64_t prev_request_offset = pull_request_->next_offset(); |
| pull_request_->set_next_offset(pull_result->next_begin_offset()); |
| |
| int64_t first_msg_offset = (std::numeric_limits<int64_t>::max)(); |
| if (!pull_result->msg_found_list().empty()) { |
| first_msg_offset = pull_result->msg_found_list()[0]->queue_offset(); |
| |
| pull_request_->process_queue()->putMessage(pull_result->msg_found_list()); |
| consumer->consume_service_->submitConsumeRequest( |
| pull_result->msg_found_list(), pull_request_->process_queue(), pull_request_->message_queue(), true); |
| } |
| |
| consumer->executePullRequestImmediately(pull_request_); |
| |
| if (pull_result->next_begin_offset() < prev_request_offset || first_msg_offset < prev_request_offset) { |
| LOG_WARN_NEW( |
| "[BUG] pull message result maybe data wrong, nextBeginOffset:{} firstMsgOffset:{} prevRequestOffset:{}", |
| pull_result->next_begin_offset(), first_msg_offset, prev_request_offset); |
| } |
| } break; |
| case NO_NEW_MSG: |
| case NO_MATCHED_MSG: |
| pull_request_->set_next_offset(pull_result->next_begin_offset()); |
| consumer->correctTagsOffset(pull_request_); |
| consumer->executePullRequestImmediately(pull_request_); |
| break; |
| case NO_LATEST_MSG: |
| pull_request_->set_next_offset(pull_result->next_begin_offset()); |
| consumer->correctTagsOffset(pull_request_); |
| consumer->executePullRequestLater( |
| pull_request_, consumer->getDefaultMQPushConsumerConfig()->pull_time_delay_millis_when_exception()); |
| break; |
| case OFFSET_ILLEGAL: { |
| LOG_WARN_NEW("the pull request offset illegal, {} {}", pull_request_->toString(), pull_result->toString()); |
| |
| pull_request_->set_next_offset(pull_result->next_begin_offset()); |
| pull_request_->process_queue()->set_dropped(true); |
| |
| // update and persist offset, then removeProcessQueue |
| auto pull_request = pull_request_; |
| consumer->executeTaskLater( |
| [consumer, pull_request]() { |
| try { |
| consumer->getOffsetStore()->updateOffset(pull_request->message_queue(), pull_request->next_offset(), |
| false); |
| consumer->getOffsetStore()->persist(pull_request->message_queue()); |
| consumer->getRebalanceImpl()->removeProcessQueue(pull_request->message_queue()); |
| |
| LOG_WARN_NEW("fix the pull request offset, {}", pull_request->toString()); |
| } catch (std::exception& e) { |
| LOG_ERROR_NEW("executeTaskLater Exception: {}", e.what()); |
| } |
| }, |
| 10000); |
| } break; |
| default: |
| break; |
| } |
| } |
| |
| void onException(MQException& e) noexcept override { |
| auto consumer = default_mq_push_consumer_.lock(); |
| if (nullptr == consumer) { |
| LOG_WARN_NEW("AsyncPullCallback::onException: DefaultMQPushConsumerImpl is released."); |
| return; |
| } |
| |
| if (!UtilAll::isRetryTopic(pull_request_->message_queue().topic())) { |
| LOG_WARN_NEW("execute the pull request exception: {}", e.what()); |
| } |
| |
| // TODO |
| consumer->executePullRequestLater( |
| pull_request_, consumer->getDefaultMQPushConsumerConfig()->pull_time_delay_millis_when_exception()); |
| } |
| |
| private: |
| std::weak_ptr<DefaultMQPushConsumerImpl> default_mq_push_consumer_; |
| PullRequestPtr pull_request_; |
| SubscriptionData* subscription_data_; |
| }; |
| |
| DefaultMQPushConsumerImpl::DefaultMQPushConsumerImpl(DefaultMQPushConsumerConfigPtr config) |
| : DefaultMQPushConsumerImpl(config, nullptr) {} |
| |
| DefaultMQPushConsumerImpl::DefaultMQPushConsumerImpl(DefaultMQPushConsumerConfigPtr config, RPCHookPtr rpcHook) |
| : MQClientImpl(config, rpcHook), |
| start_time_(UtilAll::currentTimeMillis()), |
| pause_(false), |
| consume_orderly_(false), |
| message_listener_(nullptr), |
| consume_service_(nullptr), |
| rebalance_impl_(new RebalancePushImpl(this)), |
| pull_api_wrapper_(nullptr), |
| offset_store_(nullptr) {} |
| |
| DefaultMQPushConsumerImpl::~DefaultMQPushConsumerImpl() = default; |
| |
| void DefaultMQPushConsumerImpl::start() { |
| #ifndef WIN32 |
| /* Ignore the SIGPIPE */ |
| struct sigaction sa; |
| memset(&sa, 0, sizeof(struct sigaction)); |
| sa.sa_handler = SIG_IGN; |
| sa.sa_flags = 0; |
| ::sigaction(SIGPIPE, &sa, 0); |
| #endif |
| |
| switch (service_state_) { |
| case CREATE_JUST: { |
| // wrap namespace |
| client_config_->set_group_name( |
| NamespaceUtil::wrapNamespace(client_config_->name_space(), client_config_->group_name())); |
| |
| LOG_INFO_NEW("the consumer [{}] start beginning.", client_config_->group_name()); |
| |
| service_state_ = START_FAILED; |
| |
| checkConfig(); |
| |
| copySubscription(); |
| |
| if (messageModel() == MessageModel::CLUSTERING) { |
| client_config_->changeInstanceNameToPID(); |
| } |
| |
| // init client_instance_ |
| MQClientImpl::start(); |
| |
| // init rebalance_impl_ |
| rebalance_impl_->set_consumer_group(client_config_->group_name()); |
| rebalance_impl_->set_message_model(getDefaultMQPushConsumerConfig()->message_model()); |
| rebalance_impl_->set_allocate_mq_strategy(getDefaultMQPushConsumerConfig()->allocate_mq_strategy()); |
| rebalance_impl_->set_client_instance(client_instance_.get()); |
| |
| // init pull_api_wrapper_ |
| pull_api_wrapper_.reset(new PullAPIWrapper(client_instance_.get(), client_config_->group_name())); |
| // TODO: registerFilterMessageHook |
| |
| // init offset_store_ |
| switch (getDefaultMQPushConsumerConfig()->message_model()) { |
| case MessageModel::BROADCASTING: |
| offset_store_.reset(new LocalFileOffsetStore(client_instance_.get(), client_config_->group_name())); |
| break; |
| case MessageModel::CLUSTERING: |
| offset_store_.reset(new RemoteBrokerOffsetStore(client_instance_.get(), client_config_->group_name())); |
| break; |
| } |
| offset_store_->load(); |
| |
| // checkConfig() guarantee message_listener_ is not nullptr |
| if (message_listener_->getMessageListenerType() == messageListenerOrderly) { |
| LOG_INFO_NEW("start orderly consume service: {}", client_config_->group_name()); |
| consume_orderly_ = true; |
| consume_service_.reset(new ConsumeMessageOrderlyService( |
| this, getDefaultMQPushConsumerConfig()->consume_thread_nums(), message_listener_)); |
| } else { |
| // for backward compatible, defaultly and concurrently listeners are allocating |
| // ConsumeMessageConcurrentlyService |
| LOG_INFO_NEW("start concurrently consume service: {}", client_config_->group_name()); |
| consume_orderly_ = false; |
| consume_service_.reset(new ConsumeMessageConcurrentlyService( |
| this, getDefaultMQPushConsumerConfig()->consume_thread_nums(), message_listener_)); |
| } |
| consume_service_->start(); |
| |
| // register consumer |
| bool registerOK = client_instance_->registerConsumer(client_config_->group_name(), this); |
| if (!registerOK) { |
| service_state_ = CREATE_JUST; |
| consume_service_->shutdown(); |
| THROW_MQEXCEPTION(MQClientException, "The cousumer group[" + client_config_->group_name() + |
| "] has been created before, specify another name please.", |
| -1); |
| } |
| |
| client_instance_->start(); |
| |
| LOG_INFO_NEW("the consumer [{}] start OK", client_config_->group_name()); |
| service_state_ = RUNNING; |
| break; |
| } |
| case RUNNING: |
| case START_FAILED: |
| case SHUTDOWN_ALREADY: |
| THROW_MQEXCEPTION(MQClientException, "The PushConsumer service state not OK, maybe started once", -1); |
| break; |
| default: |
| break; |
| } |
| |
| updateTopicSubscribeInfoWhenSubscriptionChanged(); |
| client_instance_->sendHeartbeatToAllBrokerWithLock(); |
| client_instance_->rebalanceImmediately(); |
| } |
| |
| void DefaultMQPushConsumerImpl::checkConfig() { |
| std::string groupname = client_config_->group_name(); |
| |
| // check consumerGroup |
| Validators::checkGroup(groupname); |
| |
| // consumerGroup |
| if (DEFAULT_CONSUMER_GROUP == groupname) { |
| THROW_MQEXCEPTION(MQClientException, |
| "consumerGroup can not equal " + DEFAULT_CONSUMER_GROUP + ", please specify another one.", -1); |
| } |
| |
| if (getDefaultMQPushConsumerConfig()->message_model() != BROADCASTING && |
| getDefaultMQPushConsumerConfig()->message_model() != CLUSTERING) { |
| THROW_MQEXCEPTION(MQClientException, "messageModel is valid", -1); |
| } |
| |
| // allocateMessageQueueStrategy |
| if (nullptr == getDefaultMQPushConsumerConfig()->allocate_mq_strategy()) { |
| THROW_MQEXCEPTION(MQClientException, "allocateMessageQueueStrategy is null", -1); |
| } |
| |
| // subscription |
| if (subscription_.empty()) { |
| THROW_MQEXCEPTION(MQClientException, "subscription is empty", -1); |
| } |
| |
| // messageListener |
| if (message_listener_ == nullptr) { |
| THROW_MQEXCEPTION(MQClientException, "messageListener is null", -1); |
| } |
| } |
| |
| void DefaultMQPushConsumerImpl::copySubscription() { |
| for (const auto& it : subscription_) { |
| LOG_INFO_NEW("buildSubscriptionData: {}, {}", it.first, it.second); |
| rebalance_impl_->setSubscriptionData(it.first, FilterAPI::buildSubscriptionData(it.first, it.second)); |
| } |
| |
| switch (getDefaultMQPushConsumerConfig()->message_model()) { |
| case BROADCASTING: |
| break; |
| case CLUSTERING: { |
| // auto subscript retry topic |
| std::string retryTopic = UtilAll::getRetryTopic(client_config_->group_name()); |
| rebalance_impl_->setSubscriptionData(retryTopic, FilterAPI::buildSubscriptionData(retryTopic, SUB_ALL)); |
| break; |
| } |
| default: |
| break; |
| } |
| } |
| |
| void DefaultMQPushConsumerImpl::updateTopicSubscribeInfoWhenSubscriptionChanged() { |
| auto& subTable = rebalance_impl_->getSubscriptionInner(); |
| for (const auto& it : subTable) { |
| const auto& topic = it.first; |
| auto topic_route_data = client_instance_->getTopicRouteData(topic); |
| if (topic_route_data != nullptr) { |
| std::vector<MQMessageQueue> subscribeInfo = |
| MQClientInstance::topicRouteData2TopicSubscribeInfo(topic, topic_route_data); |
| updateTopicSubscribeInfo(topic, subscribeInfo); |
| } else { |
| bool ret = client_instance_->updateTopicRouteInfoFromNameServer(topic); |
| if (!ret) { |
| LOG_WARN_NEW("The topic[{}] not exist, or its route data not changed", topic); |
| } |
| } |
| } |
| } |
| |
| void DefaultMQPushConsumerImpl::shutdown() { |
| switch (service_state_) { |
| case RUNNING: { |
| consume_service_->shutdown(); |
| persistConsumerOffset(); |
| client_instance_->unregisterConsumer(client_config_->group_name()); |
| client_instance_->shutdown(); |
| rebalance_impl_->destroy(); |
| service_state_ = SHUTDOWN_ALREADY; |
| LOG_INFO_NEW("the consumer [{}] shutdown OK", client_config_->group_name()); |
| break; |
| } |
| case CREATE_JUST: |
| case SHUTDOWN_ALREADY: |
| break; |
| default: |
| break; |
| } |
| } |
| |
| void DefaultMQPushConsumerImpl::suspend() { |
| pause_ = true; |
| LOG_INFO_NEW("suspend this consumer, {}", client_config_->group_name()); |
| } |
| |
| void DefaultMQPushConsumerImpl::resume() { |
| pause_ = false; |
| doRebalance(); |
| LOG_INFO_NEW("resume this consumer, {}", client_config_->group_name()); |
| } |
| |
| MQMessageListener* DefaultMQPushConsumerImpl::getMessageListener() const { |
| return message_listener_; |
| } |
| |
| void DefaultMQPushConsumerImpl::registerMessageListener(MessageListenerConcurrently* message_listener) { |
| if (nullptr != message_listener) { |
| message_listener_ = message_listener; |
| } |
| } |
| |
| void DefaultMQPushConsumerImpl::registerMessageListener(MessageListenerOrderly* message_listener) { |
| if (nullptr != message_listener) { |
| message_listener_ = message_listener; |
| } |
| } |
| |
| void DefaultMQPushConsumerImpl::subscribe(const std::string& topic, const std::string& subExpression) { |
| // TODO: change substation after start |
| subscription_[topic] = subExpression; |
| } |
| |
| std::vector<SubscriptionData> DefaultMQPushConsumerImpl::subscriptions() const { |
| std::vector<SubscriptionData> result; |
| auto& subTable = rebalance_impl_->getSubscriptionInner(); |
| for (const auto& it : subTable) { |
| result.push_back(*(it.second)); |
| } |
| return result; |
| } |
| |
| void DefaultMQPushConsumerImpl::updateTopicSubscribeInfo(const std::string& topic, std::vector<MQMessageQueue>& info) { |
| rebalance_impl_->setTopicSubscribeInfo(topic, info); |
| } |
| |
| void DefaultMQPushConsumerImpl::doRebalance() { |
| if (!pause_) { |
| rebalance_impl_->doRebalance(consume_orderly()); |
| } |
| } |
| |
| void DefaultMQPushConsumerImpl::executePullRequestLater(PullRequestPtr pullRequest, long timeDelay) { |
| client_instance_->getPullMessageService()->executePullRequestLater(pullRequest, timeDelay); |
| } |
| |
| void DefaultMQPushConsumerImpl::executePullRequestImmediately(PullRequestPtr pullRequest) { |
| client_instance_->getPullMessageService()->executePullRequestImmediately(pullRequest); |
| } |
| |
| void DefaultMQPushConsumerImpl::pullMessage(PullRequestPtr pull_request) { |
| if (nullptr == pull_request) { |
| LOG_ERROR("PullRequest is NULL, return"); |
| return; |
| } |
| |
| auto process_queue = pull_request->process_queue(); |
| if (process_queue->dropped()) { |
| LOG_WARN_NEW("the pull request[{}] is dropped.", pull_request->toString()); |
| return; |
| } |
| |
| process_queue->set_last_pull_timestamp(UtilAll::currentTimeMillis()); |
| |
| int cachedMessageCount = process_queue->getCacheMsgCount(); |
| if (cachedMessageCount > getDefaultMQPushConsumerConfig()->pull_threshold_for_queue()) { |
| // too many message in cache, wait to process |
| executePullRequestLater(pull_request, 1000); |
| return; |
| } |
| |
| if (consume_orderly()) { |
| if (process_queue->locked()) { |
| if (!pull_request->locked_first()) { |
| const auto offset = rebalance_impl_->computePullFromWhere(pull_request->message_queue()); |
| bool brokerBusy = offset < pull_request->next_offset(); |
| LOG_INFO_NEW( |
| "the first time to pull message, so fix offset from broker. pullRequest: {} NewOffset: {} brokerBusy: {}", |
| pull_request->toString(), offset, UtilAll::to_string(brokerBusy)); |
| if (brokerBusy) { |
| LOG_INFO_NEW( |
| "[NOTIFYME] the first time to pull message, but pull request offset larger than broker consume offset. " |
| "pullRequest: {} NewOffset: {}", |
| pull_request->toString(), offset); |
| } |
| |
| pull_request->set_locked_first(true); |
| pull_request->set_next_offset(offset); |
| } |
| } else { |
| executePullRequestLater(pull_request, getDefaultMQPushConsumerConfig()->pull_time_delay_millis_when_exception()); |
| LOG_INFO_NEW("pull message later because not locked in broker, {}", pull_request->toString()); |
| return; |
| } |
| } |
| |
| const auto& message_queue = pull_request->message_queue(); |
| SubscriptionData* subscription_data = rebalance_impl_->getSubscriptionData(message_queue.topic()); |
| if (nullptr == subscription_data) { |
| executePullRequestLater(pull_request, getDefaultMQPushConsumerConfig()->pull_time_delay_millis_when_exception()); |
| LOG_WARN_NEW("find the consumer's subscription failed, {}", pull_request->toString()); |
| return; |
| } |
| |
| bool commitOffsetEnable = false; |
| int64_t commitOffsetValue = 0; |
| if (CLUSTERING == getDefaultMQPushConsumerConfig()->message_model()) { |
| commitOffsetValue = offset_store_->readOffset(message_queue, READ_FROM_MEMORY); |
| if (commitOffsetValue > 0) { |
| commitOffsetEnable = true; |
| } |
| } |
| |
| const auto& subExpression = subscription_data->sub_string(); |
| |
| int sysFlag = PullSysFlag::buildSysFlag(commitOffsetEnable, // commitOffset |
| true, // suspend |
| !subExpression.empty(), // subscription |
| false); // class filter |
| |
| try { |
| std::unique_ptr<AsyncPullCallback> callback( |
| new AsyncPullCallback(shared_from_this(), pull_request, subscription_data)); |
| |
| pull_api_wrapper_->pullKernelImpl(message_queue, // mq |
| subExpression, // subExpression |
| subscription_data->expression_type(), // expressionType |
| subscription_data->sub_version(), // subVersion |
| pull_request->next_offset(), // offset |
| getDefaultMQPushConsumerConfig()->pull_batch_size(), // maxNums |
| sysFlag, // sysFlag |
| commitOffsetValue, // commitOffset |
| BROKER_SUSPEND_MAX_TIME_MILLIS, // brokerSuspendMaxTimeMillis |
| CONSUMER_TIMEOUT_MILLIS_WHEN_SUSPEND, // timeoutMillis |
| CommunicationMode::ASYNC, // communicationMode |
| callback.get()); // pullCallback |
| |
| (void)callback.release(); |
| } catch (MQException& e) { |
| LOG_ERROR_NEW("pullKernelImpl exception: {}", e.what()); |
| executePullRequestLater(pull_request, getDefaultMQPushConsumerConfig()->pull_time_delay_millis_when_exception()); |
| } |
| } |
| |
| void DefaultMQPushConsumerImpl::correctTagsOffset(PullRequestPtr pullRequest) { |
| if (0L == pullRequest->process_queue()->getCacheMsgCount()) { |
| offset_store_->updateOffset(pullRequest->message_queue(), pullRequest->next_offset(), true); |
| } |
| } |
| |
| void DefaultMQPushConsumerImpl::executeTaskLater(const handler_type& task, long timeDelay) { |
| client_instance_->getPullMessageService()->executeTaskLater(task, timeDelay); |
| } |
| |
| void DefaultMQPushConsumerImpl::resetRetryAndNamespace(const std::vector<MessageExtPtr>& msgs) { |
| std::string retry_topic = UtilAll::getRetryTopic(groupName()); |
| for (auto& msg : msgs) { |
| std::string group_topic = msg->getProperty(MQMessageConst::PROPERTY_RETRY_TOPIC); |
| if (!group_topic.empty() && retry_topic == msg->topic()) { |
| msg->set_topic(group_topic); |
| } |
| } |
| |
| const auto& name_space = client_config_->name_space(); |
| if (!name_space.empty()) { |
| for (auto& msg : msgs) { |
| msg->set_topic(NamespaceUtil::withoutNamespace(msg->topic(), name_space)); |
| } |
| } |
| } |
| |
| bool DefaultMQPushConsumerImpl::sendMessageBack(MessageExtPtr msg, int delay_level) { |
| return sendMessageBack(msg, delay_level, null); |
| } |
| |
| bool DefaultMQPushConsumerImpl::sendMessageBack(MessageExtPtr msg, int delay_level, const std::string& brokerName) { |
| try { |
| msg->set_topic(NamespaceUtil::wrapNamespace(client_config_->name_space(), msg->topic())); |
| |
| std::string brokerAddr = |
| brokerName.empty() ? msg->store_host_string() : client_instance_->findBrokerAddressInPublish(brokerName); |
| |
| client_instance_->getMQClientAPIImpl()->consumerSendMessageBack( |
| brokerAddr, msg, getDefaultMQPushConsumerConfig()->group_name(), delay_level, 5000, |
| getDefaultMQPushConsumerConfig()->max_reconsume_times()); |
| return true; |
| } catch (const std::exception& e) { |
| LOG_ERROR_NEW("sendMessageBack exception, group: {}, msg: {}. {}", getDefaultMQPushConsumerConfig()->group_name(), |
| msg->toString(), e.what()); |
| } |
| return false; |
| } |
| |
| void DefaultMQPushConsumerImpl::persistConsumerOffset() { |
| if (isServiceStateOk()) { |
| std::vector<MQMessageQueue> mqs = rebalance_impl_->getAllocatedMQ(); |
| offset_store_->persistAll(mqs); |
| } |
| } |
| |
| void DefaultMQPushConsumerImpl::updateConsumeOffset(const MQMessageQueue& mq, int64_t offset) { |
| if (offset >= 0) { |
| offset_store_->updateOffset(mq, offset, false); |
| } else { |
| LOG_ERROR_NEW("updateConsumeOffset of mq:{} error", mq.toString()); |
| } |
| } |
| |
| std::unique_ptr<ConsumerRunningInfo> DefaultMQPushConsumerImpl::consumerRunningInfo() { |
| std::unique_ptr<ConsumerRunningInfo> info(new ConsumerRunningInfo()); |
| |
| info->setProperty(ConsumerRunningInfo::PROP_CONSUME_ORDERLY, UtilAll::to_string(consume_orderly_)); |
| info->setProperty(ConsumerRunningInfo::PROP_THREADPOOL_CORE_SIZE, |
| UtilAll::to_string(getDefaultMQPushConsumerConfig()->consume_thread_nums())); |
| info->setProperty(ConsumerRunningInfo::PROP_CONSUMER_START_TIMESTAMP, UtilAll::to_string(start_time_)); |
| |
| auto sub_set = subscriptions(); |
| info->setSubscriptionSet(sub_set); |
| |
| auto processQueueTable = rebalance_impl_->getProcessQueueTable(); |
| for (const auto& it : processQueueTable) { |
| const auto& mq = it.first; |
| const auto& pq = it.second; |
| |
| ProcessQueueInfo pq_info; |
| pq_info.setCommitOffset(offset_store_->readOffset(mq, MEMORY_FIRST_THEN_STORE)); |
| pq->fillProcessQueueInfo(pq_info); |
| info->setMqTable(mq, pq_info); |
| } |
| |
| // TODO: ConsumeStatus |
| |
| return info; |
| } |
| |
| const std::string& DefaultMQPushConsumerImpl::groupName() const { |
| return client_config_->group_name(); |
| } |
| |
| MessageModel DefaultMQPushConsumerImpl::messageModel() const { |
| return getDefaultMQPushConsumerConfig()->message_model(); |
| }; |
| |
| ConsumeType DefaultMQPushConsumerImpl::consumeType() const { |
| return CONSUME_PASSIVELY; |
| } |
| |
| ConsumeFromWhere DefaultMQPushConsumerImpl::consumeFromWhere() const { |
| return getDefaultMQPushConsumerConfig()->consume_from_where(); |
| } |
| |
| } // namespace rocketmq |