CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-quarkus--quarkus-smallrye-fault-tolerance

Build fault-tolerant network services

Pending
Overview
Eval results
Files

programmatic-api.mddocs/

Programmatic API

Programmatic fault tolerance configuration using TypedGuard and Guard interfaces for scenarios where annotation-based configuration is insufficient or dynamic configuration is required.

Capabilities

TypedGuard Creation

Create typed guards for specific return types with fluent configuration API.

TypedGuard<ReturnType> guard = TypedGuard.create(ReturnType.class)
    .withRetry().maxRetries(3).delay(1000, ChronoUnit.MILLISECONDS).done()
    .withCircuitBreaker().requestVolumeThreshold(10).failureRatio(0.5).done()
    .withTimeout().timeout(5000, ChronoUnit.MILLISECONDS).done()
    .build();

// Guard usage
ReturnType result = guard.call(() -> riskyOperation());

Usage Example

@ApplicationScoped
public class ProgrammaticFaultToleranceService {
    
    private final Supplier<String> weatherSupplier;
    private final Function<String, WeatherData> weatherFunction;
    
    @PostConstruct
    public void initializeGuards() {
        // Create guard for weather API calls
        TypedGuard<String> weatherGuard = TypedGuard.create(String.class)
            .withRetry()
                .maxRetries(3)
                .delay(1000, ChronoUnit.MILLISECONDS)
                .retryOn(IOException.class, TimeoutException.class)
                .done()
            .withCircuitBreaker()
                .requestVolumeThreshold(10)
                .failureRatio(0.4)
                .delay(30000, ChronoUnit.MILLISECONDS)
                .done()
            .withTimeout()
                .timeout(8000, ChronoUnit.MILLISECONDS)
                .done()
            .build();
        
        // Adapt supplier for easy usage
        weatherSupplier = weatherGuard.adaptSupplier(() -> {
            return weatherApiClient.getCurrentWeather();
        });
        
        // Create function guard for city-specific weather
        TypedGuard<WeatherData> cityWeatherGuard = TypedGuard.create(WeatherData.class)
            .withRetry()
                .maxRetries(2)
                .delay(500, ChronoUnit.MILLISECONDS)
                .done()
            .withCircuitBreaker()
                .requestVolumeThreshold(5)
                .failureRatio(0.3)
                .name("city-weather-circuit")
                .done()
            .build();
        
        weatherFunction = cityWeatherGuard.adaptFunction(city -> {
            return weatherApiClient.getWeatherForCity(city);
        });
    }
    
    public String getCurrentWeather() {
        return weatherSupplier.get();
    }
    
    public WeatherData getWeatherForCity(String city) {
        return weatherFunction.apply(city);
    }
}

Guard Configuration Options

Comprehensive configuration options for all fault tolerance strategies.

Retry Configuration

TypedGuard<T> guard = TypedGuard.create(ReturnType.class)
    .withRetry()
        .maxRetries(5)
        .delay(1000, ChronoUnit.MILLISECONDS)
        .maxDuration(30000, ChronoUnit.MILLISECONDS)
        .jitter(200, ChronoUnit.MILLISECONDS)
        .retryOn(IOException.class, TimeoutException.class)
        .abortOn(SecurityException.class)
        .done()
    .build();

Circuit Breaker Configuration

TypedGuard<T> guard = TypedGuard.create(ReturnType.class)
    .withCircuitBreaker()
        .requestVolumeThreshold(20)
        .failureRatio(0.5)
        .delay(10000, ChronoUnit.MILLISECONDS)
        .successThreshold(3)
        .name("my-circuit-breaker")
        .failOn(RuntimeException.class)
        .skipOn(IllegalArgumentException.class)
        .done()
    .build();

Timeout Configuration

TypedGuard<T> guard = TypedGuard.create(ReturnType.class)
    .withTimeout()
        .timeout(5000, ChronoUnit.MILLISECONDS)
        .done()
    .build();

Bulkhead Configuration

