salvatorecampagna commented on code in PR #15378:
URL: https://github.com/apache/lucene/pull/15378#discussion_r2482342022


##########
lucene/core/src/java/org/apache/lucene/index/MergePolicy.java:
##########
@@ -939,4 +939,96 @@ static final class MergeReader {
       this.hardLiveDocs = hardLiveDocs;
     }
   }
+
+  /**
+   * Observer for merge operations returned by {@link 
IndexWriter#forceMergeDeletes(boolean)}.
+   * Provides methods to query merge status and wait for completion.
+   *
+   * <p>When no merges are needed, {@link #hasNewMerges()} returns {@code 
false} and {@link
+   * #numMerges()} returns 0. In this case, {@link #await()} returns {@code 
true} immediately since
+   * there is nothing to wait for.
+   *
+   * @lucene.experimental
+   */
+  public static final class MergeObserver {
+    private final MergePolicy.MergeSpecification spec;
+
+    MergeObserver(MergePolicy.MergeSpecification spec) {
+      this.spec = spec;
+    }
+
+    /**
+     * Returns the number of merges in this specification.
+     *
+     * @return number of merges, or 0 if no merges were scheduled
+     */
+    public int numMerges() {
+      return spec == null ? 0 : spec.merges.size();
+    }
+
+    /**
+     * Returns whether any new merges were scheduled.
+     *
+     * @return {@code true} if merges were scheduled, {@code false} if no 
merges needed
+     */
+    public boolean hasNewMerges() {
+      return spec != null;
+    }
+
+    /**
+     * Waits for all merges in this specification to complete. Returns 
immediately if no merges were
+     * scheduled.
+     *
+     * @return {@code true} if all merges completed successfully or no merges 
were needed, {@code
+     *     false} on error
+     */
+    public boolean await() {
+      return spec == null || spec.await();
+    }
+
+    /**
+     * Waits for all merges in this specification to complete, with timeout. 
Returns immediately if
+     * no merges were scheduled.
+     *
+     * @param timeout maximum time to wait
+     * @param unit time unit for timeout
+     * @return {@code true} if all merges completed within timeout or no 
merges were needed, {@code
+     *     false} on timeout or error
+     */
+    public boolean await(long timeout, TimeUnit unit) {
+      return spec == null || spec.await(timeout, unit);
+    }
+
+    /**
+     * Returns a {@link CompletableFuture} that completes when all merges 
finish. Returns an
+     * already-completed future if no merges were scheduled.
+     *
+     * @return future that completes when merges finish
+     */
+    public CompletableFuture<Void> awaitAsync() {
+      return spec == null
+          ? CompletableFuture.completedFuture(null)
+          : spec.getMergeCompletedFutures();
+    }
+
+    @Override
+    public String toString() {
+      return spec == null ? "MergeObserver: no merges" : spec.toString();
+    }
+
+    /**
+     * Returns the merge at the specified index. Caller must ensure {@link 
#hasNewMerges()} returns
+     * {@code true} and index is within bounds.
+     *
+     * @param i merge index (0 to {@link #numMerges()} - 1)
+     * @return the merge at index i
+     * @throws IndexOutOfBoundsException if index is invalid or no merges exist
+     */
+    public MergePolicy.OneMerge getMerge(int i) {

Review Comment:
   You're right on both points. My original intent was to provide detailed 
observability, but as you noted, the caller can't meaningfully use index-based 
access without already having the `MergeSpec`. And `OneMerge` is definitely 
mutable, so exposing it breaks encapsulation.
   
   The `umMerges()/numCompletedMerges()` approach you suggested is much better, 
as it provides progress tracking without exposing internals.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to