This is an automated email from the ASF dual-hosted git repository.
lizhimins pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/rocketmq.git
The following commit(s) were added to refs/heads/develop by this push:
new 45254d5e13 [ISSUE #10615] Fix missing long-polling notification under
CombineConsumeQueue selective double-write (#10616)
45254d5e13 is described below
commit 45254d5e13e965b8bdece6101ef42fb38472cd89
Author: imzs <[email protected]>
AuthorDate: Tue Jul 14 13:39:34 2026 +0800
[ISSUE #10615] Fix missing long-polling notification under
CombineConsumeQueue selective double-write (#10616)
---
.../apache/rocketmq/store/DefaultMessageStore.java | 36 +++++++++++++++-------
.../apache/rocketmq/store/RocksDBMessageStore.java | 11 +++++++
.../store/queue/RocksDBConsumeQueueStore.java | 1 -
3 files changed, 36 insertions(+), 12 deletions(-)
diff --git
a/store/src/main/java/org/apache/rocketmq/store/DefaultMessageStore.java
b/store/src/main/java/org/apache/rocketmq/store/DefaultMessageStore.java
index aee767dae2..64ce41e47d 100644
--- a/store/src/main/java/org/apache/rocketmq/store/DefaultMessageStore.java
+++ b/store/src/main/java/org/apache/rocketmq/store/DefaultMessageStore.java
@@ -164,8 +164,6 @@ public class DefaultMessageStore implements MessageStore {
private volatile boolean shutdown = true;
- private boolean notifyMessageArriveInBatch = false;
-
protected StoreCheckpoint storeCheckpoint;
private MessageRocksDBStorage messageRocksDBStorage;
private TimerMessageStore timerMessageStore;
@@ -2746,7 +2744,7 @@ public class DefaultMessageStore implements MessageStore {
currentReputTimestamp =
dispatchRequest.getStoreTimestamp();
DefaultMessageStore.this.doDispatch(dispatchRequest);
- if (!notifyMessageArriveInBatch) {
+ if (isNotifyMessageArriveWhenReput()) {
notifyMessageArriveIfNecessary(dispatchRequest);
}
@@ -3208,6 +3206,30 @@ public class DefaultMessageStore implements MessageStore
{
this.defaultStoreMetricsManager.init(meter, attributesBuilderSupplier,
this);
}
+ /**
+ * Decide whether long-polling consumers should be notified during reput.
+ * <p>
+ * Notification is only safe when the consume queue is updated
synchronously in the reput dispatch:
+ * <ul>
+ * <li>a plain file-based {@link ConsumeQueueStore}, which is always
written synchronously;</li>
+ * <li>a {@link CombineConsumeQueueStore} with selective double-write
enabled, where the
+ * file-based store acts as both the assign-offset and read store and
is written
+ * synchronously, while RocksDB CQ is built asynchronously for only
part of the topics.</li>
+ * </ul>
+ * In other cases (e.g. reading from RocksDB CQ) the notification is
handled by
+ * {@code RocksGroupCommitService} after the CQ is committed, so we can
skip it here.
+ */
+ public boolean isNotifyMessageArriveWhenReput() {
+ if (consumeQueueStore instanceof ConsumeQueueStore) {
+ return true;
+ }
+ if (consumeQueueStore instanceof CombineConsumeQueueStore
+ && messageStoreConfig.isRocksdbCQSelectiveDoubleWriteEnable()) {
+ return true;
+ }
+ return false;
+ }
+
/**
* Enable transient commitLog store pool only if transientStorePoolEnable
is true and broker role is not SLAVE or
* enableControllerMode is true
@@ -3249,14 +3271,6 @@ public class DefaultMessageStore implements MessageStore
{
return this.messageRocksDBStorage;
}
- public boolean isNotifyMessageArriveInBatch() {
- return notifyMessageArriveInBatch;
- }
-
- public void setNotifyMessageArriveInBatch(boolean
notifyMessageArriveInBatch) {
- this.notifyMessageArriveInBatch = notifyMessageArriveInBatch;
- }
-
public DefaultStoreMetricsManager getDefaultStoreMetricsManager() {
return defaultStoreMetricsManager;
}
diff --git
a/store/src/main/java/org/apache/rocketmq/store/RocksDBMessageStore.java
b/store/src/main/java/org/apache/rocketmq/store/RocksDBMessageStore.java
index 0983dee7f9..4757ac4f68 100644
--- a/store/src/main/java/org/apache/rocketmq/store/RocksDBMessageStore.java
+++ b/store/src/main/java/org/apache/rocketmq/store/RocksDBMessageStore.java
@@ -37,4 +37,15 @@ public class RocksDBMessageStore extends DefaultMessageStore
{
public ConsumeQueueStoreInterface createConsumeQueueStore() {
return new RocksDBConsumeQueueStore(this);
}
+
+ /**
+ * RocksDB consume queue is built asynchronously by {@code
RocksGroupCommitService}, which is
+ * responsible for notifying long-polling consumers once the CQ is
committed. Therefore, we must
+ * not notify during reput, otherwise consumers could be woken up before
the message is visible
+ * in the consume queue.
+ */
+ @Override
+ public boolean isNotifyMessageArriveWhenReput() {
+ return false;
+ }
}
diff --git
a/store/src/main/java/org/apache/rocketmq/store/queue/RocksDBConsumeQueueStore.java
b/store/src/main/java/org/apache/rocketmq/store/queue/RocksDBConsumeQueueStore.java
index 8573ae8147..2ead65ab64 100644
---
a/store/src/main/java/org/apache/rocketmq/store/queue/RocksDBConsumeQueueStore.java
+++
b/store/src/main/java/org/apache/rocketmq/store/queue/RocksDBConsumeQueueStore.java
@@ -104,7 +104,6 @@ public class RocksDBConsumeQueueStore extends
AbstractConsumeQueueStore {
*/
public RocksDBConsumeQueueStore(DefaultMessageStore messageStore) {
super(messageStore);
- messageStore.setNotifyMessageArriveInBatch(true);
String root = messageStoreConfig.getStorePathRootDir();
File checkFile;