TypedGuard<T> guard = TypedGuard.create(ReturnType.class)
    .withBulkhead()
        .limit(10)
        .queueSize(20)
        .done()
    .build();

Rate Limit Configuration

TypedGuard<T> guard = TypedGuard.create(ReturnType.class)
    .withRateLimit()
        .limit(100)
        .window(1, ChronoUnit.MINUTES)
        .minSpacing(100, ChronoUnit.MILLISECONDS)
        .type(RateLimitType.ROLLING)
        .done()
    .build();

Guard Adaptation Methods

Different ways to use guards with various functional interfaces.

// Supplier adaptation (no parameters)
Supplier<T> guardedSupplier = guard.adaptSupplier(originalSupplier);

// Function adaptation (single parameter)
Function<P, T> guardedFunction = guard.adaptFunction(originalFunction);

// Callable adaptation (throws exceptions)
T result = guard.call(callableOperation);

// Runnable adaptation (void return)
guard.run(runnableOperation);

Usage Example

@ApplicationScoped
public class AdaptedGuardService {
    
    private final Supplier<List<User>> userListSupplier;
    private final Function<Long, User> userByIdFunction;
    private final Function<UserQuery, List<User>> userQueryFunction;
    
    @PostConstruct
    public void setupGuards() {
        // Guard for listing all users
        TypedGuard<List<User>> listGuard = TypedGuard.create(new TypeToken<List<User>>() {})
            .withRetry().maxRetries(2).delay(500, ChronoUnit.MILLISECONDS).done()
            .withTimeout().timeout(3000, ChronoUnit.MILLISECONDS).done()
            .build();
        
        userListSupplier = listGuard.adaptSupplier(() -> {
            return userRepository.findAll();
        });
        
        // Guard for finding user by ID
        TypedGuard<User> userGuard = TypedGuard.create(User.class)
            .withRetry().maxRetries(3).done()
            .withCircuitBreaker().requestVolumeThreshold(10).done()
            .build();
        
        userByIdFunction = userGuard.adaptFunction(userId -> {
            return userRepository.findById(userId);
        });
        
        // Guard for complex queries
        TypedGuard<List<User>> queryGuard = TypedGuard.create(new TypeToken<List<User>>() {})
            .withBulkhead().limit(5).done()
            .withTimeout().timeout(10000, ChronoUnit.MILLISECONDS).done()
            .build();
        
        userQueryFunction = queryGuard.adaptFunction(query -> {
            return userRepository.find(query);
        });
    }
    
    public List<User> getAllUsers() {
        return userListSupplier.get();
    }
    
    public User findUserById(Long userId) {
        return userByIdFunction.apply(userId);
    }
    
    public List<User> findUsers(UserQuery query) {
        return userQueryFunction.apply(query);
    }
}

Dynamic Guard Configuration

Runtime configuration of guards based on external parameters or conditions.

public TypedGuard<T> createDynamicGuard(GuardConfiguration config) {
    TypedGuardBuilder<T> builder = TypedGuard.create(ReturnType.class);
    
    if (config.isRetryEnabled()) {
        builder = builder.withRetry()
            .maxRetries(config.getMaxRetries())
            .delay(config.getRetryDelay(), ChronoUnit.MILLISECONDS)
            .done();
    }
    
    if (config.isCircuitBreakerEnabled()) {
        builder = builder.withCircuitBreaker()
            .requestVolumeThreshold(config.getCircuitBreakerThreshold())
            .failureRatio(config.getFailureRatio())
            .done();
    }
    
    return builder.build();
}

Usage Example

@ApplicationScoped
public class DynamicGuardService {
    
    @Inject
    ConfigurationService configService;
    
    private Map<String, TypedGuard<ApiResponse>> apiGuards = new ConcurrentHashMap<>();
    
    public ApiResponse callApi(String apiName, ApiRequest request) {
        TypedGuard<ApiResponse> guard = getOrCreateGuard(apiName);
        return guard.call(() -> apiClient.call(apiName, request));
    }
    
