From bb6e7c58161ac441a9b9a68da5e765ea5a7942d5 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Wed, 09 Sep 2026 07:15:42 +0000
Subject: [PATCH] [#918] Record a ReplicaOfflineMsg as sent only when it really was published (#946)

---
 opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChanges.java |   17 ++++++++++++++---
 1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChanges.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChanges.java
index 8ebba8c..d718937 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChanges.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChanges.java
@@ -123,9 +123,17 @@
   }
 
   /**
-   * Add a replica offline message to the pending list.
+   * Add a replica offline message to the pending list and publish it, if the changes which
+   * come before it have all been published.
+   * <p>
+   * The message carries the newest CSN of the replica, so a change which is still in flight
+   * holds it back - and there is nobody left to publish it afterwards: the caller announces
+   * the replica offline while its service is being disabled, and the broker stops right after.
+   * Such a message is given up on rather than left queued, so that it is neither reported as
+   * sent nor published later on the session which follows.
    *
-   * @return the CSN of the message which was added
+   * @return the CSN of the message which was published, or {@code null} if it could not be
+   *         published
    */
   public synchronized CSN putReplicaOfflineMsg()
   {
@@ -136,7 +144,10 @@
 
     pendingChanges.put(offlineCSN, pendingChange);
     pushCommittedChanges();
-    return offlineCSN;
+    // pushCommittedChanges() removes whatever it published, so the message is still listed
+    // here if and only if a change before it held it back.
+    final boolean heldBack = pendingChanges.remove(offlineCSN) != null;
+    return heldBack ? null : offlineCSN;
   }
 
   /**

--
Gitblit v1.10.0