Skip to content

Commit

Permalink
Refactoring SolveRemote Module (#460)
Browse files Browse the repository at this point in the history
* creating and binding service to clear the cache

* refactoring

* refactoriong

* refactoring and fixed test

* refactoring

* reactivated the tests

* refactoring and testing circuit breaker

* unnecessary test, the current active test shows that when a circuit exception or CircuitBreakerOpenException is thrown, it will return an empty result, not throws exception

* refactoring

* release notes

* [Gradle Release Plugin] - new version commit:  '3.18.5-snapshot'.

* refactoring

* revert
  • Loading branch information
mageddo authored Jun 3, 2024
1 parent e13b5c1 commit 71a6e38
Show file tree
Hide file tree
Showing 20 changed files with 404 additions and 239 deletions.
3 changes: 3 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 3.18.5
* Refactor `SolverRemote` module, see #459.

## 3.18.4
* Refactor `SolverRemote` solver class, see #459.

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=3.18.4-snapshot
version=3.18.5-snapshot
4 changes: 3 additions & 1 deletion src/main/java/com/mageddo/dnsproxyserver/di/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.mageddo.dnsproxyserver.di.module.ModuleMap;
import com.mageddo.dnsproxyserver.di.module.ModuleSolver;
import com.mageddo.dnsproxyserver.di.module.ModuleStartup;
import com.mageddo.dnsproxyserver.solver.remote.configurator.SolverRemoteModule;
import com.mageddo.dnsproxyserver.docker.dataprovider.DockerNetworkFacade;
import com.mageddo.dnsproxyserver.quarkus.QuarkusConfig;
import com.mageddo.dnsproxyserver.server.Starter;
Expand Down Expand Up @@ -36,7 +37,8 @@
ModuleSolver.class,
ModuleStartup.class,
ModuleMap.class,
ModuleConfigDAO.class
ModuleConfigDAO.class,
SolverRemoteModule.class
})
public interface Context {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package com.mageddo.dnsproxyserver.quarkus;

import com.mageddo.dnsproxyserver.config.application.Configs;
import com.mageddo.dnsproxyserver.solver.RemoteResolvers;
import com.mageddo.dnsproxyserver.solver.Resolver;
import com.mageddo.dnsproxyserver.solver.SimpleResolver;
import com.mageddo.dnsproxyserver.solver.remote.mapper.ResolverMapper;
import com.mageddo.net.IpAddr;
import com.mageddo.dnsproxyserver.solver.RemoteResolvers;
import com.mageddo.dnsproxyserver.utils.InetAddresses;
import dagger.Module;
import dagger.Provides;

import javax.enterprise.inject.Produces;
import java.time.Duration;
import java.util.function.Function;

@Module
Expand All @@ -28,11 +26,7 @@ public RemoteResolvers remoteResolvers(Function<IpAddr, Resolver> resolverProvid
@Produces
@Provides
public Function<IpAddr, Resolver> getResolverProvider() {
return it -> {
final var resolver = new SimpleResolver(InetAddresses.toSocketAddress(it.getRawIP(), it.getPortOrDef(53)));
resolver.setTimeout(Duration.ofSeconds(10)); // default is 10 seconds
return resolver;
};
return ResolverMapper::from;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,7 @@ private List<SolverCache> getCaches() {

public void clear(Name name) {
if (name == null) {
for (final var cache : this.getCaches()) {
cache.clear();
}
this.clearCaches();
return;
}
this.getInstance(name).clear();
Expand All @@ -73,4 +71,10 @@ public Map<String, Integer> findInstancesSizeMap(Name name) {
.collect(Collectors.toMap(it -> it.name().name(), SolverCache::getSize))
;
}

public void clearCaches() {
for (final var cache : this.getCaches()) {
cache.clear();
}
}
}
130 changes: 5 additions & 125 deletions src/main/java/com/mageddo/dnsproxyserver/solver/SolverRemote.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,11 @@

import com.mageddo.commons.circuitbreaker.CircuitCheckException;
import com.mageddo.dns.utils.Messages;
import com.mageddo.dnsproxyserver.config.application.ConfigService;
import com.mageddo.net.IpAddr;
import com.mageddo.net.IpAddrs;
import com.mageddo.dnsproxyserver.solver.remote.Request;
import com.mageddo.dnsproxyserver.solver.remote.Result;
import com.mageddo.dnsproxyserver.solver.remote.CircuitBreakerService;
import com.mageddo.net.NetExecutorWatchdog;
import dev.failsafe.CircuitBreaker;
import dev.failsafe.CircuitBreakerOpenException;
import dev.failsafe.Failsafe;
import lombok.Builder;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.time.StopWatch;
Expand All @@ -22,12 +16,8 @@
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
Expand All @@ -42,10 +32,8 @@ public class SolverRemote implements Solver, AutoCloseable {
static final String QUERY_TIMED_OUT_MSG = "Query timed out";

private final RemoteResolvers delegate;
private final Map<InetSocketAddress, CircuitBreaker<Result>> circuitBreakerMap = new ConcurrentHashMap<>();
private final NetExecutorWatchdog netWatchdog = new NetExecutorWatchdog();
private final ConfigService configService;
private String status;
private final CircuitBreakerService circuitBreakerService;

@Override
public Response handle(Message query) {
Expand Down Expand Up @@ -94,17 +82,7 @@ Request buildRequest(Message query, int resolverIndex, StopWatch stopWatch, Reso

Result safeQueryResult(Request req) {
req.splitStopWatch();
final var circuitBreaker = this.circuitBreakerFor(req.getResolverAddress());
try {
return Failsafe
.with(circuitBreaker)
.get((ctx) -> this.queryResultWhilePingingResolver(req));
} catch (CircuitCheckException | CircuitBreakerOpenException e) {
final var clazz = ClassUtils.getSimpleName(e);
log.debug("status=circuitEvent, server={}, type={}", req.getResolverAddress(), clazz);
this.status = String.format("%s for %s", clazz, req.getResolverAddress());
return Result.empty();
}
return this.circuitBreakerService.handle(req, () -> this.queryResultWhilePingingResolver(req));
}

Result queryResultWhilePingingResolver(Request req) {
Expand Down Expand Up @@ -165,107 +143,9 @@ void checkCircuitError(Exception e, Request request) {
}
}

CircuitBreaker<Result> circuitBreakerFor(InetSocketAddress address) {
final var config = this.findCircuitBreakerConfig();
return this.circuitBreakerMap.computeIfAbsent(address, inetSocketAddress -> buildCircuitBreaker(config));
}

static CircuitBreaker<Result> buildCircuitBreaker(com.mageddo.dnsproxyserver.config.CircuitBreaker config) {
return CircuitBreaker.<Result>builder()
.handle(CircuitCheckException.class)
.withFailureThreshold(config.getFailureThreshold(), config.getFailureThresholdCapacity())
.withSuccessThreshold(config.getSuccessThreshold())
.withDelay(config.getTestDelay())
.build();
}

com.mageddo.dnsproxyserver.config.CircuitBreaker findCircuitBreakerConfig() {
return this.configService.findCurrentConfig()
.getSolverRemote()
.getCircuitBreaker();
}

String getStatus() {
return this.status;
}

@Override
public void close() throws Exception {
this.netWatchdog.close();
}

@Value
@Builder
static class Request {

@NonNull
Message query;

@NonNull
Resolver resolver;

@NonNull
Integer resolverIndex;

@NonNull
StopWatch stopWatch;

public IpAddr getResolverAddr() {
return IpAddrs.from(this.getResolverAddress());
}

public InetSocketAddress getResolverAddress() {
return this.getResolver().getAddress();
}

public void splitStopWatch() {
this.stopWatch.split();
}

public CompletableFuture<Message> sendQueryAsyncToResolver() {
return this.resolver.sendAsync(this.query).toCompletableFuture();
}

public long getElapsedTimeInMs() {
return this.stopWatch.getTime() - this.stopWatch.getSplitTime();
}

public long getTime() {
return this.stopWatch.getTime();
}
}

@Value
@Builder
static class Result {

private Response successResponse;
private Message errorMessage;

public static Result empty() {
return Result.builder().build();
}

public static Result fromErrorMessage(Message message) {
return builder().errorMessage(message).build();
}

public static Result fromSuccessResponse(Response res) {
return Result.builder().successResponse(res).build();
}

public boolean hasSuccessMessage() {
return this.successResponse != null;
}

public boolean hasErrorMessage() {
return this.errorMessage != null;
}

public Response getErrorResponse() {
return Optional.ofNullable(this.errorMessage)
.map(Response::nxDomain)
.orElse(null);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.mageddo.dnsproxyserver.solver.remote;

import java.util.function.Supplier;

public interface CircuitBreakerService {

Result handle(Request req, Supplier<Result> sup);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.mageddo.dnsproxyserver.solver.remote;

import com.mageddo.dnsproxyserver.solver.Resolver;
import com.mageddo.net.IpAddr;
import com.mageddo.net.IpAddrs;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import org.apache.commons.lang3.time.StopWatch;
import org.xbill.DNS.Message;

import java.net.InetSocketAddress;
import java.util.concurrent.CompletableFuture;

@Value
@Builder
public class Request {

@NonNull
Message query;

@NonNull
Resolver resolver;

@NonNull
Integer resolverIndex;

@NonNull
StopWatch stopWatch;

public IpAddr getResolverAddr() {
return IpAddrs.from(this.getResolverAddress());
}

public InetSocketAddress getResolverAddress() {
return this.getResolver().getAddress();
}

public void splitStopWatch() {
this.stopWatch.split();
}

public CompletableFuture<Message> sendQueryAsyncToResolver() {
return this.resolver.sendAsync(this.query).toCompletableFuture();
}

public long getElapsedTimeInMs() {
return this.stopWatch.getTime() - this.stopWatch.getSplitTime();
}

public long getTime() {
return this.stopWatch.getTime();
}
}
47 changes: 47 additions & 0 deletions src/main/java/com/mageddo/dnsproxyserver/solver/remote/Result.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.mageddo.dnsproxyserver.solver.remote;

import com.mageddo.dnsproxyserver.solver.Response;
import lombok.Builder;
import lombok.Value;
import org.apache.commons.lang3.ObjectUtils;
import org.xbill.DNS.Message;

import java.util.Optional;

@Value
@Builder
public class Result {

private Response successResponse;
private Message errorMessage;

public static Result empty() {
return Result.builder().build();
}

public static Result fromErrorMessage(Message message) {
return builder().errorMessage(message).build();
}

public static Result fromSuccessResponse(Response res) {
return Result.builder().successResponse(res).build();
}

public boolean hasSuccessMessage() {
return this.successResponse != null;
}

public boolean hasErrorMessage() {
return this.errorMessage != null;
}

public Response getErrorResponse() {
return Optional.ofNullable(this.errorMessage)
.map(Response::nxDomain)
.orElse(null);
}

public boolean isEmpty() {
return ObjectUtils.allNull(this.errorMessage, this.successResponse);
}
}
Loading

0 comments on commit 71a6e38

Please sign in to comment.