mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-19 20:25:31 +00:00
Implemented back off handling for consecutively failed calls.
This commit is contained in:
+23
-19
@@ -5,6 +5,7 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
@@ -20,6 +21,7 @@ import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.sap.sailing.domain.windfinder.ReviewedSpotsCollection;
|
||||
import com.sap.sailing.domain.windfinder.Spot;
|
||||
import com.sap.sse.common.util.BackoffTracker;
|
||||
import com.sap.sse.util.HttpUrlConnectionHelper;
|
||||
import com.sap.sse.util.ThreadPoolUtil;
|
||||
|
||||
@@ -42,18 +44,17 @@ public class ReviewedSpotsCollectionImpl implements ReviewedSpotsCollection {
|
||||
* map initialized with the result of calling {@link #loadSpots()}.
|
||||
*/
|
||||
private Future<ConcurrentMap<String, Spot>> spotsByIdCache;
|
||||
|
||||
private BackoffTracker backoffTracker;
|
||||
|
||||
public ReviewedSpotsCollectionImpl(String id) {
|
||||
this.id = id;
|
||||
this.parser = new WindFinderReportParser();
|
||||
this.spotsByIdCache = ThreadPoolUtil.INSTANCE.getDefaultForegroundTaskThreadPoolExecutor().schedule(()->{
|
||||
this.spotsByIdCache = ThreadPoolUtil.INSTANCE.getDefaultForegroundTaskThreadPoolExecutor().schedule(() -> {
|
||||
backoffTracker = new BackoffTracker(TimeUnit.SECONDS.toMillis(5), 2);
|
||||
final ConcurrentMap<String, Spot> result = new ConcurrentHashMap<>();
|
||||
try {
|
||||
for (final Spot spot : loadSpots()) {
|
||||
result.put(spot.getId(), spot);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Problem loading spots for spot collection "+id, e);
|
||||
for (final Spot spot : loadSpots()) {
|
||||
result.put(spot.getId(), spot);
|
||||
}
|
||||
return result;
|
||||
}, /* delay */ 0, TimeUnit.MILLISECONDS);
|
||||
@@ -103,19 +104,22 @@ public class ReviewedSpotsCollectionImpl implements ReviewedSpotsCollection {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Iterable<Spot> loadSpots() throws IOException, ParseException, MalformedURLException {
|
||||
final Iterable<Spot> result;
|
||||
final InputStreamReader in = new InputStreamReader(
|
||||
(InputStream) HttpUrlConnectionHelper.redirectConnection(
|
||||
new URL(Activator.BASE_URL_FOR_JSON_DOCUMENTS+"/"+getId()+SPOT_LIST_DOCUMENT_SUFFIX))
|
||||
.getContent());
|
||||
try {
|
||||
JSONArray spotsAsJson = (JSONArray) new JSONParser().parse(in);
|
||||
result = parser.parseSpots(spotsAsJson, this);
|
||||
return result;
|
||||
} finally {
|
||||
in.close();
|
||||
private Iterable<Spot> loadSpots() {
|
||||
Iterable<Spot> result = Collections.emptySet();
|
||||
if (!backoffTracker.backOff()) {
|
||||
try (InputStreamReader in = new InputStreamReader((InputStream) HttpUrlConnectionHelper
|
||||
.redirectConnection(
|
||||
new URL(Activator.BASE_URL_FOR_JSON_DOCUMENTS + "/" + getId() + SPOT_LIST_DOCUMENT_SUFFIX))
|
||||
.getContent())) {
|
||||
JSONArray spotsAsJson = (JSONArray) new JSONParser().parse(in);
|
||||
result = parser.parseSpots(spotsAsJson, this);
|
||||
backoffTracker.clear();
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Problem loading spots for spot collection " + id, e);
|
||||
backoffTracker.logFailure();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.sap.sse.common.util;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BackoffTracker {
|
||||
private Long backOffUntil;
|
||||
private final int factor;
|
||||
private Long currentTimeoutInMillis;
|
||||
private final Long initialTimeoutInMillis;
|
||||
private static final Long maxTimeout = TimeUnit.MINUTES.toMillis(5);
|
||||
|
||||
/**
|
||||
* A tracker to handle continous failures of processes. Before every process execution call {@link #backOff()} to query whether there is a timeout.
|
||||
* Every failure should call {@link #logFailure()}, which will increase the time until {@link #backOff()} returns false again.
|
||||
* @param initialTimeoutInMillis
|
||||
* @param backoffMultiplier: The factor by which the timeout will be multiplied on consecutive failures
|
||||
*/
|
||||
public BackoffTracker(Long initialTimeoutInMillis, int backoffMultiplier) {
|
||||
this.initialTimeoutInMillis = initialTimeoutInMillis;
|
||||
this.factor = backoffMultiplier;
|
||||
}
|
||||
|
||||
public void logFailure() {
|
||||
if(currentTimeoutInMillis == null) {
|
||||
currentTimeoutInMillis = initialTimeoutInMillis;
|
||||
}
|
||||
final Long newTimeOut = currentTimeoutInMillis * factor;
|
||||
currentTimeoutInMillis = newTimeOut >= maxTimeout ? maxTimeout : newTimeOut;
|
||||
backOffUntil = System.currentTimeMillis() + currentTimeoutInMillis;
|
||||
}
|
||||
|
||||
public boolean backOff() {
|
||||
return backOffUntil == null ? false : backOffUntil > System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
currentTimeoutInMillis = null;
|
||||
backOffUntil = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user