    private TypedGuard<ApiResponse> getOrCreateGuard(String apiName) {
        return apiGuards.computeIfAbsent(apiName, name -> {
            ApiConfiguration config = configService.getApiConfiguration(name);
            
            TypedGuardBuilder<ApiResponse> builder = TypedGuard.create(ApiResponse.class);
            
            // Configure retry based on API characteristics
            builder = builder.withRetry()
                .maxRetries(config.getMaxRetries())
                .delay(config.getRetryDelay(), ChronoUnit.MILLISECONDS);
            
            if (config.hasExponentialBackoff()) {
                builder = builder.withExponentialBackoff()
                    .factor(config.getBackoffFactor())
                    .maxDelay(config.getMaxBackoffDelay(), ChronoUnit.MILLISECONDS);
            }
            
            builder = builder.done();
            
            // Configure circuit breaker for unreliable APIs
            if (config.isUnreliable()) {
                builder = builder.withCircuitBreaker()
                    .requestVolumeThreshold(config.getCircuitThreshold())
                    .failureRatio(config.getFailureRatio())
                    .delay(config.getCircuitDelay(), ChronoUnit.MILLISECONDS)
                    .name(name + "-circuit")
                    .done();
            }
            
            // Configure rate limiting for rate-limited APIs
            if (config.hasRateLimit()) {
                builder = builder.withRateLimit()
                    .limit(config.getRateLimit())
                    .window(config.getRateWindow(), ChronoUnit.MINUTES)
                    .done();
            }
            
            return builder.build();
        });
    }
}

Guard Composition and Reuse

Combining multiple guards and reusing guard configurations.

// Base guard configuration
TypedGuard<T> baseGuard = TypedGuard.create(ReturnType.class)
    .withRetry().maxRetries(3).done()
    .withTimeout().timeout(5000, ChronoUnit.MILLISECONDS).done()
    .build();

// Extended guard with additional strategies
TypedGuard<T> extendedGuard = TypedGuard.create(ReturnType.class)
    .from(baseGuard)  // Copy configuration from base guard
    .withCircuitBreaker().requestVolumeThreshold(10).done()
    .build();

Usage Example

@ApplicationScoped
public class GuardCompositionService {
    
    // Base guard for all database operations
    private final TypedGuard<Object> databaseBaseGuard;
    
    // Specialized guards for different operation types
    private final TypedGuard<List<Entity>> queryGuard;
    private final TypedGuard<Entity> crudGuard;
    private final TypedGuard<Void> batchOperationGuard;
    
    @PostConstruct
    public void initializeGuards() {
        // Base configuration for all database operations
        databaseBaseGuard = TypedGuard.create(Object.class)
            .withRetry()
                .maxRetries(3)
                .delay(500, ChronoUnit.MILLISECONDS)
                .retryOn(SQLException.class, TransientDataAccessException.class)
                .done()
            .withTimeout()
                .timeout(10000, ChronoUnit.MILLISECONDS)
                .done()
            .build();
        
        // Query operations with additional circuit breaker
        queryGuard = TypedGuard.create(new TypeToken<List<Entity>>() {})
            .from(databaseBaseGuard)
            .withCircuitBreaker()
                .requestVolumeThreshold(15)
                .failureRatio(0.4)
                .name("database-query-circuit")
                .done()
            .build();
        
        // CRUD operations with bulkhead
        crudGuard = TypedGuard.create(Entity.class)
            .from(databaseBaseGuard)
            .withBulkhead()
                .limit(5)
                .queueSize(10)
                .done()
            .build();
        
        // Batch operations with extended timeout and rate limiting
        batchOperationGuard = TypedGuard.create(Void.class)
            .from(databaseBaseGuard)
            .withTimeout()
                .timeout(60000, ChronoUnit.MILLISECONDS)  // Override base timeout
                .done()
            .withRateLimit()
                .limit(5)
                .window(1, ChronoUnit.MINUTES)
                .done()
            .build();
    }
    
