Add MaxMind circuit breaker. Finishes #38
This commit is contained in:
parent
53a56401e0
commit
f0d8256f07
5
pom.xml
5
pom.xml
@ -79,6 +79,11 @@
|
|||||||
<artifactId>vertx-redis-client</artifactId>
|
<artifactId>vertx-redis-client</artifactId>
|
||||||
<version>3.3.0</version>
|
<version>3.3.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.vertx</groupId>
|
||||||
|
<artifactId>vertx-circuit-breaker</artifactId>
|
||||||
|
<version>3.3.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Google Libs -->
|
<!-- Google Libs -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -2,6 +2,8 @@ package net.frozenorb.apiv3.util;
|
|||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.mongodb.async.SingleResultCallback;
|
import com.mongodb.async.SingleResultCallback;
|
||||||
|
import io.vertx.circuitbreaker.CircuitBreaker;
|
||||||
|
import io.vertx.circuitbreaker.CircuitBreakerOptions;
|
||||||
import io.vertx.core.http.HttpClient;
|
import io.vertx.core.http.HttpClient;
|
||||||
import io.vertx.core.http.HttpClientOptions;
|
import io.vertx.core.http.HttpClientOptions;
|
||||||
import io.vertx.core.json.JsonObject;
|
import io.vertx.core.json.JsonObject;
|
||||||
@ -17,13 +19,23 @@ public class MaxMindUtils {
|
|||||||
private static final String maxMindUserId = APIv3.getConfig().getProperty("maxMind.userId");
|
private static final String maxMindUserId = APIv3.getConfig().getProperty("maxMind.userId");
|
||||||
private static final String maxMindLicenseKey = APIv3.getConfig().getProperty("maxMind.maxMindLicenseKey");
|
private static final String maxMindLicenseKey = APIv3.getConfig().getProperty("maxMind.maxMindLicenseKey");
|
||||||
private static final HttpClient httpsClient = APIv3.getVertxInstance().createHttpClient(new HttpClientOptions().setSsl(true).setTrustAll(true));
|
private static final HttpClient httpsClient = APIv3.getVertxInstance().createHttpClient(new HttpClientOptions().setSsl(true).setTrustAll(true));
|
||||||
|
private static final CircuitBreaker breaker;
|
||||||
|
|
||||||
public static void getInsights(String ip, SingleResultCallback<MaxMindResult> callback) {
|
// MaxMind likes to randomly not respond, so we take advantage of the circuit breaker pattern to only
|
||||||
if (1 == 1) {
|
// check MaxMind periodically (while it's in a non-responsive state) to keep our average response times
|
||||||
callback.onResult(null, null);
|
// nice and low.
|
||||||
return;
|
static {
|
||||||
|
breaker = CircuitBreaker.create("maxmind-circuit-breaker", APIv3.getVertxInstance(),
|
||||||
|
new CircuitBreakerOptions()
|
||||||
|
.setMaxFailures(5)
|
||||||
|
.setTimeout(1000) // 1 second
|
||||||
|
.setFallbackOnFailure(true)
|
||||||
|
.setResetTimeout(120_000) // 2 minutes
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void getInsights(String ip, SingleResultCallback<MaxMindResult> callback) {
|
||||||
|
breaker.executeWithFallback((future) -> {
|
||||||
String authHeader = "Basic " + Base64.getEncoder().encodeToString((maxMindUserId + ":" + maxMindLicenseKey).getBytes(Charsets.UTF_8));
|
String authHeader = "Basic " + Base64.getEncoder().encodeToString((maxMindUserId + ":" + maxMindLicenseKey).getBytes(Charsets.UTF_8));
|
||||||
|
|
||||||
httpsClient.get(443, "geoip.maxmind.com", "/geoip/v2.1/insights/" + ip, (response) -> {
|
httpsClient.get(443, "geoip.maxmind.com", "/geoip/v2.1/insights/" + ip, (response) -> {
|
||||||
@ -32,17 +44,23 @@ public class MaxMindUtils {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
MaxMindResult maxMindResult = new MaxMindResult(bodyJson);
|
MaxMindResult maxMindResult = new MaxMindResult(bodyJson);
|
||||||
callback.onResult(maxMindResult, null);
|
future.complete(maxMindResult);
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
callback.onResult(null, null);
|
future.complete(null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
response.exceptionHandler((error) -> callback.onResult(null, error));
|
response.exceptionHandler(future::fail);
|
||||||
})
|
})
|
||||||
.putHeader("Authorization", authHeader)
|
.putHeader("Authorization", authHeader)
|
||||||
.setTimeout(1000)
|
|
||||||
.end();
|
.end();
|
||||||
|
}, (ignored) -> null).setHandler((result) -> { // The (ignored) -> null section is our fallback, which just returns null (when the breaker is open)
|
||||||
|
if (result.failed()) {
|
||||||
|
callback.onResult(null, result.cause());
|
||||||
|
} else {
|
||||||
|
callback.onResult((MaxMindResult) result.result(), null);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getEnglishName(JsonObject source) {
|
public static String getEnglishName(JsonObject source) {
|
||||||
|
Loading…
Reference in New Issue
Block a user