issue #707 ExponentialBackOff refactored to interface for custom implementation
This commit is contained in:
parent
f437fd885c
commit
e38c3b0ba9
17
pom.xml
17
pom.xml
@ -178,6 +178,23 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<!-- <reporting>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
|
<version>3.1.2</version>
|
||||||
|
<reportSets>
|
||||||
|
<reportSet>
|
||||||
|
<reports>
|
||||||
|
<report>checkstyle</report>
|
||||||
|
</reports>
|
||||||
|
</reportSet>
|
||||||
|
</reportSets>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</reporting>-->
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package org.telegram.telegrambots.meta.generics;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Calvin
|
||||||
|
* @version 1.0
|
||||||
|
* Interface for backoff retries
|
||||||
|
*/
|
||||||
|
public interface BackOff {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should be able to reset to the starting
|
||||||
|
*/
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* specify the next backoff interval in milliseconds
|
||||||
|
*/
|
||||||
|
long nextBackOffMillis();
|
||||||
|
}
|
@ -5,7 +5,7 @@ import org.apache.http.client.protocol.HttpClientContext;
|
|||||||
import org.apache.http.protocol.HttpContext;
|
import org.apache.http.protocol.HttpContext;
|
||||||
import org.telegram.telegrambots.meta.ApiConstants;
|
import org.telegram.telegrambots.meta.ApiConstants;
|
||||||
import org.telegram.telegrambots.meta.generics.BotOptions;
|
import org.telegram.telegrambots.meta.generics.BotOptions;
|
||||||
import org.telegram.telegrambots.updatesreceivers.ExponentialBackOff;
|
import org.telegram.telegrambots.meta.generics.BackOff;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ public class DefaultBotOptions implements BotOptions {
|
|||||||
private int maxThreads; ///< Max number of threads used for async methods executions (default 1)
|
private int maxThreads; ///< Max number of threads used for async methods executions (default 1)
|
||||||
private RequestConfig requestConfig;
|
private RequestConfig requestConfig;
|
||||||
private volatile HttpContext httpContext;
|
private volatile HttpContext httpContext;
|
||||||
private ExponentialBackOff exponentialBackOff;
|
private BackOff backOff;
|
||||||
private Integer maxWebhookConnections;
|
private Integer maxWebhookConnections;
|
||||||
private String baseUrl;
|
private String baseUrl;
|
||||||
private List<String> allowedUpdates;
|
private List<String> allowedUpdates;
|
||||||
@ -91,23 +91,23 @@ public class DefaultBotOptions implements BotOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @implSpec Default implementation assumes no proxy is needed and sets a 75secs timoute
|
|
||||||
* @param requestConfig Request config to be used in all Http requests
|
* @param requestConfig Request config to be used in all Http requests
|
||||||
|
* @implSpec Default implementation assumes no proxy is needed and sets a 75secs timoute
|
||||||
*/
|
*/
|
||||||
public void setRequestConfig(RequestConfig requestConfig) {
|
public void setRequestConfig(RequestConfig requestConfig) {
|
||||||
this.requestConfig = requestConfig;
|
this.requestConfig = requestConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExponentialBackOff getExponentialBackOff() {
|
public BackOff getBackOff() {
|
||||||
return exponentialBackOff;
|
return backOff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param BackOff backOff to be used when long polling fails
|
||||||
* @implSpec Default implementation assumes starting at 500ms and max time of 60 minutes
|
* @implSpec Default implementation assumes starting at 500ms and max time of 60 minutes
|
||||||
* @param exponentialBackOff ExponentialBackOff to be used when long polling fails
|
|
||||||
*/
|
*/
|
||||||
public void setExponentialBackOff(ExponentialBackOff exponentialBackOff) {
|
public void setBackOff(BackOff BackOff) {
|
||||||
this.exponentialBackOff = exponentialBackOff;
|
this.backOff = BackOff;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProxyType getProxyType() {
|
public ProxyType getProxyType() {
|
||||||
|
@ -16,11 +16,7 @@ import org.telegram.telegrambots.facilities.TelegramHttpClientBuilder;
|
|||||||
import org.telegram.telegrambots.meta.api.methods.updates.GetUpdates;
|
import org.telegram.telegrambots.meta.api.methods.updates.GetUpdates;
|
||||||
import org.telegram.telegrambots.meta.api.objects.Update;
|
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
|
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
|
||||||
import org.telegram.telegrambots.meta.generics.BotOptions;
|
import org.telegram.telegrambots.meta.generics.*;
|
||||||
import org.telegram.telegrambots.meta.generics.BotSession;
|
|
||||||
import org.telegram.telegrambots.meta.generics.LongPollingBot;
|
|
||||||
import org.telegram.telegrambots.meta.generics.UpdatesHandler;
|
|
||||||
import org.telegram.telegrambots.meta.generics.UpdatesReader;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InvalidObjectException;
|
import java.io.InvalidObjectException;
|
||||||
@ -142,7 +138,7 @@ public class DefaultBotSession implements BotSession {
|
|||||||
private final UpdatesSupplier updatesSupplier;
|
private final UpdatesSupplier updatesSupplier;
|
||||||
private final Object lock;
|
private final Object lock;
|
||||||
private CloseableHttpClient httpclient;
|
private CloseableHttpClient httpclient;
|
||||||
private ExponentialBackOff exponentialBackOff;
|
private BackOff backOff;
|
||||||
private RequestConfig requestConfig;
|
private RequestConfig requestConfig;
|
||||||
|
|
||||||
public ReaderThread(UpdatesSupplier updatesSupplier, Object lock) {
|
public ReaderThread(UpdatesSupplier updatesSupplier, Object lock) {
|
||||||
@ -154,10 +150,11 @@ public class DefaultBotSession implements BotSession {
|
|||||||
public synchronized void start() {
|
public synchronized void start() {
|
||||||
httpclient = TelegramHttpClientBuilder.build(options);
|
httpclient = TelegramHttpClientBuilder.build(options);
|
||||||
requestConfig = options.getRequestConfig();
|
requestConfig = options.getRequestConfig();
|
||||||
exponentialBackOff = options.getExponentialBackOff();
|
backOff = options.getBackOff();
|
||||||
|
|
||||||
if (exponentialBackOff == null) {
|
// fall back to default exponential backoff strategy if no backoff specified
|
||||||
exponentialBackOff = new ExponentialBackOff();
|
if (backOff == null) {
|
||||||
|
backOff = new ExponentialBackOff();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestConfig == null) {
|
if (requestConfig == null) {
|
||||||
@ -215,7 +212,7 @@ public class DefaultBotSession implements BotSession {
|
|||||||
log.error(global.getLocalizedMessage(), global);
|
log.error(global.getLocalizedMessage(), global);
|
||||||
try {
|
try {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
lock.wait(exponentialBackOff.nextBackOffMillis());
|
lock.wait(backOff.nextBackOffMillis());
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
if (!running.get()) {
|
if (!running.get()) {
|
||||||
@ -261,7 +258,7 @@ public class DefaultBotSession implements BotSession {
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
List<Update> updates = request.deserializeResponse(responseContent);
|
List<Update> updates = request.deserializeResponse(responseContent);
|
||||||
exponentialBackOff.reset();
|
backOff.reset();
|
||||||
return updates;
|
return updates;
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
log.error("Error deserializing update: " + responseContent, e);
|
log.error("Error deserializing update: " + responseContent, e);
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
package org.telegram.telegrambots.updatesreceivers;
|
package org.telegram.telegrambots.updatesreceivers;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
import org.telegram.telegrambots.meta.generics.BackOff;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of BackOff that increases the back off period for each retry attempt using
|
* Implementation of BackOff that increases the back off period for each retry attempt using
|
||||||
@ -68,7 +69,7 @@ import com.google.common.base.Preconditions;
|
|||||||
* @since 1.15
|
* @since 1.15
|
||||||
* @author Ravi Mistry
|
* @author Ravi Mistry
|
||||||
*/
|
*/
|
||||||
public class ExponentialBackOff {
|
public class ExponentialBackOff implements BackOff {
|
||||||
/** The default initial interval value in milliseconds (0.5 seconds). */
|
/** The default initial interval value in milliseconds (0.5 seconds). */
|
||||||
private static final int DEFAULT_INITIAL_INTERVAL_MILLIS = 500;
|
private static final int DEFAULT_INITIAL_INTERVAL_MILLIS = 500;
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ public class ExponentialBackOff {
|
|||||||
private static final double DEFAULT_MULTIPLIER = 1.5;
|
private static final double DEFAULT_MULTIPLIER = 1.5;
|
||||||
|
|
||||||
/** The default maximum back off time in milliseconds (15 minutes). */
|
/** The default maximum back off time in milliseconds (15 minutes). */
|
||||||
private static final int DEFAULT_MAX_INTERVAL_MILLIS = 30000;
|
private static final int DEFAULT_MAX_INTERVAL_MILLIS = 900000;
|
||||||
|
|
||||||
/** The default maximum elapsed time in milliseconds (60 minutes). */
|
/** The default maximum elapsed time in milliseconds (60 minutes). */
|
||||||
private static final int DEFAULT_MAX_ELAPSED_TIME_MILLIS = 3600000;
|
private static final int DEFAULT_MAX_ELAPSED_TIME_MILLIS = 3600000;
|
||||||
@ -161,7 +162,8 @@ public class ExponentialBackOff {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the interval back to the initial retry interval and restarts the timer. */
|
/** Sets the interval back to the initial retry interval and restarts the timer. */
|
||||||
final void reset() {
|
@Override
|
||||||
|
public void reset() {
|
||||||
currentIntervalMillis = initialIntervalMillis;
|
currentIntervalMillis = initialIntervalMillis;
|
||||||
startTimeNanos = nanoTime();
|
startTimeNanos = nanoTime();
|
||||||
}
|
}
|
||||||
@ -178,7 +180,8 @@ public class ExponentialBackOff {
|
|||||||
* Subclasses may override if a different algorithm is required.
|
* Subclasses may override if a different algorithm is required.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
long nextBackOffMillis() {
|
@Override
|
||||||
|
public long nextBackOffMillis() {
|
||||||
// Make sure we have not gone over the maximum elapsed time.
|
// Make sure we have not gone over the maximum elapsed time.
|
||||||
if (getElapsedTimeMillis() > maxElapsedTimeMillis) {
|
if (getElapsedTimeMillis() > maxElapsedTimeMillis) {
|
||||||
return maxElapsedTimeMillis;
|
return maxElapsedTimeMillis;
|
||||||
@ -274,7 +277,32 @@ public class ExponentialBackOff {
|
|||||||
*/
|
*/
|
||||||
int maxElapsedTimeMillis = DEFAULT_MAX_ELAPSED_TIME_MILLIS;
|
int maxElapsedTimeMillis = DEFAULT_MAX_ELAPSED_TIME_MILLIS;
|
||||||
|
|
||||||
Builder() {
|
public Builder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setInitialIntervalMillis(int initialIntervalMillis) {
|
||||||
|
this.initialIntervalMillis = initialIntervalMillis;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setRandomizationFactor(double randomizationFactor) {
|
||||||
|
this.randomizationFactor = randomizationFactor;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMultiplier(double multiplier) {
|
||||||
|
this.multiplier = multiplier;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMaxIntervalMillis(int maxIntervalMillis) {
|
||||||
|
this.maxIntervalMillis = maxIntervalMillis;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMaxElapsedTimeMillis(int maxElapsedTimeMillis) {
|
||||||
|
this.maxElapsedTimeMillis = maxElapsedTimeMillis;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Builds a new instance of {@link ExponentialBackOff}. */
|
/** Builds a new instance of {@link ExponentialBackOff}. */
|
||||||
|
@ -15,9 +15,11 @@ import org.mockito.Mockito;
|
|||||||
import org.telegram.telegrambots.bots.DefaultBotOptions;
|
import org.telegram.telegrambots.bots.DefaultBotOptions;
|
||||||
import org.telegram.telegrambots.meta.TelegramBotsApi;
|
import org.telegram.telegrambots.meta.TelegramBotsApi;
|
||||||
import org.telegram.telegrambots.meta.api.objects.Update;
|
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||||
|
import org.telegram.telegrambots.meta.generics.BackOff;
|
||||||
import org.telegram.telegrambots.meta.generics.LongPollingBot;
|
import org.telegram.telegrambots.meta.generics.LongPollingBot;
|
||||||
import org.telegram.telegrambots.test.Fakes.FakeLongPollingBot;
|
import org.telegram.telegrambots.test.Fakes.FakeLongPollingBot;
|
||||||
import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
|
import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
|
||||||
|
import org.telegram.telegrambots.updatesreceivers.ExponentialBackOff;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -139,6 +141,30 @@ public class TestDefaultBotSession {
|
|||||||
session.stop();
|
session.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultBotSessionWithCustomExponentialBackOff() {
|
||||||
|
ExponentialBackOff ex = new ExponentialBackOff.Builder()
|
||||||
|
.setInitialIntervalMillis(500)
|
||||||
|
.setRandomizationFactor(0.5)
|
||||||
|
.setMultiplier(1.5)
|
||||||
|
.setMaxIntervalMillis(900000)
|
||||||
|
.setMaxElapsedTimeMillis(3600000)
|
||||||
|
.build();
|
||||||
|
DefaultBotOptions options = new DefaultBotOptions();
|
||||||
|
options.setBackOff(ex);
|
||||||
|
DefaultBotSession session = new DefaultBotSession();
|
||||||
|
session.setOptions(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultBotSessionWithCustomConstantBackOff() {
|
||||||
|
DefaultBotOptions options = new DefaultBotOptions();
|
||||||
|
ConstantBackOff backOff = new ConstantBackOff(3000);
|
||||||
|
options.setBackOff(backOff);
|
||||||
|
DefaultBotSession session = new DefaultBotSession();
|
||||||
|
session.setOptions(options);
|
||||||
|
}
|
||||||
|
|
||||||
private Update[] createFakeUpdates(int count) {
|
private Update[] createFakeUpdates(int count) {
|
||||||
return IntStream.range(0, count).mapToObj(x -> {
|
return IntStream.range(0, count).mapToObj(x -> {
|
||||||
Update mock = Mockito.mock(Update.class);
|
Update mock = Mockito.mock(Update.class);
|
||||||
@ -178,4 +204,26 @@ public class TestDefaultBotSession {
|
|||||||
session.setOptions(new DefaultBotOptions());
|
session.setOptions(new DefaultBotOptions());
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ConstantBackOff implements BackOff {
|
||||||
|
|
||||||
|
private long backOffMillis;
|
||||||
|
|
||||||
|
ConstantBackOff() {
|
||||||
|
new ConstantBackOff(3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantBackOff(long millis) {
|
||||||
|
this.backOffMillis = millis;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long nextBackOffMillis() {
|
||||||
|
return backOffMillis;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user