From c6b483127f13fc7d96dbc90c5157ab113ac12973 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Wed, 16 Sep 2026 10:07:08 +0000
Subject: [PATCH] [#925] Keep asking for a session restart until it has run (#981)

---
 opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ReplayDuringImportTest.java |   41 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ReplayDuringImportTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ReplayDuringImportTest.java
index 3bedecb..3dc590f 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ReplayDuringImportTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ReplayDuringImportTest.java
@@ -63,6 +63,9 @@
  * one thing it must not do is stop the session the import is reading (issue #956). The same
  * holds from the moment the total update is asked for: the answer to the request arrives
  * over that session, so a replay which fails while it is on its way must not restart it.
+ * A restart asked for before the total update took the session, and left standing for the
+ * length of it, is not run once it is over either: the change it was asked for is gone with
+ * the ServerState the import replaced.
  * <p>
  * The exporter is a broker of this test, so that the test says when the entries arrive: the
  * change is replayed while the import is waiting for them - or, for the request, while the
@@ -285,6 +288,44 @@
   }
 
   /**
+   * A session restart which stood while the import ran was asked for by a replay thread
+   * for a change given back before the total update owned the session, and that change is
+   * forgotten with the pending changes when the imported data replaces the ServerState:
+   * the session started back at the end of the import asks for everything the imported
+   * state does not cover. Run, the request would stop that session once for a delivery
+   * which can not come. The request is made here by hand, in the place of one made
+   * between a replay thread's read of the owner and the import claiming the session.
+   * <p>
+   * The restart is the state checkpointer's to run, within its first tick after the total
+   * update has released the session, so the pin is that the failure it would meet is never
+   * spent: a restart which ran would have spent it, and would have left the session it
+   * stopped down.
+   */
+  @Test(timeOut = 120_000)
+  public void aRequestWhichStoodWhileTheImportRanIsNotRunOnceItIsOver() throws Exception
+  {
+    final String[] exported = exportedEntries();
+    startImportInto(exported.length);
+    domain.requestSessionRestart();
+    domain.failNextSessionRestarts(1);
+    try
+    {
+      finishImport(exported);
+
+      // Two ticks of the checkpointer: a request standing when the import ends is run on the first.
+      Thread.sleep(2000);
+      assertEquals(domain.getSessionRestartFailuresLeft(), 1, "the request which stood while"
+          + " the import ran was run against the session started back at its end");
+      assertTrue(domain.isConnected(), "the session started back at the end of the import"
+          + " was stopped for a request made before it");
+    }
+    finally
+    {
+      domain.failNextSessionRestarts(0);
+    }
+  }
+
+  /**
    * Has the exporter start a total update into this replica, and returns once the backend
    * of the domain is deregistered for it: from then on the import is reading the session,
    * and a change replayed here is replayed into no backend.

--
Gitblit v1.10.0