AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified Apache-2.0 Self-run

Kora Aop Resilient

skill-kora-projects-kora-skills-kora-aop-resilient · by kora-projects

Kora resilience aspects — @CircuitBreaker, @Retry, @Timeout, @Fallback from the resilient-kora module (ResilientModule). Covers circuit breaker states (CLOSED/OPEN/HALF_OPEN), retry backoff, execution timeouts, fallback methods, custom CircuitBreakerPredicate/RetryPredicate/FallbackPredicate, the imperative *Manager API, and stacking aspects on one method. Use when adding fault tolerance to outbo…

No reviews yet
0 installs
34 views
0.0% view→install

Install

$ agentstack add skill-kora-projects-kora-skills-kora-aop-resilient

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-kora-projects-kora-skills-kora-aop-resilient)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Kora Aop Resilient? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Kora AOP Resilient

Compile-time AOP annotations for fault tolerance: @Retry, @CircuitBreaker, @Timeout, @Fallback. They are generated into $__AopProxy classes at build time — no reflection. Provided by the resilient-kora module via ResilientModule.

Quick Navigation:

  • [Quick Start](#quick-start) — get running in four steps
  • [Combined Pattern](#combined-resilience-pattern) — stack all annotations on one method
  • [References](#references) — per-aspect deep dives

Quick Start

1. Add the dependency and annotation processor

dependencies {
    // All Kora artifacts inherit their version from the kora-parent BOM — never pin them individually.
    annotationProcessor "ru.tinkoff.kora:annotation-processors" // mandatory: generates the AOP proxies

    implementation "ru.tinkoff.kora:resilient-kora"
}

> Kotlin uses ksp "ru.tinkoff.kora:symbol-processors" instead of annotationProcessor.

2. Enable ResilientModule

@KoraApp
public interface Application extends
        HoconConfigModule,
        LogbackModule,
        ResilientModule { } // enables the resilience aspects

3. Apply Resilience Annotations

Each annotation lives in its own package:

| Annotation | Import | |------------|--------| | @CircuitBreaker | ru.tinkoff.kora.resilient.circuitbreaker.annotation.CircuitBreaker | | @Retry | ru.tinkoff.kora.resilient.retry.annotation.Retry | | @Timeout | ru.tinkoff.kora.resilient.timeout.annotation.Timeout | | @Fallback | ru.tinkoff.kora.resilient.fallback.annotation.Fallback |

@Component
public class PaymentService { // MUST be non-final (Java) / open (Kotlin) for aspects to apply

    @Fallback(value = "payment.process", method = "processFallback(request)")
    @CircuitBreaker("payment.process")
    @Retry("payment.process")
    @Timeout("payment.process")
    public PaymentResult process(PaymentRequest request) {
        return paymentGateway.charge(request);
    }

    protected PaymentResult processFallback(PaymentRequest request) {
        return PaymentResult.pendingManualReview();
    }
}

The annotation value is a config key, not a shared identifier — @Retry("payment.process") reads resilient.retry."payment.process". Different aspects on the same method may use independent keys.

4. Configure Resilience

resilient {
  timeout {
    default { duration = "1s" }
    "payment.process" { duration = "5s" }
  }
  retry {
    default {
      delay = "100ms"
      attempts = 3
      delayStep = "100ms"
    }
  }
  circuitbreaker {
    default {
      slidingWindowSize = 100
      minimumRequiredCalls = 10
      failureRateThreshold = 50
      waitDurationInOpenState = "30s"
      permittedCallsInHalfOpenState = 5
    }
  }
  fallback {
    default { enabled = true }
  }
}

> Important: Use minimumRequiredCalls (NOT minimumNumberOfCalls) — Kora-specific key.


Combined Resilience Pattern

Recommended order (outer → inner):

@Component
public class PaymentClient {
    
    // Order (outer → inner):
    // 1. @Fallback — degraded response if everything fails
    // 2. @CircuitBreaker — fail fast if repeatedly failing
    // 3. @Retry — retry transient failures
    // 4. @Timeout — bound each attempt
    
    @Fallback(value = "payment.charge", method = "chargeFallback(request)")
    @CircuitBreaker("payment.charge")
    @Retry("payment.charge")
    @Timeout("payment.charge")
    public PaymentResult charge(PaymentRequest request) {
        return httpClient.post("/payments", request);
    }
    
    protected PaymentResult chargeFallback(PaymentRequest request) {
        return PaymentResult.pendingManualReview();
    }
}

Execution flow:

  1. @Timeout bounds the actual HTTP call
  2. @Retry repeats on transient failures (up to N attempts)
  3. @CircuitBreaker opens if failures exceed threshold
  4. @Fallback returns degraded response if circuit is open or all retries fail

References

Detailed guides with configuration options, patterns, and examples:

| Reference | Description | |-----------|-------------| | [retry-reference.md](references/retry-reference.md) | @Retry, predicates, backoff patterns, wait time calculation | | [circuit-breaker-reference.md](references/circuit-breaker-reference.md) | @CircuitBreaker, state machine (CLOSED/OPEN/HALF_OPEN), custom predicates | | [timeout-reference.md](references/timeout-reference.md) | @Timeout patterns, per-attempt vs overall timeout, thread interruption | | [fallback-reference.md](references/fallback-reference.md) | @Fallback methods, signature rules, fallback patterns | | [resilience-config-reference.md](references/resilience-config-reference.md) | Full configuration reference, custom predicates, high-throughput tuning |


Supported Signatures

Java

Class must be non-final for AOP to work.

| Return Type | Example | |-------------|---------| | T (or Void) | User getUser(String id) | | Optional | Optional getUser(String id) | | Mono / Flux | Project Reactor types (require io.projectreactor:reactor-core) |

Kotlin

Class and methods must be open for AOP to work.

| Return Type | Example | |-------------|---------| | T / T? / Unit | fun getUser(id: String): User? | | suspend fun ... : T | suspend fun getUserAsync(id: String): User (requires kotlinx-coroutines-core) | | Flow | fun getAllUsers(): Flow (requires kotlinx-coroutines-core) |


Common Pitfalls

| Problem | Solution | |---------|----------| | Annotations don't trigger | Java: class must be non-final. Kotlin: class and methods must be open | | Circuit breaker never opens | Check minimumRequiredCalls — need enough calls to evaluate | | Circuit breaker reacts to 404 | Implement CircuitBreakerPredicate to exclude business errors | | Fallback not called | Check method signature: return type compatible, parameters match subset | | Retry makes latency worse | Estimate worst-case: attempts × (delay + delayStep). Reduce for latency-sensitive paths | | Config not applied | Config key must match annotation value: @Retry("custom")resilient.retry."custom" |


Troubleshooting

Verify AOP is working

# Check generated proxy classes
find build -name "*__AopProxy.java" | head -5

If no proxies are generated:

  • Check the class is non-final (Java) / open (Kotlin), and the method is open in Kotlin.
  • Verify the annotation processor is wired: Java annotationProcessor "ru.tinkoff.kora:annotation-processors", Kotlin ksp "ru.tinkoff.kora:symbol-processors".
  • Clean rebuild: ./gradlew clean build --no-daemon

Enable debug logging

logging.levels {
  "ru.tinkoff.kora.resilient": "DEBUG"
}

Assets

Templates in assets/:

| Template | Description | |----------|-------------| | ResilientService.java.template | Full resilience stack (Java) | | ResilientService.kt.template | Full resilience stack (Kotlin) | | RetryService.*.template | @Retry pattern | | CircuitBreakerService.*.template | @CircuitBreaker pattern | | TimeoutService.*.template | @Timeout pattern | | FallbackService.*.template | @Fallback pattern |

See [assets/README.md](assets/README.md) for usage.


See Also

  • [kora-http-client](../kora-http-client/SKILL.md) — Pair resilient with outbound HTTP clients
  • [kora-telemetry-metrics](../kora-telemetry-metrics/SKILL.md) — Monitor retry attempts, circuit breaker state
  • [kora-aop-logging](../kora-aop-logging/SKILL.md) — Add logging to resilient services

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.