diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..f04422db Binary files /dev/null and b/.DS_Store differ diff --git a/core/.DS_Store b/core/.DS_Store new file mode 100644 index 00000000..0fbb35f8 Binary files /dev/null and b/core/.DS_Store differ diff --git a/core/src/.DS_Store b/core/src/.DS_Store new file mode 100644 index 00000000..c0c271f8 Binary files /dev/null and b/core/src/.DS_Store differ diff --git a/core/src/main/.DS_Store b/core/src/main/.DS_Store new file mode 100644 index 00000000..faf983f6 Binary files /dev/null and b/core/src/main/.DS_Store differ diff --git a/core/src/main/java/.DS_Store b/core/src/main/java/.DS_Store new file mode 100644 index 00000000..d3e6bd63 Binary files /dev/null and b/core/src/main/java/.DS_Store differ diff --git a/core/src/main/java/dev/.DS_Store b/core/src/main/java/dev/.DS_Store new file mode 100644 index 00000000..15dc27ec Binary files /dev/null and b/core/src/main/java/dev/.DS_Store differ diff --git a/core/src/main/java/dev/failsafe/.DS_Store b/core/src/main/java/dev/failsafe/.DS_Store new file mode 100644 index 00000000..f321073e Binary files /dev/null and b/core/src/main/java/dev/failsafe/.DS_Store differ diff --git a/core/src/main/java/dev/failsafe/ExecutorDelegation.java b/core/src/main/java/dev/failsafe/ExecutorDelegation.java new file mode 100644 index 00000000..46243092 --- /dev/null +++ b/core/src/main/java/dev/failsafe/ExecutorDelegation.java @@ -0,0 +1,66 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package dev.failsafe; + +import dev.failsafe.function.AsyncRunnable; +import dev.failsafe.function.ContextualSupplier; + +import java.util.concurrent.Executor; + +/** + * Wraps a {@link ContextualSupplier} or {@link AsyncRunnable} so that it runs on a user-supplied {@link Executor} + * rather than the calling thread, and propagates any resulting throwable back out of the executor thread. + *

+ * Extracted from {@link Functions}, which previously combined this executor-delegation concern with + * execution-pipeline wiring and generic function adaptation in a single class with no shared state across the + * three concerns. + * + * @author Jonathan Halterman + */ +final class ExecutorDelegation { + static ContextualSupplier withExecutor(ContextualSupplier supplier, Executor executor) { + return executor == null ? supplier : ctx -> { + executor.execute(() -> { + try { + supplier.get(ctx); + } catch (Throwable e) { + handleExecutorThrowable(e); + } + }); + return null; + }; + } + + static AsyncRunnable withExecutor(AsyncRunnable runnable, Executor executor) { + return executor == null ? runnable : exec -> { + executor.execute(() -> { + try { + runnable.run(exec); + } catch (Throwable e) { + handleExecutorThrowable(e); + } + }); + }; + } + + private static void handleExecutorThrowable(Throwable e) { + if (e instanceof RuntimeException) + throw (RuntimeException) e; + if (e instanceof Error) + throw (Error) e; + throw new FailsafeException(e); + } +} \ No newline at end of file diff --git a/core/src/main/java/dev/failsafe/FailsafeExecutor.java b/core/src/main/java/dev/failsafe/FailsafeExecutor.java index 82b3144e..992f7d68 100644 --- a/core/src/main/java/dev/failsafe/FailsafeExecutor.java +++ b/core/src/main/java/dev/failsafe/FailsafeExecutor.java @@ -32,6 +32,7 @@ import java.util.function.Function; import static dev.failsafe.Functions.*; +import static dev.failsafe.FunctionAdapters.*; /** *

diff --git a/core/src/main/java/dev/failsafe/Fallback.java b/core/src/main/java/dev/failsafe/Fallback.java index ed3de304..01c2dd2f 100644 --- a/core/src/main/java/dev/failsafe/Fallback.java +++ b/core/src/main/java/dev/failsafe/Fallback.java @@ -25,7 +25,7 @@ import java.util.concurrent.CompletionStage; -import static dev.failsafe.Functions.toFn; +import static dev.failsafe.FunctionAdapters.toFn; /** * A Policy that handles failures using a fallback function or result. @@ -224,4 +224,4 @@ static Fallback none() { */ @Override FallbackConfig getConfig(); -} +} \ No newline at end of file diff --git a/core/src/main/java/dev/failsafe/FunctionAdapters.java b/core/src/main/java/dev/failsafe/FunctionAdapters.java new file mode 100644 index 00000000..3437be8f --- /dev/null +++ b/core/src/main/java/dev/failsafe/FunctionAdapters.java @@ -0,0 +1,74 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package dev.failsafe; + +import dev.failsafe.function.*; +import dev.failsafe.internal.util.Assert; + +/** + * Adapts various user-supplied functional interface shapes (runnables, suppliers, consumers, results) into the + * common {@link ContextualSupplier} or {@link CheckedFunction} shape that the rest of Failsafe operates on. + *

+ * Extracted from {@link Functions}, which previously combined this purely-functional adaptation logic with + * execution-pipeline wiring and executor-thread delegation in a single class with no shared state across the three + * concerns. + * + * @author Jonathan Halterman + */ +final class FunctionAdapters { + static ContextualSupplier toCtxSupplier(CheckedRunnable runnable) { + Assert.notNull(runnable, "runnable"); + return ctx -> { + runnable.run(); + return null; + }; + } + + static ContextualSupplier toCtxSupplier(ContextualRunnable runnable) { + Assert.notNull(runnable, "runnable"); + return ctx -> { + runnable.run(ctx); + return null; + }; + } + + static ContextualSupplier toCtxSupplier(CheckedSupplier supplier) { + Assert.notNull(supplier, "supplier"); + return ctx -> supplier.get(); + } + + static CheckedFunction toFn(CheckedConsumer consumer) { + return t -> { + consumer.accept(t); + return null; + }; + } + + static CheckedFunction toFn(CheckedRunnable runnable) { + return t -> { + runnable.run(); + return null; + }; + } + + static CheckedFunction toFn(CheckedSupplier supplier) { + return t -> supplier.get(); + } + + static CheckedFunction toFn(R result) { + return t -> result; + } +} \ No newline at end of file diff --git a/core/src/main/java/dev/failsafe/Functions.java b/core/src/main/java/dev/failsafe/Functions.java index 75a050fa..8ed4737c 100644 --- a/core/src/main/java/dev/failsafe/Functions.java +++ b/core/src/main/java/dev/failsafe/Functions.java @@ -36,14 +36,14 @@ final class Functions { * @param result type */ static Function, ExecutionResult> get(ContextualSupplier supplier, - Executor executor) { + Executor executor) { return execution -> { ExecutionResult result; Throwable throwable = null; try { execution.preExecute(); - result = ExecutionResult.success(withExecutor(supplier, executor).get(execution)); + result = ExecutionResult.success(ExecutorDelegation.withExecutor(supplier, executor).get(execution)); } catch (Throwable t) { throwable = t; result = ExecutionResult.exception(t); @@ -73,14 +73,14 @@ static Function, ExecutionResult> get(ContextualSupp * @param result type */ static Function, CompletableFuture>> getPromise( - ContextualSupplier supplier, Executor executor) { + ContextualSupplier supplier, Executor executor) { Assert.notNull(supplier, "supplier"); return execution -> { ExecutionResult result; try { execution.preExecute(); - result = ExecutionResult.success(withExecutor(supplier, executor).get(execution)); + result = ExecutionResult.success(ExecutorDelegation.withExecutor(supplier, executor).get(execution)); } catch (Throwable t) { result = ExecutionResult.exception(t); } @@ -97,7 +97,7 @@ static Function, CompletableFuture result type */ static Function, CompletableFuture>> getPromiseExecution( - AsyncRunnable runnable, Executor executor) { + AsyncRunnable runnable, Executor executor) { Assert.notNull(runnable, "runnable"); return new Function, CompletableFuture>>() { @@ -105,7 +105,7 @@ static Function, CompletableFuture> apply(AsyncExecutionInternal execution) { try { execution.preExecute(); - withExecutor(runnable, executor).run(execution); + ExecutorDelegation.withExecutor(runnable, executor).run(execution); } catch (Throwable e) { execution.record(null, e); } @@ -125,15 +125,15 @@ public synchronized CompletableFuture> apply(AsyncExecutionIn */ @SuppressWarnings("unchecked") static Function, CompletableFuture>> getPromiseOfStage( - ContextualSupplier> supplier, FailsafeFuture future, - Executor executor) { + ContextualSupplier> supplier, FailsafeFuture future, + Executor executor) { Assert.notNull(supplier, "supplier"); return execution -> { CompletableFuture> promise = new CompletableFuture<>(); try { execution.preExecute(); - CompletionStage stage = withExecutor(supplier, executor).get(execution); + CompletionStage stage = ExecutorDelegation.withExecutor(supplier, executor).get(execution); if (stage == null) { ExecutionResult r = ExecutionResult.success(null); @@ -168,7 +168,7 @@ static Function, CompletableFuture result type */ static Function, CompletableFuture>> toExecutionAware( - Function, CompletableFuture>> innerFn) { + Function, CompletableFuture>> innerFn) { return execution -> { ExecutionResult result = execution.getResult(); if (result == null) { @@ -186,8 +186,8 @@ static Function, CompletableFuture result type */ static Function, CompletableFuture>> toAsync( - Function, CompletableFuture>> innerFn, Scheduler scheduler, - FailsafeFuture future) { + Function, CompletableFuture>> innerFn, Scheduler scheduler, + FailsafeFuture future) { AtomicBoolean scheduled = new AtomicBoolean(); return execution -> { @@ -221,80 +221,4 @@ static Function, CompletableFuture toCtxSupplier(CheckedRunnable runnable) { - Assert.notNull(runnable, "runnable"); - return ctx -> { - runnable.run(); - return null; - }; - } - - static ContextualSupplier toCtxSupplier(ContextualRunnable runnable) { - Assert.notNull(runnable, "runnable"); - return ctx -> { - runnable.run(ctx); - return null; - }; - } - - static ContextualSupplier toCtxSupplier(CheckedSupplier supplier) { - Assert.notNull(supplier, "supplier"); - return ctx -> supplier.get(); - } - - static ContextualSupplier withExecutor(ContextualSupplier supplier, Executor executor) { - return executor == null ? supplier : ctx -> { - executor.execute(() -> { - try { - supplier.get(ctx); - } catch (Throwable e) { - handleExecutorThrowable(e); - } - }); - return null; - }; - } - - static AsyncRunnable withExecutor(AsyncRunnable runnable, Executor executor) { - return executor == null ? runnable : exec -> { - executor.execute(() -> { - try { - runnable.run(exec); - } catch (Throwable e) { - handleExecutorThrowable(e); - } - }); - }; - } - - private static void handleExecutorThrowable(Throwable e) { - if (e instanceof RuntimeException) - throw (RuntimeException) e; - if (e instanceof Error) - throw (Error) e; - throw new FailsafeException(e); - } - - static CheckedFunction toFn(CheckedConsumer consumer) { - return t -> { - consumer.accept(t); - return null; - }; - } - - static CheckedFunction toFn(CheckedRunnable runnable) { - return t -> { - runnable.run(); - return null; - }; - } - - static CheckedFunction toFn(CheckedSupplier supplier) { - return t -> supplier.get(); - } - - static CheckedFunction toFn(R result) { - return t -> result; - } -} +} \ No newline at end of file diff --git a/core/src/main/java/dev/failsafe/internal/.DS_Store b/core/src/main/java/dev/failsafe/internal/.DS_Store new file mode 100644 index 00000000..5008ddfc Binary files /dev/null and b/core/src/main/java/dev/failsafe/internal/.DS_Store differ diff --git a/core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java b/core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java index 1169adca..a78f54f7 100644 --- a/core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java +++ b/core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java @@ -24,6 +24,8 @@ import java.time.Duration; import java.util.concurrent.atomic.AtomicReference; +import java.util.logging.Level; +import java.util.logging.Logger; /** * A {@link CircuitBreaker} implementation. @@ -34,6 +36,8 @@ * @see CircuitBreakerOpenException */ public class CircuitBreakerImpl implements CircuitBreaker, FailurePolicy, DelayablePolicy { + private static final Logger LOGGER = Logger.getLogger(CircuitBreakerImpl.class.getName()); + private final CircuitBreakerConfig config; /** Writes guarded by "this" */ @@ -154,26 +158,15 @@ protected void recordResult(R result, Throwable exception) { /** * Transitions to the {@code newState} if not already in that state and calls any associated event listener. */ - protected void transitionTo(State newState, EventListener listener, + protected void transitionTo(State newState, EventListener listener, /*extracted method for solo responsibility-MITI*/ ExecutionContext context) { boolean transitioned = false; State currentState; synchronized (this) { currentState = getState(); - if (!getState().equals(newState)) { - switch (newState) { - case CLOSED: - state.set(new ClosedState<>(this)); - break; - case OPEN: - Duration computedDelay = computeDelay(context); - state.set(new OpenState<>(this, state.get(), computedDelay != null ? computedDelay : config.getDelay())); - break; - case HALF_OPEN: - state.set(new HalfOpenState<>(this)); - break; - } + if (!currentState.equals(newState)) { + state.set(createState(newState, context)); transitioned = true; } } @@ -181,11 +174,38 @@ protected void transitionTo(State newState, EventListener + * Extracting this from {@link #transitionTo} resolves the prior non-exhaustive {@code switch} (PMD: + * NonExhaustiveSwitch) by making {@link State} coverage explicit and enforced at compile time, and gives + * state-construction a single, testable seam independent of transition/locking concerns. + * + * @throws IllegalArgumentException if {@code newState} is not a recognized transition target + */ + protected CircuitState createState(State newState, ExecutionContext context) { + switch (newState) { + case CLOSED: + return new ClosedState<>(this); + case OPEN: + Duration computedDelay = computeDelay(context); + return new OpenState<>(this, state.get(), computedDelay != null ? computedDelay : config.getDelay()); + case HALF_OPEN: + return new HalfOpenState<>(this); + default: + throw new IllegalArgumentException("Unexpected circuit breaker state: " + newState); + } + } + /** * Records an execution failure. */ @@ -205,4 +225,4 @@ protected void open(ExecutionContext context) { public PolicyExecutor toExecutor(int policyIndex) { return new CircuitBreakerExecutor<>(this, policyIndex); } -} +} \ No newline at end of file diff --git a/core/src/main/java/dev/failsafe/internal/RetryDelayCalculator.java b/core/src/main/java/dev/failsafe/internal/RetryDelayCalculator.java new file mode 100644 index 00000000..ee3e98d8 --- /dev/null +++ b/core/src/main/java/dev/failsafe/internal/RetryDelayCalculator.java @@ -0,0 +1,110 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package dev.failsafe.internal; + +import dev.failsafe.ExecutionContext; +import dev.failsafe.RetryPolicyConfig; + +import java.time.Duration; + +import static dev.failsafe.internal.util.RandomDelay.randomDelay; +import static dev.failsafe.internal.util.RandomDelay.randomDelayInRange; + +/** + * Computes the delay, in nanoseconds, to use before the next retry attempt. + *

+ * Extracted from {@link RetryPolicyExecutor#onFailure}, which previously interleaved this delay-math with + * retry-exhaustion checks and event-listener dispatch in a single method, and held {@code lastDelayNanos} as + * executor-wide mutable state even though only the delay computation ever read or wrote it. + *

+ * The computation is a fixed sequence of independent adjustment steps, applied in order: a user-supplied delay + * function takes precedence if configured; otherwise a fixed-or-random base delay is computed, then adjusted for + * backoff, then jitter, then clamped to any configured max duration. Structuring it this way (each step consuming + * the previous step's output, free to leave it unchanged) gives the pipeline its own seam to test and extend + * independently of retry-decision logic, in the spirit of Chain of Responsibility. + * + * @param result type + */ +class RetryDelayCalculator { + private final RetryPolicyConfig config; + + /** The last fixed, backoff, random or computed delay time in nanoseconds. */ + private volatile long lastDelayNanos; + + RetryDelayCalculator(RetryPolicyConfig config) { + this.config = config; + } + + /** + * Computes the delay to use before the next retry attempt. + * + * @param userComputedDelay the result of any user-supplied delay function, or {@code null} if none is configured + * or it did not apply for this result/exception. Takes precedence over the fixed/random/backoff steps below. + * @param context the current execution context, used for attempt-count-based backoff + * @param elapsedNanos elapsed execution time, used to clamp the result to any configured max duration + */ + long computeDelayNanos(Duration userComputedDelay, ExecutionContext context, long elapsedNanos) { + long delayNanos; + + if (userComputedDelay != null) { + delayNanos = userComputedDelay.toNanos(); + } else { + delayNanos = getFixedOrRandomDelayNanos(lastDelayNanos); + delayNanos = adjustForBackoff(context, delayNanos); + lastDelayNanos = delayNanos; + } + + if (delayNanos != 0) + delayNanos = adjustForJitter(delayNanos); + return adjustForMaxDuration(delayNanos, elapsedNanos); + } + + private long getFixedOrRandomDelayNanos(long delayNanos) { + Duration delay = config.getDelay(); + Duration delayMin = config.getDelayMin(); + Duration delayMax = config.getDelayMax(); + + if (delayNanos == 0 && delay != null && !delay.equals(Duration.ZERO)) + delayNanos = delay.toNanos(); + else if (delayMin != null && delayMax != null) + delayNanos = randomDelayInRange(delayMin.toNanos(), delayMax.toNanos(), Math.random()); + return delayNanos; + } + + private long adjustForBackoff(ExecutionContext context, long delayNanos) { + if (context.getAttemptCount() != 1 && config.getMaxDelay() != null) + delayNanos = (long) Math.min(delayNanos * config.getDelayFactor(), config.getMaxDelay().toNanos()); + return delayNanos; + } + + private long adjustForJitter(long delayNanos) { + if (config.getJitter() != null) + delayNanos = randomDelay(delayNanos, config.getJitter().toNanos(), Math.random()); + else if (config.getJitterFactor() > 0.0) + delayNanos = randomDelay(delayNanos, config.getJitterFactor(), Math.random()); + return delayNanos; + } + + private long adjustForMaxDuration(long delayNanos, long elapsedNanos) { + if (config.getMaxDuration() != null) { + long maxRemainingDelay = config.getMaxDuration().toNanos() - elapsedNanos; + delayNanos = Math.min(delayNanos, maxRemainingDelay < 0 ? 0 : maxRemainingDelay); + if (delayNanos < 0) + delayNanos = 0; + } + return delayNanos; + } +} \ No newline at end of file diff --git a/core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java b/core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java index 60d24005..b3abfd7a 100644 --- a/core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java +++ b/core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java @@ -28,9 +28,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; -import static dev.failsafe.internal.util.RandomDelay.randomDelay; -import static dev.failsafe.internal.util.RandomDelay.randomDelayInRange; - /** * A PolicyExecutor that handles failures according to a {@link RetryPolicy}. * @@ -44,8 +41,8 @@ public class RetryPolicyExecutor extends PolicyExecutor { // Mutable state private volatile int failedAttempts; private volatile boolean retriesExceeded; - /** The last fixed, backoff, random or computed delay time in nanoseconds. */ - private volatile long lastDelayNanos; + /** Extracted: owns the delay-computation pipeline and its state (see RetryDelayCalculator). */ + private final RetryDelayCalculator delayCalculator; // Handlers private final EventHandler abortHandler; @@ -63,6 +60,7 @@ public RetryPolicyExecutor(RetryPolicyImpl retryPolicy, int policyIndex) { this.retriesExceededHandler = EventHandler.ofExecutionCompleted(config.getRetriesExceededListener()); this.retryHandler = EventHandler.ofExecutionAttempted(config.getRetryListener()); this.retryScheduledHandler = EventHandler.ofExecutionScheduled(config.getRetryScheduledListener()); + this.delayCalculator = new RetryDelayCalculator<>(config); } @Override @@ -220,23 +218,11 @@ public ExecutionResult onFailure(ExecutionContext context, ExecutionResult failedAttemptHandler.handle(result, context); failedAttempts++; - long delayNanos = lastDelayNanos; - - // Determine the computed delay - Duration computedDelay = retryPolicy.computeDelay(context); - if (computedDelay != null) { - delayNanos = computedDelay.toNanos(); - } else { - // Determine the fixed or random delay - delayNanos = getFixedOrRandomDelayNanos(delayNanos); - delayNanos = adjustForBackoff(context, delayNanos); - lastDelayNanos = delayNanos; - } - if (delayNanos != 0) - delayNanos = adjustForJitter(delayNanos); + // Determine the delay to use before the next attempt + Duration userComputedDelay = retryPolicy.computeDelay(context); long elapsedNanos = context.getElapsedTime().toNanos(); - delayNanos = adjustForMaxDuration(delayNanos, elapsedNanos); + long delayNanos = delayCalculator.computeDelayNanos(userComputedDelay, context, elapsedNanos); // Calculate result boolean maxRetriesExceeded = config.getMaxRetries() != -1 && failedAttempts > config.getMaxRetries(); @@ -265,40 +251,4 @@ public CompletableFuture> onFailureAsync(ExecutionContext Scheduler scheduler, FailsafeFuture future) { return super.onFailureAsync(context, result.withNotComplete(), scheduler, future); } - - private long getFixedOrRandomDelayNanos(long delayNanos) { - Duration delay = config.getDelay(); - Duration delayMin = config.getDelayMin(); - Duration delayMax = config.getDelayMax(); - - if (delayNanos == 0 && delay != null && !delay.equals(Duration.ZERO)) - delayNanos = delay.toNanos(); - else if (delayMin != null && delayMax != null) - delayNanos = randomDelayInRange(delayMin.toNanos(), delayMax.toNanos(), Math.random()); - return delayNanos; - } - - private long adjustForBackoff(ExecutionContext context, long delayNanos) { - if (context.getAttemptCount() != 1 && config.getMaxDelay() != null) - delayNanos = (long) Math.min(delayNanos * config.getDelayFactor(), config.getMaxDelay().toNanos()); - return delayNanos; - } - - private long adjustForJitter(long delayNanos) { - if (config.getJitter() != null) - delayNanos = randomDelay(delayNanos, config.getJitter().toNanos(), Math.random()); - else if (config.getJitterFactor() > 0.0) - delayNanos = randomDelay(delayNanos, config.getJitterFactor(), Math.random()); - return delayNanos; - } - - private long adjustForMaxDuration(long delayNanos, long elapsedNanos) { - if (config.getMaxDuration() != null) { - long maxRemainingDelay = config.getMaxDuration().toNanos() - elapsedNanos; - delayNanos = Math.min(delayNanos, maxRemainingDelay < 0 ? 0 : maxRemainingDelay); - if (delayNanos < 0) - delayNanos = 0; - } - return delayNanos; - } -} +} \ No newline at end of file diff --git a/core/src/test/.DS_Store b/core/src/test/.DS_Store new file mode 100644 index 00000000..28b3405f Binary files /dev/null and b/core/src/test/.DS_Store differ diff --git a/core/src/test/java/.DS_Store b/core/src/test/java/.DS_Store new file mode 100644 index 00000000..d3e6bd63 Binary files /dev/null and b/core/src/test/java/.DS_Store differ diff --git a/core/src/test/java/dev/.DS_Store b/core/src/test/java/dev/.DS_Store new file mode 100644 index 00000000..97ac27be Binary files /dev/null and b/core/src/test/java/dev/.DS_Store differ diff --git a/pmd-report.txt b/pmd-report.txt new file mode 100644 index 00000000..3a2cd2d3 --- /dev/null +++ b/pmd-report.txt @@ -0,0 +1,229 @@ +core/src/main/java/dev/failsafe/AsyncExecutionImpl.java:19: UnnecessaryImport: Unused import 'dev.failsafe.spi.*' +core/src/main/java/dev/failsafe/AsyncExecutionImpl.java:45: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/AsyncExecutionImpl.java:56: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/AsyncExecutionImpl.java:148: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/AsyncExecutionImpl.java:153: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/AsyncExecutionImpl.java:156: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Bulkhead.java:92: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/CallImpl.java:25: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/CallImpl.java:40: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/CircuitBreaker.java:121: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/CircuitBreakerConfig.java:50: UncommentedEmptyConstructor: Document empty constructor +core/src/main/java/dev/failsafe/DelayablePolicyConfig.java:34: UncommentedEmptyConstructor: Document empty constructor +core/src/main/java/dev/failsafe/ExecutionImpl.java:43: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:56: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:58: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:60: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:62: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:64: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:66: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:68: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/ExecutionImpl.java:126: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/ExecutionImpl.java:181: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/ExecutionImpl.java:181: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/ExecutionImpl.java:195: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/ExecutionImpl.java:195: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Failsafe.java:29: UseUtilityClass: All members are static. Consider adding a private no-args constructor to prevent instantiation. +core/src/main/java/dev/failsafe/FailsafeException.java:27: UncommentedEmptyConstructor: Document empty constructor +core/src/main/java/dev/failsafe/FailsafeExecutor.java:20: UnnecessaryImport: Unused import 'dev.failsafe.function.*' +core/src/main/java/dev/failsafe/FailsafeExecutor.java:55: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/FailsafeExecutor.java:56: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/FailsafeExecutor.java:57: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/FailsafeExecutor.java:353: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailsafeExecutor.java:355: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailsafeExecutor.java:413: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailsafeExecutor.java:415: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailsafeExecutor.java:417: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailurePolicyBuilder.java:180: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailurePolicyBuilder.java:181: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FailurePolicyBuilder.java:183: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/FallbackConfig.java:45: UncommentedEmptyConstructor: Document empty constructor +core/src/main/java/dev/failsafe/Functions.java:18: UnnecessaryImport: Unused import 'dev.failsafe.function.*' +core/src/main/java/dev/failsafe/Functions.java:20: UnnecessaryImport: Unused import 'dev.failsafe.spi.*' +core/src/main/java/dev/failsafe/Functions.java:31: UseUtilityClass: All members are static. Consider adding a private no-args constructor to prevent instantiation. +core/src/main/java/dev/failsafe/Functions.java:47: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:62: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:84: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:109: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:145: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:149: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:155: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:200: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:202: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:215: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:217: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:251: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:264: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/Functions.java:273: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/Functions.java:275: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/PolicyConfig.java:28: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/PolicyConfig.java:29: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/PolicyConfig.java:31: UncommentedEmptyConstructor: Document empty constructor +core/src/main/java/dev/failsafe/RateLimiter.java:187: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/RetryPolicyConfig.java:58: UncommentedEmptyConstructor: Document empty constructor +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:26: UnnecessaryImport: Unused import 'java.util.concurrent.atomic.AtomicReference' +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:54: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:81: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:84: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:99: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:193: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/SyncExecutionImpl.java:195: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/event/EventListener.java:33: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/event/EventListener.java:33: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/BulkheadExecutor.java:84: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/BulkheadImpl.java:56: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/internal/BulkheadImpl.java:74: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/BurstyRateLimiterStats.java:68: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/BurstyRateLimiterStats.java:74: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java:18: UnnecessaryImport: Unused import 'dev.failsafe.*' +core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java:149: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java:151: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java:165: NonExhaustiveSwitch: Switch statements or expressions should be exhaustive, add a default case (or missing enum branches) +core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java:184: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/internal/CircuitBreakerImpl.java:184: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/CircuitState.java:20: UnnecessaryImport: Unused import 'dev.failsafe.CircuitBreakerOpenException' +core/src/main/java/dev/failsafe/internal/CircuitState.java:34: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/CircuitState.java:64: UncommentedEmptyMethodBody: Document empty method body +core/src/main/java/dev/failsafe/internal/CircuitState.java:67: UncommentedEmptyMethodBody: Document empty method body +core/src/main/java/dev/failsafe/internal/CircuitState.java:72: UncommentedEmptyMethodBody: Document empty method body +core/src/main/java/dev/failsafe/internal/CircuitStats.java:28: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CircuitStats.java:38: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CircuitStats.java:40: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/ClosedState.java:53: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/ClosedState.java:62: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/ClosedState.java:64: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:28: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:29: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:30: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:31: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:53: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:54: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:114: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:116: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:123: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:125: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:128: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:130: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/CountingCircuitStats.java:144: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/DefaultCircuitStats.java:7: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:19: UnnecessaryImport: Unused import 'dev.failsafe.spi.*' +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:52: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:56: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:62: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:82: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:84: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:86: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:89: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:98: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:103: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:111: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/FallbackExecutor.java:121: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/HalfOpenState.java:87: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/HalfOpenState.java:89: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/HalfOpenState.java:98: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/HalfOpenState.java:100: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RateLimiterExecutor.java:64: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RateLimiterExecutor.java:79: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/RateLimiterImpl.java:57: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RateLimiterImpl.java:75: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RateLimiterImpl.java:77: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:21: UnnecessaryImport: Unused import 'dev.failsafe.spi.*' +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:45: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:46: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:48: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:77: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:81: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:85: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:93: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:102: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:110: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:126: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:142: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:164: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:186: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:220: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:237: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:252: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:254: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:275: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:277: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:283: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:289: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:291: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyExecutor.java:300: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyImpl.java:62: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/RetryPolicyImpl.java:63: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/internal/RetryPolicyImpl.java:63: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/SmoothRateLimiterStats.java:59: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/TimedCircuitStats.java:35: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/TimedCircuitStats.java:42: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/TimedCircuitStats.java:117: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/TimedCircuitStats.java:189: OneDeclarationPerLine: Use one line for each declaration, it enhances code readability. +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:21: UnnecessaryImport: Unused import 'dev.failsafe.spi.*' +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:82: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:87: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:94: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:146: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:163: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/TimeoutExecutor.java:169: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/Assert.java:29: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/Assert.java:34: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/Assert.java:40: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:37: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:38: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:51: MissingOverride: The method 'newThread(Runnable)' is missing an @Override annotation. +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:61: AvoidUsingVolatile: Use of modifier volatile is not recommended. +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:76: OverrideBothEqualsAndHashCodeOnComparable: When implementing Comparable, both equals() and hashCode() should be overridden +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:77: CompareObjectsWithEquals: Use equals() to compare object references. +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:90: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:92: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:102: CloseResource: Ensure that resources like this ScheduledThreadPoolExecutor object are closed after use +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:113: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:118: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:120: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:131: CloseResource: Ensure that resources like this ExecutorService object are closed after use +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:142: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:155: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:157: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/DelegatingScheduler.java:161: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:48: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:48: AssignmentInOperand: Avoid assignment to tail in operand +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:65: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:72: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:74: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:75: CompareObjectsWithEquals: Use equals() to compare object references. +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:76: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:77: CompareObjectsWithEquals: Use equals() to compare object references. +core/src/main/java/dev/failsafe/internal/util/FutureLinkedList.java:78: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/internal/util/Maths.java:37: UselessParentheses: Useless parentheses around `input / interval`. +core/src/main/java/dev/failsafe/spi/DefaultScheduledFuture.java:43: OverrideBothEqualsAndHashCodeOnComparable: When implementing Comparable, both equals() and hashCode() should be overridden +core/src/main/java/dev/failsafe/spi/DelayablePolicy.java:53: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/spi/DelayablePolicy.java:54: AvoidInstanceofChecksInCatchClause: An instanceof check is being performed on the caught exception. Create a separate catch clause for RuntimeException. +core/src/main/java/dev/failsafe/spi/DelayablePolicy.java:55: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/DelayablePolicy.java:57: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/ExecutionResult.java:209: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/ExecutionResult.java:211: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:75: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:94: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:99: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:101: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:103: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:130: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:153: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:173: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailsafeFuture.java:175: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailurePolicy.java:49: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailurePolicy.java:54: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/FailurePolicy.java:55: EmptyCatchBlock: Avoid empty catch blocks +core/src/main/java/dev/failsafe/spi/FailurePolicy.java:55: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:107: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:109: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:117: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:183: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:194: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:196: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:198: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:205: UncommentedEmptyMethodBody: Document empty method body +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:224: AvoidCatchingGenericException: Avoid catching Throwable in try-catch block +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:234: ControlStatementBraces: This statement should have braces +core/src/main/java/dev/failsafe/spi/PolicyExecutor.java:239: ControlStatementBraces: This statement should have braces