-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Implementing resiliency features
Adam Walczak edited this page Apr 27, 2020
·
1 revision
NOTE: documentation of an upcoming feature https://github.com/knowm/XChange/pull/3231
This page describes the steps required to implement resiliency features which can be enabled via ExchangeSpecification#getResilience
like retries and rate limiting.
Add resiliency registries to your exchange class:
public final class BinanceResilience {
public static final String REQUEST_WEIGHT_RATE_LIMITER = "requestWeight";
// ...
private BinanceResilience() {}
public static ResilienceRegistries createRegistries() {
ResilienceRegistries registries = new ResilienceRegistries();
registries
.rateLimiters()
.rateLimiter(
REQUEST_WEIGHT_RATE_LIMITER,
RateLimiterConfig.from(registries.rateLimiters().getDefaultConfig())
.limitRefreshPeriod(Duration.ofMinutes(1))
.limitForPeriod(1200)
.build());
// ...
return registries;
}
}
public class BinanceExchange extends BaseExchange {
private static ResilienceRegistries RESILIENCE_REGISTRIES;
// ...
@Override
public ResilienceRegistries getResilienceRegistries() {
if (RESILIENCE_REGISTRIES == null) {
RESILIENCE_REGISTRIES = BinanceResilience.createRegistries();
}
return RESILIENCE_REGISTRIES;
}
Extend BaseResilientExchangeService
in your service class and pass the resilience registries to them:
public class BinanceBaseService extends BaseResilientExchangeService<BinanceExchange> {
// ...
protected BinanceBaseService(
BinanceExchange exchange,
BinanceAuthenticated binance,
ResilienceRegistries resilienceRegistries) {
super(exchange, resilienceRegistries);
public class BinanceExchange extends BaseExchange {
// ...
@Override
protected void initServices() {
// ...
this.marketDataService = new BinanceMarketDataService(this, binance, getResilienceRegistries());
this.tradeService = new BinanceTradeService(this, binance, getResilienceRegistries());
this.accountService = new BinanceAccountService(this, binance, getResilienceRegistries());
}
Use BaseResilientExchangeService#decorateApiCall
method for your API calls:
public class BinanceTradeServiceRaw extends BinanceBaseService {
// ...
public List<BinanceOrder> openOrders(CurrencyPair pair) throws BinanceException, IOException {
return decorateApiCall(
() ->
binance.openOrders(
Optional.ofNullable(pair).map(BinanceAdapters::toSymbol).orElse(null),
getRecvWindow(),
getTimestampFactory(),
apiKey,
signatureCreator))
.withRetry(retry("openOrders"))
.withRateLimiter(rateLimiter(REQUEST_WEIGHT_RATE_LIMITER), openOrdersPermits(pair))
.call();
}
public BinanceNewOrder newOrder(
CurrencyPair pair,
OrderSide side,
OrderType type,
TimeInForce timeInForce,
BigDecimal quantity,
BigDecimal price,
String newClientOrderId,
BigDecimal stopPrice,
BigDecimal icebergQty)
throws IOException, BinanceException {
return decorateApiCall(
() ->
binance.newOrder(
BinanceAdapters.toSymbol(pair),
side,
type,
timeInForce,
quantity,
price,
newClientOrderId,
stopPrice,
icebergQty,
getRecvWindow(),
getTimestampFactory(),
apiKey,
signatureCreator))
.withRetry(retry("newOrder", NON_IDEMPOTENTE_CALLS_RETRY_CONFIG_NAME))
.withRateLimiter(rateLimiter(ORDERS_PER_SECOND_RATE_LIMITER))
.withRateLimiter(rateLimiter(ORDERS_PER_DAY_RATE_LIMITER))
.withRateLimiter(rateLimiter(REQUEST_WEIGHT_RATE_LIMITER))
.call();
}
<title>gfg</title>
<style type=text/css>
p{
background-color:gray;
margin: 10px;
}
div
{
color: white;
background-color: 009900;
margin: 2px;
font-size: 25px;
}
span
{
color: black;
background-color: gray;
margin: 5px;
font-size: 25px;
}
</style>
<div> div tag </div>
<div> div tag </div>
<div> div tag </div>
<div> div tag </div>
<span>span-tag</span>
<span>span-tag</span>
<span>span-tag</span>
<span>span-tag</span>