View Javadoc
1   /*
2      Copyright 2010 Atlassian
3   
4      Licensed under the Apache License, Version 2.0 (the "License");
5      you may not use this file except in compliance with the License.
6      You may obtain a copy of the License at
7   
8          http://www.apache.org/licenses/LICENSE-2.0
9   
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15   */
16  package io.atlassian.fugue.retry;
17  
18  import static java.util.Objects.requireNonNull;
19  
20  /**
21   * A Runnable which wraps the apply method of another Runnable and attempts it a
22   * fixed number of times. This class can be used when a task is known to be
23   * prone to occasional failure and other workarounds are not known.
24   *
25   * @see RetrySupplier for a Supplier implementation
26   * @see RetryFunction for a Function implementation
27   * @see RetryFactory for some factory methods
28   * @see ExceptionHandlers for some predefined handlers
29   */
30  public class RetryTask implements Runnable {
31    private RetrySupplier<?> retrySupplier;
32  
33    /**
34     * An instance that does nothing before retrying and ignores exceptions that
35     * occur.
36     *
37     * @param task to run, must not be null
38     * @param tries number of times to attempt to run task, must be posititve
39     */
40    public RetryTask(final Runnable task, int tries) {
41      this(task, tries, ExceptionHandlers.ignoreExceptionHandler());
42    }
43  
44    /**
45     * An instance that does nothing before retrying.
46     *
47     * @param task to run, must not be null
48     * @param tries number of times to attempt to run task, must be positive
49     * @param handler reacts to exceptions thrown by the wrapped task, must not be
50     * null
51     */
52    public RetryTask(final Runnable task, int tries, ExceptionHandler handler) {
53      this(task, tries, handler, new NoOp());
54    }
55  
56    /**
57     * <p>
58     * Constructor for RetryTask.
59     * </p>
60     *
61     * @param task to run, must not be null
62     * @param tries number of times to attempt to run task, must be positive
63     * @param handler reacts to exceptions thrown by the wrapped task, must not be
64     * null
65     * @param beforeRetry runs before each retry, must not be null
66     */
67    public RetryTask(final Runnable task, int tries, ExceptionHandler handler, Runnable beforeRetry) {
68      requireNonNull(task, "task");
69  
70      retrySupplier = new RetrySupplier<>(() -> {
71        task.run();
72        return null;
73      }, tries, handler, beforeRetry);
74    }
75  
76    /**
77     * {@inheritDoc}
78     *
79     * Attempt to run the wrapped Runnable <i>tries</i> number of times. Any
80     * exceptions thrown will be ignored until the number of attempts is reached.
81     * If the number of attempts is reached without success, the most recent
82     * exception to be thrown will be rethrown.
83     */
84    @Override public void run() {
85      retrySupplier.get();
86    }
87  }