From 35b4a351f04867a08325f319eee90aa6f5bd72ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ka=C5=A1=C3=ADk?= Date: Thu, 19 Sep 2024 09:23:39 +0200 Subject: [PATCH] Added javadoc to cz.xtf.core.waiting.SimpleWaiter --- .../cz/xtf/core/waiting/SimpleWaiter.java | 133 +++++++++++++++++- 1 file changed, 132 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/cz/xtf/core/waiting/SimpleWaiter.java b/core/src/main/java/cz/xtf/core/waiting/SimpleWaiter.java index b8b44fda..faa53528 100644 --- a/core/src/main/java/cz/xtf/core/waiting/SimpleWaiter.java +++ b/core/src/main/java/cz/xtf/core/waiting/SimpleWaiter.java @@ -9,8 +9,11 @@ import cz.xtf.core.waiting.failfast.ExponentialTimeBackoff; import cz.xtf.core.waiting.failfast.FailFastCheck; +/** + * A simple waiter enabling user to wait until a success or a fail condition will be satisfied + */ public class SimpleWaiter implements Waiter { - private BooleanSupplier successCondition; + private final BooleanSupplier successCondition; private BooleanSupplier failureCondition; private Runnable onIteration; @@ -26,18 +29,51 @@ public class SimpleWaiter implements Waiter { private Level level; private FailFastCheck failFast; + /** + * Construct new SimpleWaiter with a defined success condition. To perform the wait, you need to call + * {@link SimpleWaiter#waitFor}. + * + * @param successCondition whenever this supplier will provide {@code true}, waiting stops. + */ public SimpleWaiter(BooleanSupplier successCondition) { this(successCondition, TimeUnit.MILLISECONDS, WaitingConfig.timeout(), null); } + /** + * Construct new SimpleWaiter with a defined success condition and a reason. The reason will be used in log + * messages associated with the wait. To perform the wait, you need to call {@link SimpleWaiter#waitFor}. + * + * @param successCondition whenever the provided condition will provide {@code true}, waiting stops. + * @param reason description of the reason why this wait is being performed + */ public SimpleWaiter(BooleanSupplier successCondition, String reason) { this(successCondition, TimeUnit.MILLISECONDS, WaitingConfig.timeout(), reason); } + /** + * Construct new SimpleWaiter with a defined success condition and a timeout. The timeout denotes the maximum time + * window in which periodical condition evaluation will be done. To perform the wait, you need to call + * {@link SimpleWaiter#waitFor}. + * + * @param successCondition whenever this supplier will provide {@code true}, waiting stops. + * @param timeoutUnit unit of the timeout + * @param timeout maximum time window in which periodical condition evaluation will be done + */ public SimpleWaiter(BooleanSupplier successCondition, TimeUnit timeoutUnit, long timeout) { this(successCondition, timeoutUnit, timeout, null); } + /** + * Construct new SimpleWaiter with a defined success condition, reason, and a timeout. The timeout denotes the + * maximum time window in which periodical condition evaluation will be done. To perform the wait, you need to call + * {@link SimpleWaiter#waitFor}. + * + * @param successCondition whenever this supplier will provide {@code true}, waiting stops. + * @param timeoutUnit unit of the timeout + * @param timeout maximum time window in which periodical condition evaluation will be done + * @param reason description of the reason why this wait is being performed. Will be used in associated log + * messages. + */ public SimpleWaiter(BooleanSupplier successCondition, TimeUnit timeoutUnit, long timeout, String reason) { this.successCondition = successCondition; this.failureCondition = () -> false; @@ -60,72 +96,166 @@ public SimpleWaiter(BooleanSupplier successCondition, TimeUnit timeoutUnit, long this.logPoint = reason == null ? LogPoint.NONE : LogPoint.START; } + /** + * Set a failure condition. Note that this condition will be evaluated first when the evaluation routine. + * + * @param failureCondition whenever this supplier provides true, the wait will stop. + * @return instance of this {@link SimpleWaiter} + */ public SimpleWaiter failureCondition(BooleanSupplier failureCondition) { this.failureCondition = failureCondition; return this; } + /** + * Set the maximum time windows in which the periodical evaluation of failure and success conditions will be done. + * + * @param millis timeout in milliseconds + * @return instance of this {@link SimpleWaiter} + */ public SimpleWaiter timeout(long millis) { this.timeout = millis; return this; } + /** + * Set the maximum time windows in which the periodical evaluation of failure and success conditions will be done. + * + * @param timeUnit timeUnit that is converts time {@code t} to milliseconds + * @param t timeout in {@code timeUnit} + * @return instance of this {@link SimpleWaiter} + */ public SimpleWaiter timeout(TimeUnit timeUnit, long t) { this.timeout = timeUnit.toMillis(t); return this; } + /** + * Set the amount of time the wait will rest after checking all the conditions in the evaluation routine + * + * @param millis interval in milliseconds + * @return instance of this {@link SimpleWaiter} + */ public SimpleWaiter interval(long millis) { this.interval = millis; return this; } + /** + * Set the amount of time the wait will rest after checking all the conditions in the evaluation routine. + * + * @param timeUnit timeUnit that is converts time {@code t} to milliseconds + * @param t interval in milliseconds + * @return instance of this {@link SimpleWaiter} + */ public SimpleWaiter interval(TimeUnit timeUnit, long t) { this.interval = timeUnit.toMillis(t); return this; } + /** + * Set the description of the reason why this wait is being performed. Will be used in associated log messages. + * + * @param reason what the waiters what upon. + * @return instance of this {@link SimpleWaiter} + */ public SimpleWaiter reason(String reason) { this.reason = reason; this.logPoint = LogPoint.START; return this; } + /** + * Set XTF Waiter specific log configuration. It can be set to any enum value from + * {@link cz.xtf.core.waiting.Waiter.LogPoint} allowing to specify whether the wait start, end, both events or none + * of them should be logged. + * + * @param logPoint what points of waiting should be logged. + * @return instance of this {@link SimpleWaiter} + */ public SimpleWaiter logPoint(LogPoint logPoint) { this.logPoint = logPoint; return this; } + /** + * Set the log level of messages produced during this wait. + * + * @param level what level of severity should be used to log the message. + * @return instance of this {@link SimpleWaiter} + */ public SimpleWaiter level(Level level) { this.level = level; return this; } + /** + * Set the {@link Runnable} to be executed upon each iteration of the evaluation cycle. This will be run after all + * conditions were evaluated. + * + * @param runnable code to be executed upon successful waiting. + * @return instance of this {@link SimpleWaiter} + */ public SimpleWaiter onIteration(Runnable runnable) { onIteration = runnable; return this; } + /** + * Set the {@link Runnable} to be executed after the {@link SimpleWaiter#successCondition} has been met. + * + * @param runnable code to be executed upon successful waiting. + * @return instance of this {@link SimpleWaiter} + */ public SimpleWaiter onSuccess(Runnable runnable) { onSuccess = runnable; return this; } + /** + * Set the {@link Runnable} to be executed after the {@link SimpleWaiter#failureCondition} has been met. + * + * @param runnable code to be executed upon successful waiting. + * @return instance of this {@link SimpleWaiter} + */ public SimpleWaiter onFailure(Runnable runnable) { onFailure = runnable; return this; } + /** + * Set the condition which will be evaluated before other conditions are checked. If evaluated to true, the wait + * will stop with a {@link WaiterException}. Note that non-blocking wait with exponential time backoff is used in + * the evaluation routine for this check meaning that this condition will not be evaluated during each routine + * cycle because the backoff time gradually increases while the interval is a constant. + * + * @param failFast returns true if waiting has failed. + * @return instance of this {@link SimpleWaiter} + */ public SimpleWaiter failFast(FailFastCheck failFast) { this.failFast = failFast; return this; } + /** + * Set a {@link Runnable} to be executed upon timeout. This will be executed as a last thing outside the evaluation + * routine before the {@link WaiterException} is thrown. + * + * @param runnable code to be executed upon timed out waiting. + * @return instance of this {@link SimpleWaiter} + */ public SimpleWaiter onTimeout(Runnable runnable) { onTimeout = runnable; return this; } + /** + * Waits for the success or a failure condition to be met or the timeout to occur. + * + * @return true if the success condition is met, false if the failure condition is met + * @throws WaiterException if the timeout occurs, the blocking wait thread is interrupted or a fast fail check is + * evaluated to true. + */ @Override public boolean waitFor() { long startTime = System.currentTimeMillis(); @@ -133,6 +263,7 @@ public boolean waitFor() { logPoint.logStart(reason, timeout, level); + //backoff counter for fast fail condition ExponentialTimeBackoff backoff = ExponentialTimeBackoff.builder() .blocking(false) .maxBackoff(32000)