    public List<Entity> findEntities(EntityQuery query) {
        return queryGuard.call(() -> entityRepository.find(query));
    }
    
    public Entity saveEntity(Entity entity) {
        return crudGuard.call(() -> entityRepository.save(entity));
    }
    
    public void processBatch(List<Entity> entities) {
        batchOperationGuard.run(() -> batchProcessor.process(entities));
    }
}

Types

Programmatic API Core Types

// Main typed guard interface
interface TypedGuard<T> {
    T call(Callable<T> callable) throws Exception;
    void run(Runnable runnable);
    Supplier<T> adaptSupplier(Supplier<T> supplier);
    <P> Function<P, T> adaptFunction(Function<P, T> function);
    <P1, P2> BiFunction<P1, P2, T> adaptBiFunction(BiFunction<P1, P2, T> function);
}

// Builder for typed guards
interface TypedGuardBuilder<T> {
    RetryBuilder<T> withRetry();
    CircuitBreakerBuilder<T> withCircuitBreaker();
    TimeoutBuilder<T> withTimeout();
    BulkheadBuilder<T> withBulkhead();
    RateLimitBuilder<T> withRateLimit();
    TypedGuardBuilder<T> from(TypedGuard<?> baseGuard);
    TypedGuard<T> build();
}

// Guard creation factory
class TypedGuard {
    static <T> TypedGuardBuilder<T> create(Class<T> type);
    static <T> TypedGuardBuilder<T> create(TypeToken<T> typeToken);
}

Strategy Builder Types

// Retry configuration builder
interface RetryBuilder<T> {
    RetryBuilder<T> maxRetries(int maxRetries);
    RetryBuilder<T> delay(long delay, ChronoUnit unit);
    RetryBuilder<T> maxDuration(long maxDuration, ChronoUnit unit);
    RetryBuilder<T> jitter(long jitter, ChronoUnit unit);
    RetryBuilder<T> retryOn(Class<? extends Throwable>... exceptions);
    RetryBuilder<T> abortOn(Class<? extends Throwable>... exceptions);
    RetryBuilder<T> withExponentialBackoff();
    RetryBuilder<T> withFibonacciBackoff();
    RetryBuilder<T> withCustomBackoff(Class<? extends CustomBackoffStrategy> strategy);
    TypedGuardBuilder<T> done();
}

// Circuit breaker configuration builder
interface CircuitBreakerBuilder<T> {
    CircuitBreakerBuilder<T> requestVolumeThreshold(int threshold);
    CircuitBreakerBuilder<T> failureRatio(double ratio);
    CircuitBreakerBuilder<T> delay(long delay, ChronoUnit unit);
    CircuitBreakerBuilder<T> successThreshold(int threshold);
    CircuitBreakerBuilder<T> name(String name);
    CircuitBreakerBuilder<T> failOn(Class<? extends Throwable>... exceptions);
    CircuitBreakerBuilder<T> skipOn(Class<? extends Throwable>... exceptions);
    TypedGuardBuilder<T> done();
}

// Additional builder interfaces for other strategies...

Type Token Support

// Type token for generic type support
abstract class TypeToken<T> {
    protected TypeToken() {}
    
    public static <T> TypeToken<T> of(Class<T> type);
    public Type getType();
}

// Usage for generic types
TypedGuard<List<String>> listGuard = TypedGuard.create(new TypeToken<List<String>>() {});
TypedGuard<Map<String, User>> mapGuard = TypedGuard.create(new TypeToken<Map<String, User>>() {});

Install with Tessl CLI

npx tessl i tessl/maven-io-quarkus--quarkus-smallrye-fault-tolerance

docs

asynchronous-strategies.md

bulkhead-strategies.md

circuit-breaker-strategies.md

configuration.md

fallback-strategies.md

index.md

programmatic-api.md

rate-limiting-strategies.md

retry-strategies.md

timeout-strategies.md

tile.json