2525import org .slf4j .Logger ;
2626import org .slf4j .LoggerFactory ;
2727
28+ /** Utility class for retrying operations with various strategies. */
2829public class RetryUtil {
2930 private static final Logger log = LoggerFactory .getLogger (MethodHandles .lookup ().lookupClass ());
3031
32+ /**
33+ * Interface for commands that can be retried and may throw exceptions.
34+ *
35+ * <p>Implementations should define the operation to be executed in the {@link #execute()} method.
36+ */
3137 public interface RetryCmd {
3238 void execute () throws Exception ;
3339 }
3440
41+ /**
42+ * Interface for commands that return a boolean result indicating success or failure.
43+ *
44+ * <p>Implementations should return {@code true} when the operation succeeds, or {@code false}
45+ * when it should be retried.
46+ */
3547 public interface BooleanRetryCmd {
3648 boolean execute ();
3749 }
3850
51+ /**
52+ * Retries a command when a specific exception type occurs, until successful or timeout is
53+ * reached.
54+ *
55+ * <p>This is a convenience method that delegates to {@link #retryOnException(Set, long, long,
56+ * RetryCmd)} with a singleton set containing the specified exception class.
57+ *
58+ * @param clazz the exception class to retry on
59+ * @param timeoutms maximum time to retry in milliseconds
60+ * @param intervalms wait interval between retries in milliseconds
61+ * @param cmd the command to execute
62+ * @throws Exception if the command fails with a different exception, or if timeout is reached
63+ * @throws InterruptedException if the thread is interrupted while sleeping between retries
64+ */
3965 public static void retryOnException (
4066 Class <? extends Exception > clazz , long timeoutms , long intervalms , RetryCmd cmd )
4167 throws Exception {
4268 retryOnException (Collections .singleton (clazz ), timeoutms , intervalms , cmd );
4369 }
4470
71+ /**
72+ * Retries a command when any of the specified exception types occur, until successful or timeout
73+ * is reached.
74+ *
75+ * <p>The command is executed repeatedly until it succeeds (completes without throwing an
76+ * exception) or the timeout is reached. If an exception matching one of the specified classes is
77+ * thrown and there is time remaining, the method will sleep for {@code intervalms} milliseconds
78+ * before retrying. If a different exception is thrown, or if the timeout is reached, the
79+ * exception is rethrown.
80+ *
81+ * @param classes set of exception classes to retry on
82+ * @param timeoutms maximum time to retry in milliseconds
83+ * @param intervalms wait interval between retries in milliseconds
84+ * @param cmd the command to execute
85+ * @throws Exception if the command fails with an exception not in the specified set, or if
86+ * timeout is reached
87+ * @throws InterruptedException if the thread is interrupted while sleeping between retries
88+ */
4589 public static void retryOnException (
4690 Set <Class <? extends Exception >> classes , long timeoutms , long intervalms , RetryCmd cmd )
4791 throws Exception {
@@ -74,6 +118,22 @@ private static boolean isInstanceOf(Set<Class<? extends Exception>> classes, Thr
74118 return false ;
75119 }
76120
121+ /**
122+ * Retries a command until it returns {@code true} or the maximum number of retries is reached.
123+ *
124+ * <p>The command is executed up to {@code retries} times. After each failed attempt (when the
125+ * command returns {@code false}), the method pauses for the specified duration before retrying.
126+ * If all retries are exhausted without success, a {@link SolrException} is thrown with the
127+ * provided error message.
128+ *
129+ * @param errorMessage the error message to use if all retries are exhausted
130+ * @param retries maximum number of retry attempts
131+ * @param pauseTime duration to pause between retries
132+ * @param pauseUnit time unit for the pause duration
133+ * @param cmd the command to execute
134+ * @throws InterruptedException if the thread is interrupted while sleeping between retries
135+ * @throws SolrException if all retries are exhausted without success
136+ */
77137 public static void retryUntil (
78138 String errorMessage , int retries , long pauseTime , TimeUnit pauseUnit , BooleanRetryCmd cmd )
79139 throws InterruptedException {
@@ -84,12 +144,32 @@ public static void retryUntil(
84144 throw new SolrException (ErrorCode .SERVER_ERROR , errorMessage );
85145 }
86146
147+ /**
148+ * Retries a command until it returns {@code true} or the timeout is reached.
149+ *
150+ * <p>The command is executed repeatedly until it returns {@code true} or the timeout expires. If
151+ * the command returns {@code false} and there is time remaining, the method sleeps for {@code
152+ * intervalms} milliseconds before retrying. If the timeout is reached before the command
153+ * succeeds, a {@link SolrException} is thrown.
154+ *
155+ * @param timeoutms maximum time to retry in milliseconds
156+ * @param intervalms wait interval between retries in milliseconds
157+ * @param cmd the command to execute
158+ * @throws SolrException if no success within timeout
159+ */
87160 public static void retryOnBoolean (long timeoutms , long intervalms , BooleanRetryCmd cmd ) {
88161 long timeout =
89162 System .nanoTime () + TimeUnit .NANOSECONDS .convert (timeoutms , TimeUnit .MILLISECONDS );
90163 while (true ) {
91164 boolean resp = cmd .execute ();
92165 if (!resp && System .nanoTime () < timeout ) {
166+ try {
167+ //noinspection BusyWait
168+ Thread .sleep (intervalms );
169+ } catch (InterruptedException e ) {
170+ Thread .currentThread ().interrupt ();
171+ throw new SolrException (ErrorCode .SERVER_ERROR , "Interrupted while retrying operation" );
172+ }
93173 continue ;
94174 } else if (System .nanoTime () >= timeout ) {
95175 throw new SolrException (ErrorCode .SERVER_ERROR , "Timed out while retrying operation" );
0 commit comments