### Compose Multiple Failsafe Policies Source: https://context7.com/failsafe-lib/failsafe/llms.txt Demonstrates composing Fallback, RateLimiter, RetryPolicy, CircuitBreaker, and Timeout policies. The composition order dictates the evaluation sequence, with the innermost policy (last listed) evaluated first. This example shows a common pattern for making remote service calls resilient. ```java // Maven dependency (add to pom.xml): // // dev.failsafe // failsafe // 3.3.2 // Fallback fallback = Fallback.of("service-unavailable"); RetryPolicy retry = RetryPolicy.builder() .handle(IOException.class, TimeoutExceededException.class, CircuitBreakerOpenException.class) .withBackoff(Duration.ofMillis(100), Duration.ofSeconds(10)) .withMaxRetries(4) .build(); Timeout timeout = Timeout.builder(Duration.ofSeconds(5)) .withInterrupt() .build(); CircuitBreaker cb = CircuitBreaker.builder() .withFailureThreshold(3, Duration.ofMinutes(1)) .withDelay(Duration.ofSeconds(30)) .build(); RateLimiter limiter = RateLimiter.smoothBuilder(50, Duration.ofSeconds(1)) .withMaxWaitTime(Duration.ofMillis(200)) .build(); // Evaluation order (inner → outer): timeout → cb → retry → limiter → fallback // limiter checked first at call site, then retry loop begins, each attempt // protected by cb and timeout; fallback activates only after all retries fail String result = Failsafe.with(fallback, limiter, retry, cb, timeout) .with(Executors.newScheduledThreadPool(4)) .onComplete(e -> metrics.record(e.getResult(), e.getException())) .get(() -> remoteService.fetch()); ``` -------------------------------- ### FailsafeExecutor.get / run — Synchronous execution Source: https://context7.com/failsafe-lib/failsafe/llms.txt Runs a supplier synchronously until a successful result is returned or all policies are exceeded. `get(CheckedSupplier)` returns the result, and `run(CheckedRunnable)` is the void equivalent. ```APIDOC ## FailsafeExecutor.get / run — Synchronous execution `get(CheckedSupplier)` runs a supplier synchronously until a successful result is returned or all policies are exceeded, returning the result. `run(CheckedRunnable)` is the void equivalent. Checked exceptions are wrapped in `FailsafeException`; `getCause()` retrieves the original exception. Contextual variants accept a `ContextualSupplier` that receives an `ExecutionContext` for access to attempt counts, elapsed time, and cancellation status. ```java RetryPolicy policy = RetryPolicy.builder() .handleResultIf(r -> r.statusCode() >= 500) .handle(IOException.class) .withDelay(Duration.ofSeconds(1)) .withMaxAttempts(4) .build(); // Synchronous with context HttpResponse response = Failsafe.with(policy).get(ctx -> { System.out.printf("Attempt %d, elapsed %s%n", ctx.getAttemptCount(), ctx.getElapsedTime()); if (ctx.isRetry()) { System.out.println("Last error: " + ctx.getLastException()); } return httpClient.send(request); }); // Synchronous void Failsafe.with(RetryPolicy.ofDefaults()).run(() -> { Files.write(path, data); }); ``` ``` -------------------------------- ### Configuring RetryPolicy to Handle Specific Exceptions Source: https://github.com/failsafe-lib/failsafe/wiki/Frequently-Asked-Questions Example of configuring a RetryPolicy to handle only specific exception types. If not explicitly configured to handle TimeoutExceededException or CircuitBreakerOpenException, these may not be caught by the policy. ```java retryPolicy.handle(ConnectException.class); ``` -------------------------------- ### Using Failsafe with RetryPolicy, Fallback, and Timeout Source: https://github.com/failsafe-lib/failsafe/wiki/Frequently-Asked-Questions Demonstrates how to combine a fallback, retry policy, and timeout for an execution. Ensure that the retry policy or fallback are configured to handle TimeoutExceededException if necessary. ```java Failsafe.with(fallback, retryPolicy, timeout).get(this::connect); ``` -------------------------------- ### RateLimiter: Smooth and Bursty Models Source: https://context7.com/failsafe-lib/failsafe/llms.txt Configure RateLimiter with smooth (token bucket) or bursty (fixed window) models. Specify max wait times for blocking or set to zero for immediate rejection. ```java // Smooth: max 100 executions per second, evenly spaced (one every 10ms) RateLimiter smoothLimiter = RateLimiter.smoothBuilder(100, Duration.ofSeconds(1)) .withMaxWaitTime(Duration.ofMillis(500)) // block up to 500ms waiting for a permit .build(); // Bursty: up to 50 executions per second, allowing bursts RateLimiter burstyLimiter = RateLimiter.burstyBuilder(50, Duration.ofSeconds(1)) .withMaxWaitTime(Duration.ZERO) // reject immediately if limit exceeded .build(); ``` ```java // Used via FailsafeExecutor (throws RateLimitExceededException if limit exceeded) Failsafe.with(burstyLimiter).run(() -> processRequest()); ``` ```java // Standalone permit acquisition if (smoothLimiter.tryAcquirePermit()) { sendEmail(); } else { // rejected — rate limit exceeded } ``` ```java // Reserve a permit and wait externally Duration waitTime = smoothLimiter.reservePermit(); if (!waitTime.isNegative()) { Thread.sleep(waitTime.toMillis()); sendEmail(); } ``` ```java // Block with timeout try { smoothLimiter.acquirePermit(Duration.ofSeconds(1)); processEvent(); } catch (RateLimitExceededException e) { log.warn("Rate limit exceeded"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } ``` -------------------------------- ### Failsafe.with — Create a FailsafeExecutor with policies Source: https://context7.com/failsafe-lib/failsafe/llms.txt Constructs a FailsafeExecutor by composing supplied policies around every execution. Policies are evaluated in reverse order. ```APIDOC ## Failsafe.with — Create a FailsafeExecutor with policies `Failsafe.with(outerPolicy, innerPolicies...)` constructs a `FailsafeExecutor` that composes the supplied policies around every execution. Policies are evaluated in reverse order: the last supplied policy wraps the execution most tightly, and the first policy is outermost. `Failsafe.none()` creates a no-op executor useful for uniform listener callbacks without actual failure handling. ```java import dev.failsafe.*; import java.time.Duration; RetryPolicy retry = RetryPolicy.builder() .handle(IOException.class) .withBackoff(Duration.ofMillis(100), Duration.ofSeconds(5)) .withMaxRetries(3) .build(); CircuitBreaker cb = CircuitBreaker.builder() .withFailureThreshold(5, 10) .withDelay(Duration.ofSeconds(30)) .build(); Fallback fallback = Fallback.of("default-response"); // Composition: Fallback( RetryPolicy( CircuitBreaker( supplier ) ) ) // CircuitBreaker is evaluated first, then RetryPolicy, then Fallback String result = Failsafe.with(fallback, retry, cb) .onSuccess(e -> System.out.println("Success: " + e.getResult())) .onFailure(e -> System.out.println("Failed: " + e.getException())) .get(() -> remoteCall()); // Returns "default-response" if all retries and the circuit breaker fail ``` ``` -------------------------------- ### Create FailsafeExecutor with Policies Source: https://context7.com/failsafe-lib/failsafe/llms.txt Use `Failsafe.with()` to compose multiple resilience policies around an execution. Policies are applied in reverse order of declaration. `Failsafe.none()` creates a no-op executor. ```java import dev.failsafe.*; import java.time.Duration; RetryPolicy retry = RetryPolicy.builder() .handle(IOException.class) .withBackoff(Duration.ofMillis(100), Duration.ofSeconds(5)) .withMaxRetries(3) .build(); CircuitBreaker cb = CircuitBreaker.builder() .withFailureThreshold(5, 10) .withDelay(Duration.ofSeconds(30)) .build(); Fallback fallback = Fallback.of("default-response"); // Composition: Fallback( RetryPolicy( CircuitBreaker( supplier ) ) ) // CircuitBreaker is evaluated first, then RetryPolicy, then Fallback String result = Failsafe.with(fallback, retry, cb) .onSuccess(e -> System.out.println("Success: " + e.getResult())) .onFailure(e -> System.out.println("Failed: " + e.getException())) .get(() -> remoteCall()); // Returns "default-response" if all retries and the circuit breaker fail ``` -------------------------------- ### Asynchronous Execution with CompletableFuture Source: https://context7.com/failsafe-lib/failsafe/llms.txt Use `FailsafeExecutor.getAsync()` to schedule suppliers on a `ForkJoinPool` and return a `CompletableFuture`. Policy logic is applied asynchronously. Cancellation of the future propagates inward. `getStageAsync` is for suppliers returning `CompletionStage`. ```java ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4); RetryPolicy retry = RetryPolicy.builder() .withBackoff(50, 2000, ChronoUnit.MILLIS) .withMaxDuration(Duration.ofSeconds(30)) .withMaxRetries(-1) // unlimited retries within maxDuration .build(); CompletableFuture future = Failsafe.with(retry) .with(scheduler) .onSuccess(e -> log.info("Got: {}", e.getResult())) .onFailure(e -> log.error("Failed after: {}", e.getElapsedTime())) .getAsync(() -> fetchDataFromRemote()); // getStageAsync: wraps an async HTTP client CompletableFuture CompletableFuture> result = Failsafe.with(retry) .getStageAsync(() -> asyncHttpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())); // Cancel if not done in 10 seconds future.orTimeout(10, TimeUnit.SECONDS) .exceptionally(ex -> "fallback-value"); ``` -------------------------------- ### Fallback Strategies in Failsafe Source: https://context7.com/failsafe-lib/failsafe/llms.txt Implement fallback strategies for static values, smart functions, exception conversion, or asynchronous operations. Use Fallback.none() to silently swallow failures. Selective fallbacks can be configured to handle specific exceptions. ```java // Static fallback value Fallback staticFallback = Fallback.of("cached-default"); ``` ```java // Function fallback using last attempt context Fallback smartFallback = Fallback.of(event -> { Throwable ex = event.getLastException(); log.error("Using fallback after: {}", ex.getMessage()); return cache.getOrDefault(event.getLastResult(), "unknown"); }); ``` ```java // Exception-converting fallback Fallback exFallback = Fallback.ofException(event -> new ServiceUnavailableException("Service down", event.getLastException())); ``` ```java // Async fallback using CompletionStage Fallback asyncFallback = Fallback.ofStage( () -> backupService.fetchAsync()); ``` ```java // Only apply fallback for specific failures Fallback selectiveFallback = Fallback.builder("default") .handle(RemoteServiceException.class) .withAsync() // run the fallback function asynchronously .onFailedAttempt(e -> log.warn("Primary attempt failed: {}", e.getLastException())) .build(); ``` ```java // Full composition String result = Failsafe .with(selectiveFallback, RetryPolicy.builder().withMaxRetries(2).build(), CircuitBreaker.builder().withFailureThreshold(3).build()) .get(() -> primaryService.fetch()); ``` -------------------------------- ### Synchronous Execution with Context Source: https://context7.com/failsafe-lib/failsafe/llms.txt Use `FailsafeExecutor.get()` for synchronous execution with a supplier that can access execution context like attempt count and elapsed time. Checked exceptions are wrapped in `FailsafeException`. ```java RetryPolicy policy = RetryPolicy.builder() .handleResultIf(r -> r.statusCode() >= 500) .handle(IOException.class) .withDelay(Duration.ofSeconds(1)) .withMaxAttempts(4) .build(); // Synchronous with context HttpResponse response = Failsafe.with(policy).get(ctx -> { System.out.printf("Attempt %d, elapsed %s%n", ctx.getAttemptCount(), ctx.getElapsedTime()); if (ctx.isRetry()) { System.out.println("Last error: " + ctx.getLastException()); } return httpClient.send(request); }); // Synchronous void Failsafe.with(RetryPolicy.ofDefaults()).run(() -> { Files.write(path, data); }); ``` -------------------------------- ### RateLimiter Source: https://context7.com/failsafe-lib/failsafe/llms.txt Limits the rate of executions using smooth (token bucket) or bursty (fixed window) models. Executions can block, be rejected, or pre-reserve permits. ```APIDOC ## RateLimiter — Control execution rate to prevent system overload `RateLimiter` limits the rate of executions using either a *smooth* (token bucket, evenly spread) or *bursty* (fixed window, burst-allowed) model. Executions that exceed the limit either block until a permit is available (up to a configurable max wait), are rejected immediately, or can pre-reserve a permit and receive an expected wait time for external coordination. ```java // Smooth: max 100 executions per second, evenly spaced (one every 10ms) RateLimiter smoothLimiter = RateLimiter.smoothBuilder(100, Duration.ofSeconds(1)) .withMaxWaitTime(Duration.ofMillis(500)) // block up to 500ms waiting for a permit .build(); // Bursty: up to 50 executions per second, allowing bursts RateLimiter burstyLimiter = RateLimiter.burstyBuilder(50, Duration.ofSeconds(1)) .withMaxWaitTime(Duration.ZERO) // reject immediately if limit exceeded .build(); // Used via FailsafeExecutor (throws RateLimitExceededException if limit exceeded) Failsafe.with(burstyLimiter).run(() -> processRequest()); // Standalone permit acquisition if (smoothLimiter.tryAcquirePermit()) { sendEmail(); } else { // rejected — rate limit exceeded } // Reserve a permit and wait externally Duration waitTime = smoothLimiter.reservePermit(); if (!waitTime.isNegative()) { Thread.sleep(waitTime.toMillis()); sendEmail(); } // Block with timeout try { smoothLimiter.acquirePermit(Duration.ofSeconds(1)); processEvent(); } catch (RateLimitExceededException e) { log.warn("Rate limit exceeded"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } ``` ``` -------------------------------- ### Bulkhead Source: https://context7.com/failsafe-lib/failsafe/llms.txt Limits the number of concurrent executions to prevent resource exhaustion. Attempts to execute when the limit is reached will block or fail. ```APIDOC ## Bulkhead — Limit concurrent executions to prevent resource exhaustion `Bulkhead` caps the number of concurrent executions to prevent thread pool or resource exhaustion. When `maxConcurrency` is reached, further execution attempts either block until a permit is released (up to a max wait time) or fail with `BulkheadFullException`. Permits are released automatically when executions finish within `Failsafe.with()`, or must be released manually in standalone use. ```java // Allow at most 10 concurrent executions, wait up to 1 second Bulkhead bulkhead = Bulkhead.builder(10) .withMaxWaitTime(Duration.ofSeconds(1)) .build(); // Via FailsafeExecutor — permit acquired/released automatically String result = Failsafe.with(bulkhead).get(() -> heavyComputation()); // Composed with retry: retry if bulkhead is full RetryPolicy retry = RetryPolicy.builder() .handle(BulkheadFullException.class) .withDelay(Duration.ofMillis(50)) .withMaxRetries(5) .build(); String value = Failsafe.with(retry, bulkhead).get(() -> heavyComputation()); // Standalone usage if (bulkhead.tryAcquirePermit()) { try { return computeResult(); } finally { bulkhead.releasePermit(); // must release manually } } else { throw new BulkheadFullException(bulkhead); } ``` ``` -------------------------------- ### Bulkhead: Limit Concurrent Executions Source: https://context7.com/failsafe-lib/failsafe/llms.txt Configure Bulkhead to limit concurrent executions, preventing resource exhaustion. Permits are acquired/released automatically with FailsafeExecutor or manually in standalone use. ```java // Allow at most 10 concurrent executions, wait up to 1 second Bulkhead bulkhead = Bulkhead.builder(10) .withMaxWaitTime(Duration.ofSeconds(1)) .build(); ``` ```java // Via FailsafeExecutor — permit acquired/released automatically String result = Failsafe.with(bulkhead).get(() -> heavyComputation()); ``` ```java // Composed with retry: retry if bulkhead is full RetryPolicy retry = RetryPolicy.builder() .handle(BulkheadFullException.class) .withDelay(Duration.ofMillis(50)) .withMaxRetries(5) .build(); String value = Failsafe.with(retry, bulkhead).get(() -> heavyComputation()); ``` ```java // Standalone usage if (bulkhead.tryAcquirePermit()) { try { return computeResult(); } finally { bulkhead.releasePermit(); // must release manually } } else { throw new BulkheadFullException(bulkhead); } ``` -------------------------------- ### FailsafeExecutor.getAsync / runAsync — Asynchronous execution Source: https://context7.com/failsafe-lib/failsafe/llms.txt Schedules the supplier asynchronously and returns a `CompletableFuture`. Retries, delays, and policy logic are applied asynchronously. Cancelling the future propagates cancellation inward. ```APIDOC ## FailsafeExecutor.getAsync / runAsync — Asynchronous execution `getAsync(CheckedSupplier)` schedules the supplier on the `ForkJoinPool.commonPool()` (or a configured executor) and returns a `CompletableFuture`. Retries, delays, and all policy logic are applied asynchronously. Cancelling the returned future propagates cancellation inward. `getStageAsync` is for suppliers that themselves return a `CompletionStage`, chaining Failsafe policy handling on top of the stage's completion. ```java ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4); RetryPolicy retry = RetryPolicy.builder() .withBackoff(50, 2000, ChronoUnit.MILLIS) .withMaxDuration(Duration.ofSeconds(30)) .withMaxRetries(-1) // unlimited retries within maxDuration .build(); CompletableFuture future = Failsafe.with(retry) .with(scheduler) .onSuccess(e -> log.info("Got: {}", e.getResult())) .onFailure(e -> log.error("Failed after: {}", e.getElapsedTime())) .getAsync(() -> fetchDataFromRemote()); // getStageAsync: wraps an async HTTP client CompletableFuture CompletableFuture> result = Failsafe.with(retry) .getStageAsync(() -> asyncHttpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())); // Cancel if not done in 10 seconds future.orTimeout(10, TimeUnit.SECONDS) .exceptionally(ex -> "fallback-value"); ``` ``` -------------------------------- ### Manual Synchronous Execution Tracking with Execution Source: https://context7.com/failsafe-lib/failsafe/llms.txt Manually track synchronous execution attempts using Execution. Record results or exceptions, check completion status, and retrieve the mandated delay for subsequent attempts. This is useful when automatic retry loops are not desired. ```java RetryPolicy policy = RetryPolicy.builder() .handle(ConnectException.class) .withDelay(Duration.ofMillis(100)) .withMaxRetries(3) .build(); Execution execution = Execution.of(policy); Connection conn = null; while (!execution.isComplete()) { try { conn = connectionFactory.create(); execution.recordResult(conn); } catch (ConnectException e) { execution.recordException(e); if (!execution.isComplete()) { // Wait for the policy-mandated delay before next attempt Thread.sleep(execution.getDelay().toMillis()); } } } if (conn == null) { throw new RuntimeException("Could not connect after retries"); } ``` -------------------------------- ### ExecutionContext for Contextual Failsafe Executions Source: https://context7.com/failsafe-lib/failsafe/llms.txt Access contextual information during Failsafe executions via ExecutionContext. This includes attempt count, elapsed time, last result/exception, and cancellation status. Use onCancel callbacks for cooperative cancellation. ```java RetryPolicy policy = RetryPolicy.builder() .withMaxRetries(5) .withDelay(Duration.ofSeconds(1)) .build(); String result = Failsafe.with(policy).get((ExecutionContext ctx) -> { System.out.printf("Attempt %d of %d, elapsed: %s%n", ctx.getAttemptCount() + 1, 6, ctx.getElapsedTime()); System.out.printf("Is first: %b, is retry: %b%n", ctx.isFirstAttempt(), ctx.isRetry()); if (ctx.getLastException() != null) { System.out.println("Previous error: " + ctx.getLastException().getMessage()); } // Register cancellation callback (e.g., for cleanup) ctx.onCancel(() -> System.out.println("Execution was cancelled")); if (ctx.isCancelled()) return null; return fetchData(); }); ``` -------------------------------- ### Configure CircuitBreaker with Failure Thresholds and Delay Source: https://context7.com/failsafe-lib/failsafe/llms.txt Implement CircuitBreaker to prevent cascading failures by temporarily blocking executions when failures exceed a threshold. Configure count-based or time-based failure thresholds, delay before transitioning to half-open, and success threshold for closing. ```java CircuitBreaker cb = CircuitBreaker.builder() .withFailureThreshold(5, 10) .handleResultIf(r -> r.statusCode() >= 500) .withDelay(Duration.ofSeconds(30)) .withSuccessThreshold(3) .onOpen(e -> log.warn("Circuit OPEN — {}", e)) .onHalfOpen(e -> log.info("Circuit HALF-OPEN — probing")) .onClose(e -> log.info("Circuit CLOSED — recovered")) .build(); HttpResponse resp = Failsafe.with(cb).get(() -> httpClient.send(request)); if (cb.tryAcquirePermit()) { try { cb.recordResult(httpClient.send(request)); } catch (Exception e) { cb.recordException(e); } } System.out.println("State: " + cb.getState()); System.out.println("Failure rate: " + cb.getFailureRate() + "%"); System.out.println("Failure count: " + cb.getFailureCount()); ``` -------------------------------- ### Configure RetryPolicy with Backoff and Abort Conditions Source: https://context7.com/failsafe-lib/failsafe/llms.txt Use RetryPolicy to automatically retry executions on specific exceptions or results. Configure exponential backoff, jitter, max attempts, max duration, and abort conditions to control retry behavior. Event listeners provide hooks for lifecycle events. ```java RetryPolicy policy = RetryPolicy.builder() .handle(ConnectException.class, SocketTimeoutException.class) .handleResultIf(r -> r.getStatus() == 503) .abortOn(AuthenticationException.class) .abortIf((result, ex) -> result != null && result.getStatus() == 400) .withBackoff(Duration.ofMillis(100), Duration.ofSeconds(30)) .withJitter(0.2) .withMaxAttempts(6) .withMaxDuration(Duration.ofMinutes(2)) .onRetry(e -> log.warn("Retry #{} after: {}", e.getAttemptCount(), e.getLastException())) .onRetriesExceeded(e -> log.error("Retries exhausted: {}", e.getException())) .onAbort(e -> log.error("Retrying aborted: {}", e.getException())) .build(); Response response = Failsafe.with(policy).get(() -> apiClient.call()); ``` -------------------------------- ### Timeout Source: https://context7.com/failsafe-lib/failsafe/llms.txt Fails executions that exceed a configured time limit, optionally interrupting the executing thread. ```APIDOC ## Timeout — Fail executions that exceed a time limit `Timeout` fails an execution with `TimeoutExceededException` if it does not complete within the configured duration. For async executions, the underlying `Future` is cancelled. Optional `withInterrupt()` causes the executing thread to be interrupted on timeout. Executions can cooperate with cancellation by checking `ExecutionContext.isCancelled()`. ```java // Simple timeout of 5 seconds Timeout timeout = Timeout.of(Duration.ofSeconds(5)); // Full configuration with interrupt and listeners Timeout configuredTimeout = Timeout.builder(Duration.ofSeconds(10)) .withInterrupt() // interrupt the executing thread on timeout .onFailure(e -> log.error("Timed out after {}", e.getElapsedTime())) .onSuccess(e -> log.debug("Completed in time")) .build(); // Compose with retry — retry will also handle TimeoutExceededException by default RetryPolicy retry = RetryPolicy.builder() .handle(TimeoutExceededException.class, IOException.class) .withMaxRetries(3) .build(); // Timeout wraps the retry: each individual attempt has its own timeout String result = Failsafe.with(retry, configuredTimeout).get(() -> { ExecutionContext ctx = ...; // available via ContextualSupplier return longRunningOperation(); }); // Cooperate with cancellation inside the supplier String data = Failsafe.with(timeout).get(ctx -> { while (!ctx.isCancelled()) { String chunk = readNextChunk(); if (chunk == null) break; buffer.append(chunk); } return buffer.toString(); }); ``` ``` -------------------------------- ### Timeout: Fail Executions Exceeding Time Limit Source: https://context7.com/failsafe-lib/failsafe/llms.txt Implement Timeout policies to fail executions that exceed a specified duration. Optionally interrupt the executing thread and configure listeners for success or failure. ```java // Simple timeout of 5 seconds Timeout timeout = Timeout.of(Duration.ofSeconds(5)); ``` ```java // Full configuration with interrupt and listeners Timeout configuredTimeout = Timeout.builder(Duration.ofSeconds(10)) .withInterrupt() // interrupt the executing thread on timeout .onFailure(e -> log.error("Timed out after {}", e.getElapsedTime())) .onSuccess(e -> log.debug("Completed in time")) .build(); ``` ```java // Compose with retry — retry will also handle TimeoutExceededException by default RetryPolicy retry = RetryPolicy.builder() .handle(TimeoutExceededException.class, IOException.class) .withMaxRetries(3) .build(); // Timeout wraps the retry: each individual attempt has its own timeout String result = Failsafe.with(retry, configuredTimeout).get(() -> { ExecutionContext ctx = ...; // available via ContextualSupplier return longRunningOperation(); }); ``` ```java // Cooperate with cancellation inside the supplier String data = Failsafe.with(timeout).get(ctx -> { while (!ctx.isCancelled()) { String chunk = readNextChunk(); if (chunk == null) break; buffer.append(chunk); } return buffer.toString(); }); ``` -------------------------------- ### RetryPolicy Source: https://context7.com/failsafe-lib/failsafe/llms.txt Configures automatic retries for executions with delays, backoff strategies, and abort conditions. It handles exceptions and specific results, providing hooks for lifecycle events. ```APIDOC ## RetryPolicy — Automatic retry with delays, backoff, and abort conditions `RetryPolicy` retries executions on configured failures or results. By default it allows 3 attempts (2 retries) with no delay and handles any `Exception`. Configuration options include fixed, random, and exponential backoff delays, jitter, max attempt count, max duration, and abort conditions to stop retrying early. Event listeners (`onRetry`, `onFailedAttempt`, `onRetriesExceeded`, `onAbort`) provide hooks for each lifecycle event. ```java RetryPolicy policy = RetryPolicy.builder() // Handle specific exceptions .handle(ConnectException.class, SocketTimeoutException.class) // Also retry on specific results .handleResultIf(r -> r.getStatus() == 503) // Abort retrying on fatal errors .abortOn(AuthenticationException.class) .abortIf((result, ex) -> result != null && result.getStatus() == 400) // Exponential backoff: 100ms → 30s cap, factor 2 .withBackoff(Duration.ofMillis(100), Duration.ofSeconds(30)) // Add ±20% jitter to each delay .withJitter(0.2) // At most 5 retry attempts (6 total executions) .withMaxAttempts(6) // Or stop after 2 minutes total .withMaxDuration(Duration.ofMinutes(2)) // Listeners .onRetry(e -> log.warn("Retry #{} after: {}", e.getAttemptCount(), e.getLastException())) .onRetriesExceeded(e -> log.error("Retries exhausted: {}", e.getException())) .onAbort(e -> log.error("Retrying aborted: {}", e.getException())) .build(); Response response = Failsafe.with(policy).get(() -> apiClient.call()); ``` ``` -------------------------------- ### CircuitBreaker Source: https://context7.com/failsafe-lib/failsafe/llms.txt Prevents cascading failures by temporarily blocking executions when failure thresholds are exceeded. It manages states (CLOSED, OPEN, HALF-OPEN) and supports count-based or time-based thresholding. ```APIDOC ## CircuitBreaker — Prevent cascading failures with open/half-open/closed states `CircuitBreaker` temporarily blocks executions when failures exceed a threshold, protecting downstream services from overload. It transitions between `CLOSED` (normal), `OPEN` (blocking), and `HALF_OPEN` (probing) states. Both count-based (consecutive or ratio) and time-based (sliding window) thresholding are supported. It exposes metrics and can also be used standalone (outside `Failsafe.with`) for permit-based access control. ```java CircuitBreaker cb = CircuitBreaker.builder() // Open if 5 of the last 10 executions fail (count-based ratio) .withFailureThreshold(5, 10) // Or use time-based: open if 50% fail in last 60s with >= 10 executions // .withFailureRateThreshold(50, 10, Duration.ofSeconds(60)) // Handle specific result conditions as failures .handleResultIf(r -> r.statusCode() >= 500) // Stay open for 30 seconds before transitioning to half-open .withDelay(Duration.ofSeconds(30)) // Close only after 3 consecutive successes in half-open .withSuccessThreshold(3) .onOpen(e -> log.warn("Circuit OPEN — {}", e)) .onHalfOpen(e -> log.info("Circuit HALF-OPEN — probing")) .onClose(e -> log.info("Circuit CLOSED — recovered")) .build(); // Used with Failsafe executor HttpResponse resp = Failsafe.with(cb).get(() -> httpClient.send(request)); // Standalone usage (manual permit management) if (cb.tryAcquirePermit()) { try { cb.recordResult(httpClient.send(request)); } catch (Exception e) { cb.recordException(e); } } // Inspect state and metrics System.out.println("State: " + cb.getState()); // CLOSED / OPEN / HALF_OPEN System.out.println("Failure rate: " + cb.getFailureRate() + "%"); System.out.println("Failure count: " + cb.getFailureCount()); ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.