New Annotation to combine different Annotations
See original GitHub issueProblems with current annotations:
- you cannot specify more then one rate limiter
- you cannot specify the order of decorators (for example specify if rate limiter should take precedent before retries to not count them or should it be after the retryier to count the retries.
Proposal for new annotations:
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD})
@Documented
public @interface ResilienceDecorators {
public Resilience[] value();
}
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD})
@Repeatable(ResilienceDecorators.class)
@Documented
public @interface Resilience {
Retry[] retry() default {};
RateLimiter[] rateLimiter() default {};
@interface Retry {
public static final String DEFAULT_CONFIG = "default";
public String name();
public String baseConfig() default DEFAULT_CONFIG;
}
@interface RateLimiter {
static String FIXED_WEIGHT = "__FIXED_WEIGHT__";
String name();
int weight() default 1;
String weightCalculator() default FIXED_WEIGHT;
}
}
Usage examples on a JAX-RS interface for a REST Proxy Client framework like retrofit or si.mazi.rescu:
@Path("")
@Produces(MediaType.APPLICATION_JSON)
public interface Binance {
@GET
@Path("api/v1/exchangeInfo")
@Resilience(retry = @Retry(name = "exchangeInfo"))
@Resilience(rateLimiter = @RateLimiter(name = REQUEST_WEIGHT_RATE_LIMITER))
BinanceExchangeInfo exchangeInfo() throws IOException;
@GET
@Path("api/v1/depth")
@Resilience(retry = @Retry(name = "depth"))
@Resilience(
rateLimiter =
@RateLimiter(name = REQUEST_WEIGHT_RATE_LIMITER, weightCalculator = "depthWeight"))
BinanceOrderbook depth(@QueryParam("symbol") String symbol, @QueryParam("limit") Integer limit)
throws IOException, BinanceException;
public static int depthWeight(String symbol, Integer limit) {
if (limit <= 100) {
return 1;
} else if (limit <= 500) {
return 5;
} else if (limit <= 1000) {
return 10;
}
return 50;
}
@GET
@Path("api/v1/aggTrades")
@Resilience(retry = @Retry(name = "aggTrades"))
@Resilience(rateLimiter = @RateLimiter(name = REQUEST_WEIGHT_RATE_LIMITER))
List<BinanceAggTrades> aggTrades(
@QueryParam("symbol") String symbol,
@QueryParam("fromId") Long fromId,
@QueryParam("startTime") Long startTime,
@QueryParam("endTime") Long endTime,
@QueryParam("limit") Integer limit)
throws IOException, BinanceException;
@GET
@Path("api/v1/ticker/24hr")
@Resilience(retry = @Retry(name = "ticker24h"))
@Resilience(rateLimiter = @RateLimiter(name = REQUEST_WEIGHT_RATE_LIMITER, weight = 5))
List<BinanceTicker24h> ticker24h() throws IOException, BinanceException;
@GET
@Path("api/v1/ticker/24hr")
@Resilience(retry = @Retry(name = "ticker24h"))
@Resilience(rateLimiter = @RateLimiter(name = REQUEST_WEIGHT_RATE_LIMITER))
BinanceTicker24h ticker24h(@QueryParam("symbol") String symbol)
throws IOException, BinanceException;
@GET
@Path("api/v1/ticker/allPrices")
@Resilience(retry = @Retry(name = "tickerAllPrices"))
@Resilience(rateLimiter = @RateLimiter(name = REQUEST_WEIGHT_RATE_LIMITER, weight = 2))
List<BinancePrice> tickerAllPrices() throws IOException, BinanceException;
@POST
@Path("api/v3/order")
@Resilience(
retry =
@Retry(
name = "newOrder",
baseConfig = ResilienceRegistries.NON_IDEMPOTENTE_CALLS_RETRY_CONFIG_NAME))
@Resilience(rateLimiter = @RateLimiter(name = ORDERS_PER_SECOND_RATE_LIMITER))
@Resilience(rateLimiter = @RateLimiter(name = ORDERS_PER_DAY_RATE_LIMITER))
@Resilience(rateLimiter = @RateLimiter(name = REQUEST_WEIGHT_RATE_LIMITER))
BinanceNewOrder newOrder(
@FormParam("symbol") String symbol,
@FormParam("side") OrderSide side,
@FormParam("type") OrderType type,
@FormParam("timeInForce") TimeInForce timeInForce,
@FormParam("quantity") BigDecimal quantity,
@FormParam("price") BigDecimal price,
@FormParam("newClientOrderId") String newClientOrderId,
@FormParam("stopPrice") BigDecimal stopPrice,
@FormParam("icebergQty") BigDecimal icebergQty,
@FormParam("recvWindow") Long recvWindow,
@FormParam("timestamp") SynchronizedValueFactory<Long> timestamp,
@HeaderParam(X_MBX_APIKEY) String apiKey,
@QueryParam(SIGNATURE) ParamsDigest signature)
throws IOException, BinanceException;
}
This also showcases the “weight” feature for RateLimiter I’m proposing at: https://github.com/resilience4j/resilience4j/issues/642
If you would like to see a working implementation of these annotations then take a look at: https://github.com/knowm/XChange/pull/3231
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:22 (20 by maintainers)
Top Results From Across the Web
merge multiple annotations with parameters - java
The answer is: probably no, this is not possible (using "standard" java). You see, there is no inheritance for annotations, ...
Read more >Composing custom annotations with Spring - mscharhag
Spring supports the composition of custom annotations based of one or more Spring annotations. In this post we will learn how we can...
Read more >How to Merge Multiple Annotations in JAVA
In order to do this, you need to create a custom annotation class. Let's name it BaseTestAnnotation and lets add @RepeatedIfExceptionsTest( ...
Read more >What Are Meta-Annotations in Java? - DZone
This allows users to combine multiple annotations into a single, composed annotation, reducing duplication and saving a great deal of manual ...
Read more >Combining annotation feature classes—Help
When you combine annotation feature classes, the annotation from each feature class becomes an annotation class in the new annotation feature class.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
ok, give me some time to prepare it
@RobWin could you have a look at my PR, it was a lot of work and I would like to know if there is anything controversial there