Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.TelegramException;
import com.pengrad.telegrambot.UpdatesListener;
import com.pengrad.telegrambot.model.ResponseParameters;
import com.pengrad.telegrambot.model.Update;
import com.pengrad.telegrambot.model.request.ReplyParameters;
import com.pengrad.telegrambot.model.request.richmessages.InputRichMessage;
Expand All @@ -33,12 +34,14 @@
import com.pengrad.telegrambot.request.richmessages.SendRichMessage;
import com.pengrad.telegrambot.request.richmessages.SendRichMessageDraft;
import com.pengrad.telegrambot.response.BaseResponse;
import org.jspecify.annotations.Nullable;
import org.slf4j.event.Level;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
Expand Down Expand Up @@ -230,9 +233,31 @@ private <T extends BaseRequest<T, R>, R extends BaseResponse> R execute(BaseRequ
return response;
}

for (int retry = 1; retry <= 3 && isRetriable(response.parameters()); retry++) {
var retryDelay = response.parameters().retryAfter();
LOGGER.at(Level.WARN).log("The {} request failed: retrying in {} seconds", request.getMethod(), retryDelay);

try {
Thread.sleep(Duration.ofSeconds(retryDelay));
} catch (InterruptedException _) {
Thread.currentThread().interrupt();
break;
}

response = bot.execute(request);

if (response.isOk()) {
return response;
}
}

throw new TelegramApiException(request.getMethod(), response.description());
}

private static boolean isRetriable(@Nullable ResponseParameters parameters) {
return parameters != null && parameters.retryAfter() != null;
}

private static void deleteTempFiles(Set<Path> pathsToDelete) {
for (var path : pathsToDelete) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ public final class MockResponses {
}
""").build();

static final MockResponse FAILURE_RESPONSE = new MockResponse.Builder().body("""
{
ok: false,
error_code: 429,
description: "Too Many Requests: retry after 3",
parameters: {
retry_after: 3
}
}
""").build();

static final MockResponse START_MESSAGE = new MockResponse.Builder().body("""
{
ok: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -404,4 +404,24 @@ void documentNotSupported() throws Exception {
assertResponseContainsMarkdownMessage(sendRichMessage, Answer.ERROR);
}
}

@Test
void retryApiCall() throws Exception {
server.enqueue(MockResponses.HELP_MESSAGE);
server.enqueue(MockResponses.FAILURE_RESPONSE);
server.enqueue(MockResponses.SUCCESS_RESPONSE);

try (var _ = runBot()) {
var getUpdates = server.takeRequest();
assertEquals("/api/token/getUpdates", getUpdates.getTarget());

var firstSendRichMessage = server.takeRequest();
assertEquals("/api/token/sendRichMessage", firstSendRichMessage.getTarget());

var secondSendRichMessage = server.takeRequest();
assertEquals("/api/token/sendRichMessage", secondSendRichMessage.getTarget());

assertResponseContainsMarkdownMessage(secondSendRichMessage, Answer.HELP);
}
}
}
Loading