### 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.