Retries to avoid 503 errors

This commit is contained in:
Nicolás Sánchez 2024-12-14 14:17:00 -03:00
parent d2802051cd
commit 02f55c715f
3 changed files with 167 additions and 130 deletions

View File

@ -25,7 +25,9 @@ public class InstanceInterface {
private static final String API_KEY = globalSettings.apiKey;
private static final OkHttpClient httpClient = new OkHttpClient();
public static ProfitStatsData getProfitStatsData() throws IOException {
public static ProfitStatsData getProfitStatsData(boolean retry) throws IOException {
int retries = 3;
Request profitRequest = new Request.Builder()
.url(API_BASE_URL + "/statistics_server/combined_totals")
.header("X-API-KEY", API_KEY)
@ -33,6 +35,9 @@ public class InstanceInterface {
try (Response statsResponse = httpClient.newCall(profitRequest).execute()) {
if (!statsResponse.isSuccessful()) {
if (statsResponse.code() == 503 && retry) {
return getProfitStatsData(false);
}
throw new IOException("Unexpected code " + statsResponse);
}
String stockResponseBody = statsResponse.body().string();
@ -90,17 +95,20 @@ public class InstanceInterface {
}
}
public static double getTraderTime(String exchange) throws IOException {
public static double getTraderTime(String exchange, boolean retry) throws IOException {
Request uptimeRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/trader_time")
.header("X-API-KEY", API_KEY)
.build();
try (Response statsResponse = httpClient.newCall(uptimeRequest).execute()) {
if (!statsResponse.isSuccessful()) {
throw new IOException("Unexpected code " + statsResponse);
try (Response uptimeResponse = httpClient.newCall(uptimeRequest).execute()) {
if (!uptimeResponse.isSuccessful()) {
if (uptimeResponse.code() == 503 && retry) {
return getTraderTime(exchange,false);
}
String stockResponseBody = statsResponse.body().string();
throw new IOException("Unexpected code " + uptimeResponse);
}
String stockResponseBody = uptimeResponse.body().string();
try {
JsonElement jsonElement = JsonParser.parseString(stockResponseBody);
@ -127,7 +135,7 @@ public class InstanceInterface {
CompletableFuture<List<DealData>> binanceFuture = CompletableFuture.supplyAsync(() -> {
try {
return getLastTradesFromExchange("binance");
return getLastTradesFromExchange("binance", true);
} catch (IOException e) {
throw new RuntimeException(e);
}
@ -135,7 +143,7 @@ public class InstanceInterface {
CompletableFuture<List<DealData>> gateioFuture = CompletableFuture.supplyAsync(() -> {
try {
return getLastTradesFromExchange("gateio");
return getLastTradesFromExchange("gateio", true);
} catch (IOException e) {
throw new RuntimeException(e);
}
@ -143,7 +151,7 @@ public class InstanceInterface {
CompletableFuture<List<DealData>> kucoinFuture = CompletableFuture.supplyAsync(() -> {
try {
return getLastTradesFromExchange("kucoin");
return getLastTradesFromExchange("kucoin", true);
} catch (IOException e) {
throw new RuntimeException(e);
}
@ -151,7 +159,7 @@ public class InstanceInterface {
CompletableFuture<List<DealData>> okxFuture = CompletableFuture.supplyAsync(() -> {
try {
return getLastTradesFromExchange("okex");
return getLastTradesFromExchange("okex", true);
} catch (IOException e) {
throw new RuntimeException(e);
}
@ -177,7 +185,7 @@ public class InstanceInterface {
return allDeals.subList(0,globalSettings.amountOfLastTrades);
}
public static List<DealData> getLastTradesFromExchange(String exchange) throws IOException {
public static List<DealData> getLastTradesFromExchange(String exchange, boolean retry) throws IOException {
Request dealsRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/get_deals_cache")
@ -185,12 +193,13 @@ public class InstanceInterface {
.build();
try (Response statsResponse = httpClient.newCall(dealsRequest).execute()) {
if (!statsResponse.isSuccessful()) {
System.err.println("Unexpected code " + statsResponse);
throw new IOException("Unexpected code " + statsResponse);
try (Response dealsResponse = httpClient.newCall(dealsRequest).execute()) {
if (!dealsResponse.isSuccessful()) {
if (dealsResponse.code() == 503 && retry) {
return getLastTradesFromExchange(exchange,false);
}
String dealsResponseBody = statsResponse.body().string();
throw new IOException("Unexpected code " + dealsResponse); }
String dealsResponseBody = dealsResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(dealsResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
@ -222,18 +231,21 @@ public class InstanceInterface {
}
}
public static String getLastLogs(String exchange) throws IOException {
public static String getLastLogs(String exchange, boolean retry) throws IOException {
Request logRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/get_log_list")
.header("X-API-KEY", API_KEY)
.build();
try (Response statsResponse = httpClient.newCall(logRequest).execute()) {
if (!statsResponse.isSuccessful()) {
throw new IOException("Unexpected code " + statsResponse);
try (Response logResponse = httpClient.newCall(logRequest).execute()) {
if (!logResponse.isSuccessful()) {
if (logResponse.code() == 503 && retry) {
return getLastLogs(exchange,false);
}
String dealsResponseBody = statsResponse.body().string();
throw new IOException("Unexpected code " + logResponse);
}
String dealsResponseBody = logResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(dealsResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
@ -268,10 +280,10 @@ public class InstanceInterface {
// Semaphore
lastSeen = getTraderTime(exchange);
lastSeen = getTraderTime(exchange, true);
//Funds available
fundsAvailable = getFundsAvailable(exchange, "USDT");
fundsAvailable = getFundsAvailable(exchange, "USDT", true);
//Individual worker status needed to calculate this
//Funds needed
@ -290,17 +302,20 @@ public class InstanceInterface {
}
private static double getFundsAvailable(String exchange, String coin) throws IOException {
private static double getFundsAvailable(String exchange, String coin, boolean retry) throws IOException {
Request fundsRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/get_balance?coin=" + coin)
.header("X-API-KEY", API_KEY)
.build();
try (Response statsResponse = httpClient.newCall(fundsRequest).execute()) {
if (!statsResponse.isSuccessful()) {
throw new IOException("Unexpected code " + statsResponse);
try (Response fundsResponse = httpClient.newCall(fundsRequest).execute()) {
if (!fundsResponse.isSuccessful()) {
if (fundsResponse.code() == 503 && retry) {
return getFundsAvailable(exchange, coin, false);
}
String fundsResponseBody = statsResponse.body().string();
throw new IOException("Unexpected code " + fundsResponse);
}
String fundsResponseBody = fundsResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(fundsResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");

View File

@ -16,7 +16,7 @@ public class TickerTracker {
static int requestDepth = 722;
static String requestResolution = "15m";
public static PriceChangeData getPriceChanges(String symbol) throws IOException {
public static PriceChangeData getPriceChanges(String symbol, boolean retry) throws IOException {
// Construct the API request URL for 24h change
Request historicalRequest = new Request.Builder()
.url("https://api.binance.com/api/v3/klines?symbol=" + symbol.toUpperCase(Locale.ROOT) + "&interval=1h&limit=722")
@ -24,6 +24,9 @@ public class TickerTracker {
try (Response historicalResponse = httpClient.newCall(historicalRequest).execute()) {
if (!historicalResponse.isSuccessful()) {
if (historicalResponse.code() == 503 && retry) {
return getPriceChanges(symbol, false);
}
throw new IOException("Unexpected code " + historicalResponse);
}
String historicalResponseBody = historicalResponse.body().string();

View File

@ -308,7 +308,7 @@ public class HomeFragment extends Fragment {
// Fetch price data in background using CompletableFuture
CompletableFuture<TickerTracker.PriceChangeData> future1 = CompletableFuture.supplyAsync(() -> {
try {
return TickerTracker.getPriceChanges(getString(R.string.ticker_1));
return TickerTracker.getPriceChanges(getString(R.string.ticker_1),true);
} catch (IOException e) {
e.printStackTrace();
return null;
@ -317,7 +317,7 @@ public class HomeFragment extends Fragment {
CompletableFuture<TickerTracker.PriceChangeData> future2 = CompletableFuture.supplyAsync(() -> {
try {
return TickerTracker.getPriceChanges(getString(R.string.ticker_2));
return TickerTracker.getPriceChanges(getString(R.string.ticker_2), true);
} catch (IOException e) {
e.printStackTrace();
return null;
@ -326,7 +326,7 @@ public class HomeFragment extends Fragment {
CompletableFuture<TickerTracker.PriceChangeData> future3 = CompletableFuture.supplyAsync(() -> {
try {
return TickerTracker.getPriceChanges(getString(R.string.ticker_3));
return TickerTracker.getPriceChanges(getString(R.string.ticker_3), true);
} catch (IOException e) {
e.printStackTrace();
return null;
@ -335,7 +335,7 @@ public class HomeFragment extends Fragment {
CompletableFuture<InstanceInterface.ProfitStatsData> future4 = CompletableFuture.supplyAsync(() -> {
try {
return InstanceInterface.getProfitStatsData();
return InstanceInterface.getProfitStatsData(true);
} catch (IOException e) {
e.printStackTrace();
return null;
@ -344,7 +344,7 @@ public class HomeFragment extends Fragment {
CompletableFuture<String> future5 = CompletableFuture.supplyAsync(() -> {
try {
return InstanceInterface.getLastLogs("binance");
return InstanceInterface.getLastLogs("binance", true);
} catch (IOException e) {
e.printStackTrace();
return null;
@ -353,7 +353,7 @@ public class HomeFragment extends Fragment {
CompletableFuture<String> future6 = CompletableFuture.supplyAsync(() -> {
try {
return InstanceInterface.getLastLogs("gateio");
return InstanceInterface.getLastLogs("gateio", true);
} catch (IOException e) {
e.printStackTrace();
return null;
@ -362,7 +362,7 @@ public class HomeFragment extends Fragment {
CompletableFuture<String> future7 = CompletableFuture.supplyAsync(() -> {
try {
return InstanceInterface.getLastLogs("kucoin");
return InstanceInterface.getLastLogs("kucoin", true);
} catch (IOException e) {
e.printStackTrace();
return null;
@ -371,7 +371,7 @@ public class HomeFragment extends Fragment {
CompletableFuture<String> future8 = CompletableFuture.supplyAsync(() -> {
try {
return InstanceInterface.getLastLogs("okex");
return InstanceInterface.getLastLogs("okex", true);
} catch (IOException e) {
e.printStackTrace();
return null;
@ -504,7 +504,7 @@ public class HomeFragment extends Fragment {
}
if (priceData!= null) {
pricePair1.setText(String.format(Locale.ROOT, "%.2f", priceData.getCurrentPrice()));
pricePair124hPercentage.setText(formatPercentage(priceData.getPriceChangePercent24h()));
pricePair17dPercentage.setText(formatPercentage(priceData.getPriceChangePercent7d()));
@ -528,14 +528,18 @@ public class HomeFragment extends Fragment {
setPercentageColor(pricePair324hPercentage, priceData3.getPriceChangePercent24h());
setPercentageColor(pricePair37dPercentage, priceData3.getPriceChangePercent7d());
setPercentageColor(pricePair330dPercentage, priceData3.getPriceChangePercent30d());
}
if (profitsData != null) {
profitsToday.setText(String.format(Locale.ROOT, "%.2f", profitsData.getProfitsToday()));
profitsThisMonth.setText(String.format(Locale.ROOT, "%.2f", profitsData.getProfitsThisMonth()));
}
//Exchange stats
int timeoutForYellow = 30*1000; //30 seconds
int timeoutForRed = 300*1000; //300 seconds
//Icons
if (binanceStats!=null){
if (binanceStats.getLastSeen()*1000+timeoutForRed < System.currentTimeMillis()) {
exchange1Status.setImageResource(R.drawable.ic_red_circle_48);
System.err.println(binanceStats.getLastSeen());}
@ -544,6 +548,8 @@ public class HomeFragment extends Fragment {
else {
exchange1Status.setImageResource(R.drawable.ic_green_circle_48);
}
}
if (gateioStats != null){
if (gateioStats.getLastSeen()*1000+timeoutForRed < System.currentTimeMillis()) {
exchange2Status.setImageResource(R.drawable.ic_red_circle_48);
System.err.println(gateioStats.getLastSeen());}
@ -552,14 +558,18 @@ public class HomeFragment extends Fragment {
else {
exchange2Status.setImageResource(R.drawable.ic_green_circle_48);
}
}
if (kucoinStats != null) {
if (kucoinStats.getLastSeen() * 1000 + timeoutForRed < System.currentTimeMillis()) {
exchange3Status.setImageResource(R.drawable.ic_red_circle_48);
System.err.println(kucoinStats.getLastSeen());}
else if (kucoinStats.getLastSeen()*1000+timeoutForYellow < System.currentTimeMillis()) {
exchange3Status.setImageResource(R.drawable.ic_yellow_circle_48);}
else {
System.err.println(kucoinStats.getLastSeen());
} else if (kucoinStats.getLastSeen() * 1000 + timeoutForYellow < System.currentTimeMillis()) {
exchange3Status.setImageResource(R.drawable.ic_yellow_circle_48);
} else {
exchange3Status.setImageResource(R.drawable.ic_green_circle_48);
}
}
if (okexStats != null) {
if (okexStats.getLastSeen()*1000+timeoutForRed < System.currentTimeMillis()) {
exchange4Status.setImageResource(R.drawable.ic_red_circle_48);
System.err.println(okexStats.getLastSeen());
@ -569,50 +579,59 @@ public class HomeFragment extends Fragment {
else {
exchange4Status.setImageResource(R.drawable.ic_green_circle_48);
}
}
//Funds available
if (binanceStats != null) {
String binanceFundsAvailable = String.format(Locale.ROOT, "%.2f", binanceStats.getFundsAvailable());
String binanceFundsNeeded = String.format(Locale.ROOT, "%.2f", binanceStats.getFundsNeeded());
String gateioFundsAvailable = String.format(Locale.ROOT,"%.2f",gateioStats.getFundsAvailable());
String gateioFundsNeeded = String.format(Locale.ROOT,"%.2f",gateioStats.getFundsNeeded());
String kucoinFundsAvailable = String.format(Locale.ROOT,"%.2f",kucoinStats.getFundsAvailable());
String kucoinFundsNeeded = String.format(Locale.ROOT,"%.2f",kucoinStats.getFundsNeeded());
String okexFundsAvailable = String.format(Locale.ROOT,"%.2f",okexStats.getFundsAvailable());
String okexFundsNeeded = String.format(Locale.ROOT,"%.2f",okexStats.getFundsNeeded());
String binanceFunds = binanceFundsAvailable + "/" + binanceFundsNeeded;
String gateioFunds = gateioFundsAvailable+"/"+gateioFundsNeeded;
String kucoinFunds = kucoinFundsAvailable+"/"+kucoinFundsNeeded;
String okexFunds = okexFundsAvailable+"/"+okexFundsNeeded;
double binanceFundsPercentage = 69.4231337;
if (binanceStats.getFundsNeeded() != 0) {
binanceFundsPercentage = 100 - (binanceStats.getFundsNeeded() - binanceStats.getFundsAvailable()) / binanceStats.getFundsNeeded() * 100;
}
String binanceFundsPercentageString = String.format(Locale.ROOT, "%.2f", binanceFundsPercentage) + "%";
exchange1Funds.setText(binanceFunds);
exchange1FundsPercentage.setText(binanceFundsPercentageString);
}
if (gateioStats != null) {
String gateioFundsAvailable = String.format(Locale.ROOT, "%.2f", gateioStats.getFundsAvailable());
String gateioFundsNeeded = String.format(Locale.ROOT, "%.2f", gateioStats.getFundsNeeded());
String gateioFunds = gateioFundsAvailable + "/" + gateioFundsNeeded;
double gateioFundsPercentage = 69.4231337;
if (gateioStats.getFundsNeeded() != 0) {
gateioFundsPercentage = 100 - (gateioStats.getFundsNeeded() - gateioStats.getFundsAvailable()) / gateioStats.getFundsNeeded() * 100;
}
String gateioFundsPercentageString = String.format(Locale.ROOT, "%.2f", gateioFundsPercentage) + "%";
exchange2Funds.setText(gateioFunds);
exchange2FundsPercentage.setText(gateioFundsPercentageString);
}
if (kucoinStats != null) {
String kucoinFundsAvailable = String.format(Locale.ROOT, "%.2f", kucoinStats.getFundsAvailable());
String kucoinFundsNeeded = String.format(Locale.ROOT, "%.2f", kucoinStats.getFundsNeeded());
String kucoinFunds = kucoinFundsAvailable + "/" + kucoinFundsNeeded;
double kucoinFundsPercentage = 69.4231337;
if (kucoinStats.getFundsNeeded() != 0) {
kucoinFundsPercentage = 100 - (kucoinStats.getFundsNeeded() - kucoinStats.getFundsAvailable()) / kucoinStats.getFundsNeeded() * 100;
}
String kucoinFundsPercentageString = String.format(Locale.ROOT, "%.2f", kucoinFundsPercentage) + "%";
exchange3Funds.setText(kucoinFunds);
exchange3FundsPercentage.setText(kucoinFundsPercentageString);
}
if (okexStats != null) {
String okexFundsAvailable = String.format(Locale.ROOT, "%.2f", okexStats.getFundsAvailable());
String okexFundsNeeded = String.format(Locale.ROOT, "%.2f", okexStats.getFundsNeeded());
String okexFunds = okexFundsAvailable + "/" + okexFundsNeeded;
double okexFundsPercentage = 69.4231337;
if (okexStats.getFundsNeeded() != 0) {
okexFundsPercentage = 100 - (okexStats.getFundsNeeded() - okexStats.getFundsAvailable()) / okexStats.getFundsNeeded() * 100;
}
String binanceFundsPercentageString = String.format(Locale.ROOT,"%.2f",binanceFundsPercentage)+"%";
String gateioFundsPercentageString = String.format(Locale.ROOT,"%.2f",gateioFundsPercentage)+"%";
String kucoinFundsPercentageString = String.format(Locale.ROOT,"%.2f",kucoinFundsPercentage)+"%";
String okexFundsPercentageString = String.format(Locale.ROOT, "%.2f", okexFundsPercentage) + "%";
exchange1Funds.setText(binanceFunds);
exchange2Funds.setText(gateioFunds);
exchange3Funds.setText(kucoinFunds);
exchange4Funds.setText(okexFunds);
exchange1FundsPercentage.setText(binanceFundsPercentageString);
exchange2FundsPercentage.setText(gateioFundsPercentageString);
exchange3FundsPercentage.setText(kucoinFundsPercentageString);
exchange4FundsPercentage.setText(okexFundsPercentageString);
}
//Populate logs
log1Content.setText(logs1);