From e62317bab05f0e889a4cafbff6a2c7979d6a4ea3 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 14:06:19 -0300 Subject: [PATCH 01/70] setup resilience4j --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 05a85c8bb..b84c1ff58 100644 --- a/build.gradle +++ b/build.gradle @@ -65,6 +65,7 @@ dependencies { implementation('org.apache.commons:commons-compress:1.22') implementation('org.rauschig:jarchivelib:1.2.0') implementation('dev.failsafe:failsafe:3.3.1') + implementation("io.github.resilience4j:resilience4j-circuitbreaker:2.2.0") implementation('com.github.docker-java:docker-java-core:3.3.4') implementation('com.github.docker-java:docker-java-transport-httpclient5:3.3.4') From 742a0e8bf9c5b386a61827807eea7a13a7fc4601 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 14:24:09 -0300 Subject: [PATCH 02/70] specifying circuit breaker strategy name --- build.gradle | 2 +- .../java/com/mageddo/dnsproxyserver/config/Config.java | 2 +- .../com/mageddo/dnsproxyserver/config/SolverRemote.java | 2 +- ...er.java => StaticThresholdCircuitBreakerStrategy.java} | 6 +++--- .../config/dataprovider/mapper/ConfigJsonV2Mapper.java | 4 ++-- .../dnsproxyserver/config/mapper/ConfigMapper.java | 6 +++--- .../config/validator/CircuitBreakerValidator.java | 4 ++-- .../application/failsafe/CircuitBreakerFactory.java | 5 +++-- .../testing/templates/CircuitBreakerConfigTemplates.java | 8 ++++---- 9 files changed, 20 insertions(+), 19 deletions(-) rename src/main/java/com/mageddo/dnsproxyserver/config/{CircuitBreaker.java => StaticThresholdCircuitBreakerStrategy.java} (74%) diff --git a/build.gradle b/build.gradle index b84c1ff58..fa4141cfb 100644 --- a/build.gradle +++ b/build.gradle @@ -64,7 +64,7 @@ dependencies { implementation('dnsjava:dnsjava:3.5.2') implementation('org.apache.commons:commons-compress:1.22') implementation('org.rauschig:jarchivelib:1.2.0') - implementation('dev.failsafe:failsafe:3.3.1') +// implementation('dev.failsafe:failsafe:3.3.1') implementation("io.github.resilience4j:resilience4j-circuitbreaker:2.2.0") implementation('com.github.docker-java:docker-java-core:3.3.4') diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java index 99294512d..1cd9822b3 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java @@ -90,7 +90,7 @@ public void resetConfigFile() { } @JsonIgnore - public CircuitBreaker getSolverRemoteCircuitBreaker() { + public StaticThresholdCircuitBreakerStrategy getSolverRemoteCircuitBreaker() { if (this.solverRemote == null) { return null; } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/SolverRemote.java b/src/main/java/com/mageddo/dnsproxyserver/config/SolverRemote.java index afc3011fc..b858c1004 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/SolverRemote.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/SolverRemote.java @@ -9,5 +9,5 @@ public class SolverRemote { private Boolean active; - private CircuitBreaker circuitBreaker; + private StaticThresholdCircuitBreakerStrategy circuitBreaker; } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreaker.java b/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java similarity index 74% rename from src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreaker.java rename to src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java index da00224a0..d3ea2224b 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreaker.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java @@ -8,7 +8,7 @@ @Value @Builder -public class CircuitBreaker { +public class StaticThresholdCircuitBreakerStrategy { /** * See {@link dev.failsafe.CircuitBreakerBuilder#withFailureThreshold(int, int)} @@ -26,7 +26,7 @@ public class CircuitBreaker { */ private Duration testDelay; - public static CircuitBreaker empty() { - return CircuitBreaker.builder().build(); + public static StaticThresholdCircuitBreakerStrategy empty() { + return StaticThresholdCircuitBreakerStrategy.builder().build(); } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java index a7744db50..b35f60c6c 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java @@ -1,6 +1,6 @@ package com.mageddo.dnsproxyserver.config.dataprovider.mapper; -import com.mageddo.dnsproxyserver.config.CircuitBreaker; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; import com.mageddo.dnsproxyserver.config.Config; import com.mageddo.dnsproxyserver.config.SolverRemote; import com.mageddo.dnsproxyserver.config.dataprovider.vo.ConfigJson; @@ -63,7 +63,7 @@ static SolverRemote buildCompleteSolverRemote(ConfigJson json, ConfigJsonV2.Circ return SolverRemote .builder() .active(Booleans.reverseWhenNotNull(json.getNoRemoteServers())) - .circuitBreaker(CircuitBreaker + .circuitBreaker(StaticThresholdCircuitBreakerStrategy .builder() .failureThreshold(circuitBreaker.getFailureThreshold()) .failureThresholdCapacity(circuitBreaker.getFailureThresholdCapacity()) diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java b/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java index 8865547d1..ac4913f32 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java @@ -1,6 +1,6 @@ package com.mageddo.dnsproxyserver.config.mapper; -import com.mageddo.dnsproxyserver.config.CircuitBreaker; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; import com.mageddo.dnsproxyserver.config.Config; import com.mageddo.dnsproxyserver.config.SolverRemote; import com.mageddo.dnsproxyserver.config.dataprovider.ConfigPropDAO; @@ -74,8 +74,8 @@ private static Config buildDefault() { .build(); } - public static CircuitBreaker defaultCircuitBreaker() { - return CircuitBreaker + public static StaticThresholdCircuitBreakerStrategy defaultCircuitBreaker() { + return StaticThresholdCircuitBreakerStrategy .builder() .failureThreshold(3) .failureThresholdCapacity(10) diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/validator/CircuitBreakerValidator.java b/src/main/java/com/mageddo/dnsproxyserver/config/validator/CircuitBreakerValidator.java index 4aca74b53..e8f917349 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/validator/CircuitBreakerValidator.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/validator/CircuitBreakerValidator.java @@ -1,12 +1,12 @@ package com.mageddo.dnsproxyserver.config.validator; -import com.mageddo.dnsproxyserver.config.CircuitBreaker; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; import org.apache.commons.lang3.Validate; import static com.mageddo.dnsproxyserver.utils.Numbers.positiveOrNull; public class CircuitBreakerValidator { - public static void validate(CircuitBreaker circuit) { + public static void validate(StaticThresholdCircuitBreakerStrategy circuit) { Validate.notNull(positiveOrNull(circuit.getFailureThreshold()), genMsg("failure theshold must be a positive number")); Validate.notNull(positiveOrNull(circuit.getSuccessThreshold()), genMsg("success theshold must be positive number")); Validate.notNull(positiveOrNull(circuit.getFailureThresholdCapacity()), genMsg("success theshold capacity must be positive number")); diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java index 7c48610a6..90b02548d 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java @@ -3,6 +3,7 @@ import com.mageddo.circuitbreaker.failsafe.CircuitStatusRefresh; import com.mageddo.commons.circuitbreaker.CircuitCheckException; import com.mageddo.commons.lang.tuple.Pair; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; import com.mageddo.dnsproxyserver.config.application.ConfigService; import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; import com.mageddo.dnsproxyserver.solver.remote.Result; @@ -48,7 +49,7 @@ CircuitBreaker createOrGetCircuitBreaker(InetSocketAddress address) { } CircuitBreaker buildCircuitBreaker( - InetSocketAddress address, com.mageddo.dnsproxyserver.config.CircuitBreaker config + InetSocketAddress address, StaticThresholdCircuitBreakerStrategy config ) { return CircuitBreaker.builder() .handle(CircuitCheckException.class) @@ -86,7 +87,7 @@ void flushCache() { this.solverConsistencyGuaranteeDAO.flushCachesFromCircuitBreakerStateChange(); } - com.mageddo.dnsproxyserver.config.CircuitBreaker findCircuitBreakerConfig() { + StaticThresholdCircuitBreakerStrategy findCircuitBreakerConfig() { return this.configService.findCurrentConfig() .getSolverRemote() .getCircuitBreaker(); diff --git a/src/test/java/testing/templates/CircuitBreakerConfigTemplates.java b/src/test/java/testing/templates/CircuitBreakerConfigTemplates.java index 81af0f357..f4a55a003 100644 --- a/src/test/java/testing/templates/CircuitBreakerConfigTemplates.java +++ b/src/test/java/testing/templates/CircuitBreakerConfigTemplates.java @@ -1,17 +1,17 @@ package testing.templates; -import com.mageddo.dnsproxyserver.config.CircuitBreaker; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; import com.mageddo.dnsproxyserver.config.mapper.ConfigMapper; import java.time.Duration; public class CircuitBreakerConfigTemplates { - public static CircuitBreaker buildDefault(){ + public static StaticThresholdCircuitBreakerStrategy buildDefault(){ return ConfigMapper.defaultCircuitBreaker(); } - public static CircuitBreaker oneTryFailSuccess() { - return CircuitBreaker + public static StaticThresholdCircuitBreakerStrategy oneTryFailSuccess() { + return StaticThresholdCircuitBreakerStrategy .builder() .successThreshold(1) .failureThreshold(1) From 6ab3d76c2d874a74a599cf4c845623ea20ec567c Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 14:29:38 -0300 Subject: [PATCH 03/70] creating agnostic interface to support multiple circuit breaker strategy types --- build.gradle | 2 +- .../dnsproxyserver/config/CircuitBreakerStrategy.java | 11 +++++++++++ .../com/mageddo/dnsproxyserver/config/Config.java | 2 +- .../mageddo/dnsproxyserver/config/SolverRemote.java | 2 +- .../config/StaticThresholdCircuitBreakerStrategy.java | 7 ++++++- .../config/validator/ConfigValidator.java | 4 +++- .../application/failsafe/CircuitBreakerFactory.java | 3 ++- 7 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java diff --git a/build.gradle b/build.gradle index fa4141cfb..b84c1ff58 100644 --- a/build.gradle +++ b/build.gradle @@ -64,7 +64,7 @@ dependencies { implementation('dnsjava:dnsjava:3.5.2') implementation('org.apache.commons:commons-compress:1.22') implementation('org.rauschig:jarchivelib:1.2.0') -// implementation('dev.failsafe:failsafe:3.3.1') + implementation('dev.failsafe:failsafe:3.3.1') implementation("io.github.resilience4j:resilience4j-circuitbreaker:2.2.0") implementation('com.github.docker-java:docker-java-core:3.3.4') diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java b/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java new file mode 100644 index 000000000..1cc48dc1b --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java @@ -0,0 +1,11 @@ +package com.mageddo.dnsproxyserver.config; + +public interface CircuitBreakerStrategy { + + Name type(); + + enum Name { + STATIC_THRESHOLD, + CANARY_RATE_THRESHOLD, + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java index 1cd9822b3..fb54467f1 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java @@ -90,7 +90,7 @@ public void resetConfigFile() { } @JsonIgnore - public StaticThresholdCircuitBreakerStrategy getSolverRemoteCircuitBreaker() { + public CircuitBreakerStrategy getSolverRemoteCircuitBreaker() { if (this.solverRemote == null) { return null; } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/SolverRemote.java b/src/main/java/com/mageddo/dnsproxyserver/config/SolverRemote.java index b858c1004..f4613ab28 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/SolverRemote.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/SolverRemote.java @@ -9,5 +9,5 @@ public class SolverRemote { private Boolean active; - private StaticThresholdCircuitBreakerStrategy circuitBreaker; + private CircuitBreakerStrategy circuitBreaker; } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java b/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java index d3ea2224b..f86ded7fb 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java @@ -8,7 +8,7 @@ @Value @Builder -public class StaticThresholdCircuitBreakerStrategy { +public class StaticThresholdCircuitBreakerStrategy implements CircuitBreakerStrategy { /** * See {@link dev.failsafe.CircuitBreakerBuilder#withFailureThreshold(int, int)} @@ -29,4 +29,9 @@ public class StaticThresholdCircuitBreakerStrategy { public static StaticThresholdCircuitBreakerStrategy empty() { return StaticThresholdCircuitBreakerStrategy.builder().build(); } + + @Override + public Name type() { + return Name.STATIC_THRESHOLD; + } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/validator/ConfigValidator.java b/src/main/java/com/mageddo/dnsproxyserver/config/validator/ConfigValidator.java index db99b818d..f1917afaa 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/validator/ConfigValidator.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/validator/ConfigValidator.java @@ -1,6 +1,7 @@ package com.mageddo.dnsproxyserver.config.validator; import com.mageddo.dnsproxyserver.config.Config; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; import org.apache.commons.lang3.Validate; public class ConfigValidator { @@ -23,6 +24,7 @@ public static void validate(Config config) { Validate.notNull(config.getSolverRemote(), "Solver Remote"); Validate.notNull(config.isSolverRemoteActive(), "Solver remote active"); - CircuitBreakerValidator.validate(config.getSolverRemoteCircuitBreaker()); + // fixme #533 this could not work every time after new types be created, check it + CircuitBreakerValidator.validate((StaticThresholdCircuitBreakerStrategy) config.getSolverRemoteCircuitBreaker()); } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java index 90b02548d..828f369d9 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java @@ -88,7 +88,8 @@ void flushCache() { } StaticThresholdCircuitBreakerStrategy findCircuitBreakerConfig() { - return this.configService.findCurrentConfig() + // fixme #533 this could not work every time, check it + return (StaticThresholdCircuitBreakerStrategy) this.configService.findCurrentConfig() .getSolverRemote() .getCircuitBreaker(); } From 460233aafc6d93b24c27093f7f9b3b8957dafdf1 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 14:33:12 -0300 Subject: [PATCH 04/70] fixme --- .../config/dataprovider/mapper/ConfigJsonV2Mapper.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java index b35f60c6c..04e7deeaf 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java @@ -63,6 +63,8 @@ static SolverRemote buildCompleteSolverRemote(ConfigJson json, ConfigJsonV2.Circ return SolverRemote .builder() .active(Booleans.reverseWhenNotNull(json.getNoRemoteServers())) + // fixme #533 need to create a dynamic json parser for different strategies, + // then a dynamic mapper to the solver remote .circuitBreaker(StaticThresholdCircuitBreakerStrategy .builder() .failureThreshold(circuitBreaker.getFailureThreshold()) From d9c28521cc4d07f726b1628888a7d630cf44e482 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 15:17:39 -0300 Subject: [PATCH 05/70] sppliting circuit breaker factory --- .../mageddo/dnsproxyserver/config/Config.java | 2 +- .../config/mapper/ConfigMapper.java | 2 +- .../config/validator/ConfigValidator.java | 2 +- .../FailsafeCircuitBreakerFactory.java | 64 +++++++++++++++++++ .../failsafe/CircuitBreakerFactory.java | 57 ++++------------- .../FailsafeCircuitBreakerDelegate.java | 33 ++++++++++ .../application/CircuitBreakerDelegate.java | 13 ++++ .../CircuitBreakerExecutorService.java | 33 ++++++++++ 8 files changed, 157 insertions(+), 49 deletions(-) create mode 100644 src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactory.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/FailsafeCircuitBreakerDelegate.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegate.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerExecutorService.java diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java index fb54467f1..e1ada8fe9 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java @@ -90,7 +90,7 @@ public void resetConfigFile() { } @JsonIgnore - public CircuitBreakerStrategy getSolverRemoteCircuitBreaker() { + public CircuitBreakerStrategy getSolverRemoteCircuitBreakerStrategy() { if (this.solverRemote == null) { return null; } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java b/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java index ac4913f32..e5263df84 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java @@ -51,7 +51,7 @@ private static Config mapFrom0(List configs) { .solverRemote(SolverRemote .builder() .active(firstNonNullRequiring(mapField(Config::isSolverRemoteActive, configs))) - .circuitBreaker(firstNonNullRequiring(mapField(Config::getSolverRemoteCircuitBreaker, configs))) + .circuitBreaker(firstNonNullRequiring(mapField(Config::getSolverRemoteCircuitBreakerStrategy, configs))) .build() ) .build(); diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/validator/ConfigValidator.java b/src/main/java/com/mageddo/dnsproxyserver/config/validator/ConfigValidator.java index f1917afaa..7dfcf33b6 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/validator/ConfigValidator.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/validator/ConfigValidator.java @@ -25,6 +25,6 @@ public static void validate(Config config) { Validate.notNull(config.isSolverRemoteActive(), "Solver remote active"); // fixme #533 this could not work every time after new types be created, check it - CircuitBreakerValidator.validate((StaticThresholdCircuitBreakerStrategy) config.getSolverRemoteCircuitBreaker()); + CircuitBreakerValidator.validate((StaticThresholdCircuitBreakerStrategy) config.getSolverRemoteCircuitBreakerStrategy()); } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactory.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactory.java new file mode 100644 index 000000000..5acc44aec --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactory.java @@ -0,0 +1,64 @@ +package com.mageddo.dnsproxyserver.solver.remote.application; + +import com.mageddo.commons.circuitbreaker.CircuitCheckException; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; +import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; +import com.mageddo.dnsproxyserver.solver.remote.Result; +import com.mageddo.dnsproxyserver.solver.remote.dataprovider.SolverConsistencyGuaranteeDAO; +import com.mageddo.dnsproxyserver.solver.remote.mapper.CircuitBreakerStateMapper; +import dev.failsafe.CircuitBreaker; +import dev.failsafe.event.CircuitBreakerStateChangedEvent; +import dev.failsafe.event.EventListener; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.net.InetSocketAddress; + +@Slf4j +@Singleton +@RequiredArgsConstructor(onConstructor = @__({@Inject})) +public class FailsafeCircuitBreakerFactory { + + private final SolverConsistencyGuaranteeDAO solverConsistencyGuaranteeDAO; + + public CircuitBreaker build( + InetSocketAddress address, StaticThresholdCircuitBreakerStrategy config + ) { + return CircuitBreaker.builder() + .handle(CircuitCheckException.class) + .withFailureThreshold(config.getFailureThreshold(), config.getFailureThresholdCapacity()) + .withSuccessThreshold(config.getSuccessThreshold()) + .withDelay(config.getTestDelay()) + .onClose(build(CircuitStatus.CLOSED, address)) + .onOpen(build(CircuitStatus.OPEN, address)) + .onHalfOpen(it -> log.trace("status=halfOpen, server={}", address)) + .build(); + } + + EventListener build(CircuitStatus actualStateName, InetSocketAddress address) { + return event -> { + final var previousStateName = CircuitBreakerStateMapper.toStateNameFrom(event); + if (isHalfOpenToOpen(previousStateName, actualStateName)) { + log.trace("status=ignoredTransition, from={}, to={}", previousStateName, actualStateName); + return; + } + log.trace( + "status=beforeFlushCaches, address={}, previous={}, actual={}", address, previousStateName, actualStateName + ); + this.flushCache(); + log.debug( + "status=clearedCache, address={}, previous={}, actual={}", address, previousStateName, actualStateName + ); + }; + } + + void flushCache() { + this.solverConsistencyGuaranteeDAO.flushCachesFromCircuitBreakerStateChange(); + } + + private static boolean isHalfOpenToOpen(CircuitStatus previousStateName, CircuitStatus actualStateName) { + return CircuitStatus.HALF_OPEN.equals(previousStateName) && CircuitStatus.OPEN.equals(actualStateName); + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java index 828f369d9..a64f82f32 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java @@ -1,18 +1,16 @@ package com.mageddo.dnsproxyserver.solver.remote.application.failsafe; import com.mageddo.circuitbreaker.failsafe.CircuitStatusRefresh; -import com.mageddo.commons.circuitbreaker.CircuitCheckException; import com.mageddo.commons.lang.tuple.Pair; import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; import com.mageddo.dnsproxyserver.config.application.ConfigService; import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; import com.mageddo.dnsproxyserver.solver.remote.Result; -import com.mageddo.dnsproxyserver.solver.remote.dataprovider.SolverConsistencyGuaranteeDAO; +import com.mageddo.dnsproxyserver.solver.remote.application.FailsafeCircuitBreakerFactory; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegate; import com.mageddo.dnsproxyserver.solver.remote.mapper.CircuitBreakerStateMapper; import dev.failsafe.CircuitBreaker; import dev.failsafe.Failsafe; -import dev.failsafe.event.CircuitBreakerStateChangedEvent; -import dev.failsafe.event.EventListener; import lombok.RequiredArgsConstructor; import lombok.Value; import lombok.extern.slf4j.Slf4j; @@ -34,7 +32,11 @@ public class CircuitBreakerFactory { private final Map> circuitBreakerMap = new ConcurrentHashMap<>(); private final ConfigService configService; private final CircuitBreakerPingCheckerService circuitBreakerCheckerService; - private final SolverConsistencyGuaranteeDAO solverConsistencyGuaranteeDAO; + private final FailsafeCircuitBreakerFactory failsafeCircuitBreakerFactory; + + public CircuitBreakerDelegate findCircuitBreaker(InetSocketAddress resolverAddress) { + return new FailsafeCircuitBreakerDelegate(this.createOrGetCircuitBreaker(resolverAddress)); + } public Result check(InetSocketAddress remoteAddress, Supplier sup) { final var circuitBreaker = this.createOrGetCircuitBreaker(remoteAddress); @@ -45,46 +47,10 @@ public Result check(InetSocketAddress remoteAddress, Supplier sup) { CircuitBreaker createOrGetCircuitBreaker(InetSocketAddress address) { final var config = this.findCircuitBreakerConfig(); - return this.circuitBreakerMap.computeIfAbsent(address, addr -> buildCircuitBreaker(addr, config)); - } - - CircuitBreaker buildCircuitBreaker( - InetSocketAddress address, StaticThresholdCircuitBreakerStrategy config - ) { - return CircuitBreaker.builder() - .handle(CircuitCheckException.class) - .withFailureThreshold(config.getFailureThreshold(), config.getFailureThresholdCapacity()) - .withSuccessThreshold(config.getSuccessThreshold()) - .withDelay(config.getTestDelay()) - .onClose(build(CircuitStatus.CLOSED, address)) - .onOpen(build(CircuitStatus.OPEN, address)) - .onHalfOpen(it -> log.trace("status=halfOpen, server={}", address)) - .build(); - } - - EventListener build(CircuitStatus actualStateName, InetSocketAddress address) { - return event -> { - final var previousStateName = CircuitBreakerStateMapper.toStateNameFrom(event); - if (isHalfOpenToOpen(previousStateName, actualStateName)) { - log.trace("status=ignoredTransition, from={}, to={}", previousStateName, actualStateName); - return; - } - log.trace( - "status=beforeFlushCaches, address={}, previous={}, actual={}", address, previousStateName, actualStateName - ); - this.flushCache(); - log.debug( - "status=clearedCache, address={}, previous={}, actual={}", address, previousStateName, actualStateName - ); - }; - } - - private static boolean isHalfOpenToOpen(CircuitStatus previousStateName, CircuitStatus actualStateName) { - return CircuitStatus.HALF_OPEN.equals(previousStateName) && CircuitStatus.OPEN.equals(actualStateName); - } - - void flushCache() { - this.solverConsistencyGuaranteeDAO.flushCachesFromCircuitBreakerStateChange(); + return this.circuitBreakerMap.computeIfAbsent( + address, + addr -> this.failsafeCircuitBreakerFactory.build(addr, config) + ); } StaticThresholdCircuitBreakerStrategy findCircuitBreakerConfig() { @@ -139,7 +105,6 @@ private Stats toStats(InetSocketAddress remoteAddr) { return Stats.of(remoteAddr.toString(), state); } - @Value public static class Stats { diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/FailsafeCircuitBreakerDelegate.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/FailsafeCircuitBreakerDelegate.java new file mode 100644 index 000000000..3a4f64b5f --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/FailsafeCircuitBreakerDelegate.java @@ -0,0 +1,33 @@ +package com.mageddo.dnsproxyserver.solver.remote.application.failsafe; + +import com.mageddo.circuitbreaker.failsafe.CircuitStatusRefresh; +import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; +import com.mageddo.dnsproxyserver.solver.remote.Result; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegate; +import com.mageddo.dnsproxyserver.solver.remote.mapper.CircuitBreakerStateMapper; +import dev.failsafe.CircuitBreaker; +import dev.failsafe.Failsafe; + +import java.util.function.Supplier; + +public class FailsafeCircuitBreakerDelegate implements CircuitBreakerDelegate { + + private final CircuitBreaker circuitBreaker; + + public FailsafeCircuitBreakerDelegate(CircuitBreaker circuitBreaker) { + this.circuitBreaker = circuitBreaker; + } + + @Override + public Result execute(Supplier sup) { + return Failsafe + .with(this.circuitBreaker) + .get((ctx) -> sup.get()); + } + + @Override + public CircuitStatus findStatus() { + CircuitStatusRefresh.refresh(this.circuitBreaker); + return CircuitBreakerStateMapper.fromFailSafeCircuitBreaker(this.circuitBreaker); + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegate.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegate.java new file mode 100644 index 000000000..095796ed8 --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegate.java @@ -0,0 +1,13 @@ +package com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application; + +import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; +import com.mageddo.dnsproxyserver.solver.remote.Result; + +import java.util.function.Supplier; + +public interface CircuitBreakerDelegate { + + Result execute(Supplier sup); + + CircuitStatus findStatus(); +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerExecutorService.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerExecutorService.java new file mode 100644 index 000000000..1324b0c4d --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerExecutorService.java @@ -0,0 +1,33 @@ +package com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application; + +import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; +import com.mageddo.dnsproxyserver.solver.remote.Result; +import com.mageddo.dnsproxyserver.solver.remote.application.failsafe.CircuitBreakerFactory; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.net.InetSocketAddress; +import java.util.function.Supplier; + +@Slf4j +@Singleton +@RequiredArgsConstructor(onConstructor = @__({@Inject})) +public class CircuitBreakerExecutorService { + + private final CircuitBreakerFactory factory; + + Result safeExecute(final InetSocketAddress resolverAddress, Supplier sup) { + final var circuitBreaker = this.findCircuitBreaker(resolverAddress); + return circuitBreaker.execute(sup); + } + + CircuitStatus findCircuitStatusFor(InetSocketAddress resolverAddress) { + return this.findCircuitBreaker(resolverAddress).findStatus(); + } + + private CircuitBreakerDelegate findCircuitBreaker(InetSocketAddress resolverAddress) { + return this.factory.findCircuitBreaker(resolverAddress); + } +} From d05ff957555d8aacc5f8fd93ea39a7584eb4daba Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 15:47:50 -0300 Subject: [PATCH 06/70] refactoring is done --- .../FailsafeCircuitBreakerFactory.java | 12 ++- .../OnCacheMustBeFlushedEvent.java | 21 ++++++ .../failsafe/CircuitBreakerFactory.java | 5 +- .../CircuitBreakerDelegateFailsafe.java} | 7 +- .../FailsafeCircuitBreakerFactoryTest.java | 73 +++++++++++++++++++ .../failsafe/CircuitBreakerFactoryTest.java | 47 ------------ 6 files changed, 106 insertions(+), 59 deletions(-) create mode 100644 src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/OnCacheMustBeFlushedEvent.java rename src/main/java/com/mageddo/dnsproxyserver/solver/remote/{application/failsafe/FailsafeCircuitBreakerDelegate.java => circuitbreaker/application/CircuitBreakerDelegateFailsafe.java} (74%) create mode 100644 src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactoryTest.java diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactory.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactory.java index 5acc44aec..32b9fd988 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactory.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactory.java @@ -4,7 +4,6 @@ import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; import com.mageddo.dnsproxyserver.solver.remote.Result; -import com.mageddo.dnsproxyserver.solver.remote.dataprovider.SolverConsistencyGuaranteeDAO; import com.mageddo.dnsproxyserver.solver.remote.mapper.CircuitBreakerStateMapper; import dev.failsafe.CircuitBreaker; import dev.failsafe.event.CircuitBreakerStateChangedEvent; @@ -21,7 +20,7 @@ @RequiredArgsConstructor(onConstructor = @__({@Inject})) public class FailsafeCircuitBreakerFactory { - private final SolverConsistencyGuaranteeDAO solverConsistencyGuaranteeDAO; + private final OnCacheMustBeFlushedEvent onCacheMustBeFlushedEvent; public CircuitBreaker build( InetSocketAddress address, StaticThresholdCircuitBreakerStrategy config @@ -37,7 +36,9 @@ public CircuitBreaker build( .build(); } - EventListener build(CircuitStatus actualStateName, InetSocketAddress address) { + private EventListener build( + CircuitStatus actualStateName, InetSocketAddress address + ) { return event -> { final var previousStateName = CircuitBreakerStateMapper.toStateNameFrom(event); if (isHalfOpenToOpen(previousStateName, actualStateName)) { @@ -47,16 +48,13 @@ EventListener build(CircuitStatus actualStateNa log.trace( "status=beforeFlushCaches, address={}, previous={}, actual={}", address, previousStateName, actualStateName ); - this.flushCache(); + this.onCacheMustBeFlushedEvent.run(); log.debug( "status=clearedCache, address={}, previous={}, actual={}", address, previousStateName, actualStateName ); }; } - void flushCache() { - this.solverConsistencyGuaranteeDAO.flushCachesFromCircuitBreakerStateChange(); - } private static boolean isHalfOpenToOpen(CircuitStatus previousStateName, CircuitStatus actualStateName) { return CircuitStatus.HALF_OPEN.equals(previousStateName) && CircuitStatus.OPEN.equals(actualStateName); diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/OnCacheMustBeFlushedEvent.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/OnCacheMustBeFlushedEvent.java new file mode 100644 index 000000000..548863d1e --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/OnCacheMustBeFlushedEvent.java @@ -0,0 +1,21 @@ +package com.mageddo.dnsproxyserver.solver.remote.application; + +import com.mageddo.dnsproxyserver.solver.remote.dataprovider.SolverConsistencyGuaranteeDAO; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Slf4j +@Singleton +@RequiredArgsConstructor(onConstructor = @__({@Inject})) +public class OnCacheMustBeFlushedEvent { + + private final SolverConsistencyGuaranteeDAO solverConsistencyGuaranteeDAO; + + public void run() { + this.solverConsistencyGuaranteeDAO.flushCachesFromCircuitBreakerStateChange(); + log.debug("status=flushed"); + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java index a64f82f32..f939db2bf 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java @@ -8,6 +8,7 @@ import com.mageddo.dnsproxyserver.solver.remote.Result; import com.mageddo.dnsproxyserver.solver.remote.application.FailsafeCircuitBreakerFactory; import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegate; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateFailsafe; import com.mageddo.dnsproxyserver.solver.remote.mapper.CircuitBreakerStateMapper; import dev.failsafe.CircuitBreaker; import dev.failsafe.Failsafe; @@ -35,7 +36,7 @@ public class CircuitBreakerFactory { private final FailsafeCircuitBreakerFactory failsafeCircuitBreakerFactory; public CircuitBreakerDelegate findCircuitBreaker(InetSocketAddress resolverAddress) { - return new FailsafeCircuitBreakerDelegate(this.createOrGetCircuitBreaker(resolverAddress)); + return new CircuitBreakerDelegateFailsafe(this.createOrGetCircuitBreaker(resolverAddress)); } public Result check(InetSocketAddress remoteAddress, Supplier sup) { @@ -47,12 +48,14 @@ public Result check(InetSocketAddress remoteAddress, Supplier sup) { CircuitBreaker createOrGetCircuitBreaker(InetSocketAddress address) { final var config = this.findCircuitBreakerConfig(); + return this.circuitBreakerMap.computeIfAbsent( address, addr -> this.failsafeCircuitBreakerFactory.build(addr, config) ); } + StaticThresholdCircuitBreakerStrategy findCircuitBreakerConfig() { // fixme #533 this could not work every time, check it return (StaticThresholdCircuitBreakerStrategy) this.configService.findCurrentConfig() diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/FailsafeCircuitBreakerDelegate.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java similarity index 74% rename from src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/FailsafeCircuitBreakerDelegate.java rename to src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java index 3a4f64b5f..d2ee6a233 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/FailsafeCircuitBreakerDelegate.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java @@ -1,20 +1,19 @@ -package com.mageddo.dnsproxyserver.solver.remote.application.failsafe; +package com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application; import com.mageddo.circuitbreaker.failsafe.CircuitStatusRefresh; import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; import com.mageddo.dnsproxyserver.solver.remote.Result; -import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegate; import com.mageddo.dnsproxyserver.solver.remote.mapper.CircuitBreakerStateMapper; import dev.failsafe.CircuitBreaker; import dev.failsafe.Failsafe; import java.util.function.Supplier; -public class FailsafeCircuitBreakerDelegate implements CircuitBreakerDelegate { +public class CircuitBreakerDelegateFailsafe implements CircuitBreakerDelegate { private final CircuitBreaker circuitBreaker; - public FailsafeCircuitBreakerDelegate(CircuitBreaker circuitBreaker) { + public CircuitBreakerDelegateFailsafe(CircuitBreaker circuitBreaker) { this.circuitBreaker = circuitBreaker; } diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactoryTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactoryTest.java new file mode 100644 index 000000000..6f9c332a9 --- /dev/null +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactoryTest.java @@ -0,0 +1,73 @@ +package com.mageddo.dnsproxyserver.solver.remote.application; + +import com.mageddo.commons.circuitbreaker.CircuitCheckException; +import com.mageddo.commons.concurrent.Threads; +import com.mageddo.dnsproxyserver.solver.remote.Result; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegate; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateFailsafe; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; +import testing.templates.CircuitBreakerConfigTemplates; +import testing.templates.InetSocketAddressTemplates; +import testing.templates.solver.remote.ResultSupplierTemplates; + +import java.util.function.Supplier; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class FailsafeCircuitBreakerFactoryTest { + + @Mock + OnCacheMustBeFlushedEvent onCacheMustBeFlushedEvent; + + @Spy + @InjectMocks + FailsafeCircuitBreakerFactory factory; + + @Test + void mustNotFlushCacheWhenChangeStateToHalfOpen() { + + // arrange + final var addr = InetSocketAddressTemplates._8_8_8_8(); + final var config = CircuitBreakerConfigTemplates.oneTryFailSuccess(); + + final var supError = ResultSupplierTemplates.alwaysFail(); + final var supSuccess = ResultSupplierTemplates.alwaysSuccess(); + + final var circuitBreaker = new CircuitBreakerDelegateFailsafe(this.factory.build(addr, config)); + assertEquals("CLOSED", circuitBreaker.findStatus().toString()); + + // act + this.checkFailAndSleep(circuitBreaker, supError); + this.checkFailAndSleep(circuitBreaker, supError); + + circuitBreaker.execute(supSuccess); + + // assert + assertEquals( + "CLOSED", + circuitBreaker.findStatus().toString() + ); + + verify(this.onCacheMustBeFlushedEvent, times(2)).run(); + + } + + void checkFailAndSleep(CircuitBreakerDelegate circuitBreaker, Supplier supError) { + assertThrows(CircuitCheckException.class, () -> circuitBreaker.execute(supError)); + assertEquals( + "OPEN", + circuitBreaker.findStatus().toString() + ); + verify(this.onCacheMustBeFlushedEvent).run(); + Threads.sleep(100); + } +} diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java index 2d7eae6f4..18c1ddddc 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java @@ -1,8 +1,5 @@ package com.mageddo.dnsproxyserver.solver.remote.application.failsafe; -import com.mageddo.commons.circuitbreaker.CircuitCheckException; -import com.mageddo.commons.concurrent.Threads; -import com.mageddo.dnsproxyserver.solver.remote.Result; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -10,17 +7,10 @@ import org.mockito.junit.jupiter.MockitoExtension; import testing.templates.CircuitBreakerConfigTemplates; import testing.templates.InetSocketAddressTemplates; -import testing.templates.solver.remote.ResultSupplierTemplates; - -import java.net.InetSocketAddress; -import java.util.function.Supplier; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; @ExtendWith(MockitoExtension.class) class CircuitBreakerFactoryTest { @@ -70,41 +60,4 @@ void mustCheckAndCountErrorWhenSafeCheckReturnsFalse() { assertEquals(1, result.getValue()); } - @Test - void mustNotFlushCacheWhenChangeStateToHalfOpen(){ - - // arrange - assertEquals("[]", this.factory.stats().toString()); - - final var addr = InetSocketAddressTemplates._8_8_8_8(); - final var supError = ResultSupplierTemplates.alwaysFail(); - final var supSuccess = ResultSupplierTemplates.alwaysSuccess(); - - doReturn(CircuitBreakerConfigTemplates.oneTryFailSuccess()) - .when(this.factory) - .findCircuitBreakerConfig() - ; - - this.checkFailAndSleep(addr, supError); - this.checkFailAndSleep(addr, supError); - - this.factory.check(addr, supSuccess); - assertEquals( - "[CircuitBreakerFactory.Stats(remoteServerAddress=/8.8.8.8:53, state=CLOSED)]", - this.factory.stats().toString() - ); - verify(this.factory, times(2)).flushCache(); - - - } - - void checkFailAndSleep(InetSocketAddress addr, Supplier supError) { - assertThrows(CircuitCheckException.class, () -> this.factory.check(addr, supError)); - assertEquals( - "[CircuitBreakerFactory.Stats(remoteServerAddress=/8.8.8.8:53, state=OPEN)]", - this.factory.stats().toString() - ); - verify(this.factory).flushCache(); - Threads.sleep(100); - } } From a7dd4c0fd5d02b8ab88fea69968a84e02be296b5 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 15:55:42 -0300 Subject: [PATCH 07/70] test is passing --- .../failsafe/CircuitBreakerFactoryTest.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java index 18c1ddddc..9d95b773d 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java @@ -1,16 +1,21 @@ package com.mageddo.dnsproxyserver.solver.remote.application.failsafe; +import com.mageddo.dnsproxyserver.solver.remote.application.FailsafeCircuitBreakerFactory; +import dev.failsafe.CircuitBreaker; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; +import org.mockito.Mock; import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import testing.templates.CircuitBreakerConfigTemplates; import testing.templates.InetSocketAddressTemplates; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; @ExtendWith(MockitoExtension.class) class CircuitBreakerFactoryTest { @@ -19,6 +24,44 @@ class CircuitBreakerFactoryTest { @Spy CircuitBreakerFactory factory; + @Mock + FailsafeCircuitBreakerFactory failsafeCircuitBreakerFactory; + + @Test + void mustCreateANewCircuitBreakerInstanceWhenDifferentKeyIsUsed(){ + // arrange + doReturn(CircuitBreakerConfigTemplates.buildDefault()) + .when(this.factory) + .findCircuitBreakerConfig() + ; + + doReturn(mock(CircuitBreaker.class)) + .when(this.failsafeCircuitBreakerFactory) + .build(any(), any()); + + // act + final var a = this.factory.findCircuitBreaker(InetSocketAddressTemplates._8_8_8_8()); + final var b = this.factory.findCircuitBreaker(InetSocketAddressTemplates._1_1_1_1()); + + // assert + assertNotEquals(a, b); + assertNotEquals(a.hashCode(), b.hashCode()); + } + + @Test + void mustReuseCircuitBreakerInstanceWhenSameKeyIsUsed(){ + // arrange + final var addr = InetSocketAddressTemplates._8_8_8_8(); + + // act + final var a = this.factory.findCircuitBreaker(addr); + final var b = this.factory.findCircuitBreaker(addr); + + // assert + assertEquals(a, b); + assertEquals(a.hashCode(), b.hashCode()); + } + @Test void mustCheckAllExistentCircuitsAndCountSuccessWhenSafeCheckReturnsTrue() { // arrange From 58691540a68fbf22d183682d1d34a3e327c29435 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 16:13:26 -0300 Subject: [PATCH 08/70] test is passing --- .../failsafe/CircuitBreakerFactory.java | 31 ++++++------------- .../CircuitBreakerPingCheckerService.java | 26 +++++++--------- .../CircuitIsOpenException.java | 7 +++++ .../CircuitBreakerDelegateFailsafe.java | 12 +++++-- .../failsafe/CircuitBreakerFactoryTest.java | 13 ++++++-- .../CircuitBreakerPingCheckerServiceTest.java | 9 +++--- .../CircuitBreakerDelegateFailsafeTest.java | 29 +++++++++++++++++ 7 files changed, 82 insertions(+), 45 deletions(-) create mode 100644 src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/CircuitIsOpenException.java create mode 100644 src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafeTest.java diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java index f939db2bf..27fe05c54 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java @@ -1,6 +1,5 @@ package com.mageddo.dnsproxyserver.solver.remote.application.failsafe; -import com.mageddo.circuitbreaker.failsafe.CircuitStatusRefresh; import com.mageddo.commons.lang.tuple.Pair; import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; import com.mageddo.dnsproxyserver.config.application.ConfigService; @@ -9,9 +8,6 @@ import com.mageddo.dnsproxyserver.solver.remote.application.FailsafeCircuitBreakerFactory; import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegate; import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateFailsafe; -import com.mageddo.dnsproxyserver.solver.remote.mapper.CircuitBreakerStateMapper; -import dev.failsafe.CircuitBreaker; -import dev.failsafe.Failsafe; import lombok.RequiredArgsConstructor; import lombok.Value; import lombok.extern.slf4j.Slf4j; @@ -30,32 +26,24 @@ @RequiredArgsConstructor(onConstructor = @__({@Inject})) public class CircuitBreakerFactory { - private final Map> circuitBreakerMap = new ConcurrentHashMap<>(); + private final Map circuitBreakerMap = new ConcurrentHashMap<>(); private final ConfigService configService; private final CircuitBreakerPingCheckerService circuitBreakerCheckerService; private final FailsafeCircuitBreakerFactory failsafeCircuitBreakerFactory; - public CircuitBreakerDelegate findCircuitBreaker(InetSocketAddress resolverAddress) { - return new CircuitBreakerDelegateFailsafe(this.createOrGetCircuitBreaker(resolverAddress)); - } - public Result check(InetSocketAddress remoteAddress, Supplier sup) { - final var circuitBreaker = this.createOrGetCircuitBreaker(remoteAddress); - return Failsafe - .with(circuitBreaker) - .get((ctx) -> sup.get()); + final var circuitBreaker = this.findCircuitBreaker(remoteAddress); + return circuitBreaker.execute(sup); } - CircuitBreaker createOrGetCircuitBreaker(InetSocketAddress address) { + public CircuitBreakerDelegate findCircuitBreaker(InetSocketAddress address) { final var config = this.findCircuitBreakerConfig(); - return this.circuitBreakerMap.computeIfAbsent( address, - addr -> this.failsafeCircuitBreakerFactory.build(addr, config) + addr -> new CircuitBreakerDelegateFailsafe(this.failsafeCircuitBreakerFactory.build(addr, config)) ); } - StaticThresholdCircuitBreakerStrategy findCircuitBreakerConfig() { // fixme #533 this could not work every time, check it return (StaticThresholdCircuitBreakerStrategy) this.configService.findCurrentConfig() @@ -81,7 +69,7 @@ public Pair checkCreatedCircuits() { return Pair.of(successes, errors); } - boolean circuitBreakerSafeCheck(Map.Entry> entry) { + boolean circuitBreakerSafeCheck(Map.Entry entry) { return this.circuitBreakerCheckerService.safeCheck(entry.getKey(), entry.getValue()); } @@ -97,14 +85,13 @@ public List stats() { } public CircuitStatus findStatus(InetSocketAddress remoteAddress) { - final var circuit = this.circuitBreakerMap.get(remoteAddress); - CircuitStatusRefresh.refresh(circuit); - return CircuitBreakerStateMapper.fromFailSafeCircuitBreaker(circuit); + return this.circuitBreakerMap.get(remoteAddress) + .findStatus(); } private Stats toStats(InetSocketAddress remoteAddr) { final var circuitBreaker = this.circuitBreakerMap.get(remoteAddr); - final var state = circuitBreaker.getState().name(); + final var state = circuitBreaker.findStatus().name(); return Stats.of(remoteAddr.toString(), state); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerService.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerService.java index bc61550bb..0d99fbf06 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerService.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerService.java @@ -2,11 +2,9 @@ import com.mageddo.commons.circuitbreaker.CircuitCheckException; import com.mageddo.dnsproxyserver.solver.SolverRemote; -import com.mageddo.dnsproxyserver.solver.remote.Result; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegate; import com.mageddo.net.Networks; -import dev.failsafe.CircuitBreaker; import dev.failsafe.CircuitBreakerOpenException; -import dev.failsafe.Failsafe; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ClassUtils; @@ -20,11 +18,11 @@ @RequiredArgsConstructor(onConstructor = @__({@Inject})) public class CircuitBreakerPingCheckerService { - public boolean safeCheck(InetSocketAddress server, CircuitBreaker circuitBreaker) { + public boolean safeCheck(InetSocketAddress server, CircuitBreakerDelegate circuitBreaker) { try { this.check(server, circuitBreaker); return true; - } catch (CircuitCheckException | CircuitBreakerOpenException e) { + } catch (CircuitCheckException | CircuitBreakerOpenException e) { // fixme 533 excecao nao pode ser especifica log.debug("status=serverNotHealth, server={}, msg={}, class={}", server, e.getMessage(), ClassUtils.getSimpleName(e)); } catch (Exception e) { log.error("status=failedToCheckCircuit, server={}", server, e); @@ -32,19 +30,19 @@ public boolean safeCheck(InetSocketAddress server, CircuitBreaker circui return false; } - void check(InetSocketAddress server, CircuitBreaker circuitBreaker) { - Failsafe - .with(circuitBreaker) - .run((ctx) -> { - if (!this.ping(server)) { - throw new CircuitCheckException("circuit breaker failed for " + server); - } - log.debug("status=serverIsHealthy, server={}", server); - }); + void check(InetSocketAddress server, CircuitBreakerDelegate circuitBreaker) { + circuitBreaker.execute(() -> { + if (!this.ping(server)) { + throw new CircuitCheckException("circuit breaker failed for " + server); + } + log.debug("status=serverIsHealthy, server={}", server); + return null; + }); } /** * Note: Ping isn't being effective for DPS circuit breaker usage. + * * @see https://github.com/mageddo/dns-proxy-server/issues/526#issuecomment-2261421618 */ boolean ping(InetSocketAddress server) { diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/CircuitIsOpenException.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/CircuitIsOpenException.java new file mode 100644 index 000000000..e47279db8 --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/CircuitIsOpenException.java @@ -0,0 +1,7 @@ +package com.mageddo.dnsproxyserver.solver.remote.circuitbreaker; + +public class CircuitIsOpenException extends RuntimeException { + public CircuitIsOpenException(Throwable e) { + super(e); + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java index d2ee6a233..2fb881a16 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java @@ -3,8 +3,10 @@ import com.mageddo.circuitbreaker.failsafe.CircuitStatusRefresh; import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; import com.mageddo.dnsproxyserver.solver.remote.Result; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.CircuitIsOpenException; import com.mageddo.dnsproxyserver.solver.remote.mapper.CircuitBreakerStateMapper; import dev.failsafe.CircuitBreaker; +import dev.failsafe.CircuitBreakerOpenException; import dev.failsafe.Failsafe; import java.util.function.Supplier; @@ -19,9 +21,13 @@ public CircuitBreakerDelegateFailsafe(CircuitBreaker circuitBreaker) { @Override public Result execute(Supplier sup) { - return Failsafe - .with(this.circuitBreaker) - .get((ctx) -> sup.get()); + try { + return Failsafe + .with(this.circuitBreaker) + .get((ctx) -> sup.get()); + } catch (CircuitBreakerOpenException e){ + throw new CircuitIsOpenException(e); + } } @Override diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java index 9d95b773d..32dd2b1d8 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java @@ -53,6 +53,15 @@ void mustReuseCircuitBreakerInstanceWhenSameKeyIsUsed(){ // arrange final var addr = InetSocketAddressTemplates._8_8_8_8(); + doReturn(CircuitBreakerConfigTemplates.buildDefault()) + .when(this.factory) + .findCircuitBreakerConfig() + ; + + doReturn(mock(CircuitBreaker.class)) + .when(this.failsafeCircuitBreakerFactory) + .build(any(), any()); + // act final var a = this.factory.findCircuitBreaker(addr); final var b = this.factory.findCircuitBreaker(addr); @@ -72,7 +81,7 @@ void mustCheckAllExistentCircuitsAndCountSuccessWhenSafeCheckReturnsTrue() { doReturn(true).when(this.factory).circuitBreakerSafeCheck(any()); final var addr = InetSocketAddressTemplates._8_8_8_8(); - this.factory.createOrGetCircuitBreaker(addr); + this.factory.findCircuitBreaker(addr); // act final var result = this.factory.checkCreatedCircuits(); @@ -93,7 +102,7 @@ void mustCheckAndCountErrorWhenSafeCheckReturnsFalse() { doReturn(false).when(this.factory).circuitBreakerSafeCheck(any()); final var addr = InetSocketAddressTemplates._8_8_8_8(); - this.factory.createOrGetCircuitBreaker(addr); + this.factory.findCircuitBreaker(addr); // act final var result = this.factory.checkCreatedCircuits(); diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerServiceTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerServiceTest.java index 2152148f0..af3b78031 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerServiceTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerServiceTest.java @@ -1,6 +1,7 @@ package com.mageddo.dnsproxyserver.solver.remote.application.failsafe; import com.mageddo.dnsproxyserver.solver.remote.Result; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateFailsafe; import com.mageddo.net.SocketUtils; import dev.failsafe.CircuitBreaker; import org.junit.jupiter.api.Test; @@ -34,7 +35,7 @@ void mustReturnTrueWhenPingGetSuccess() { doReturn(true).when(this.service).ping(any()); // act - final var ok = this.service.safeCheck(addr, circuitBreaker); + final var ok = this.service.safeCheck(addr, new CircuitBreakerDelegateFailsafe(circuitBreaker)); // assert assertTrue(ok); @@ -44,7 +45,7 @@ void mustReturnTrueWhenPingGetSuccess() { void mustReturnFalseWhenPingReturnsFalse() { // arrange final var addr = InetSocketAddressTemplates._8_8_8_8(); - final var circuitBreaker = FailSafeCircuitBreakerTemplates.buildDefault(); + final var circuitBreaker = new CircuitBreakerDelegateFailsafe(FailSafeCircuitBreakerTemplates.buildDefault()) ; doReturn(false).when(this.service).ping(any()); // act @@ -58,7 +59,7 @@ void mustReturnFalseWhenPingReturnsFalse() { void mustReturnFalseWhenThereIsAFatalException() { // arrange final var addr = InetSocketAddressTemplates._8_8_8_8(); - final var circuitBreaker = FailSafeCircuitBreakerTemplates.buildDefault(); + final var circuitBreaker = new CircuitBreakerDelegateFailsafe(FailSafeCircuitBreakerTemplates.buildDefault()); doThrow(new RuntimeException("unknown error")).when(this.service).ping(any()); // act @@ -74,7 +75,7 @@ void mustPingSpecifiedPort() throws Exception { // arrange final var server = SocketUtils.createServerOnRandomPort(); final var address = (InetSocketAddress) server.getLocalSocketAddress(); - final var circuitBreaker = CircuitBreaker.builder().build(); + final var circuitBreaker = new CircuitBreakerDelegateFailsafe(CircuitBreaker.builder().build()); try (server) { // act diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafeTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafeTest.java new file mode 100644 index 000000000..6fd390b27 --- /dev/null +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafeTest.java @@ -0,0 +1,29 @@ +package com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application; + +import com.mageddo.commons.circuitbreaker.CircuitCheckException; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.CircuitIsOpenException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.function.Executable; +import testing.templates.solver.remote.FailSafeCircuitBreakerTemplates; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class CircuitBreakerDelegateFailsafeTest { + + @Test + void mustThrowAbstractOpenCircuitException() { + // arrange + final var circuitBreaker = new CircuitBreakerDelegateFailsafe(FailSafeCircuitBreakerTemplates.fastCircuit()); + + // act + final Executable stm = () -> { + circuitBreaker.execute(() -> { + throw new CircuitCheckException("blaaa"); + }); + }; + assertThrows(CircuitCheckException.class, stm); + assertThrows(CircuitIsOpenException.class, stm); + + // assert + } +} From 34544f21e25737ac9b43e2d4d6c7b557455e50e1 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 16:16:29 -0300 Subject: [PATCH 09/70] test is passing --- .../application/failsafe/CircuitBreakerFailSafeService.java | 4 ++-- .../failsafe/CircuitBreakerFailSafeServiceCompTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeService.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeService.java index 21f7577f5..c2f42860a 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeService.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeService.java @@ -4,7 +4,7 @@ import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; import com.mageddo.dnsproxyserver.solver.remote.Result; import com.mageddo.dnsproxyserver.solver.remote.application.CircuitBreakerService; -import dev.failsafe.CircuitBreakerOpenException; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.CircuitIsOpenException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ClassUtils; @@ -27,7 +27,7 @@ public class CircuitBreakerFailSafeService implements CircuitBreakerService { public Result safeHandle(InetSocketAddress resolverAddress, Supplier sup) { try { return this.handle(resolverAddress, sup); - } catch (CircuitCheckException | CircuitBreakerOpenException e) { + } catch (CircuitCheckException | CircuitIsOpenException e) { final var clazz = ClassUtils.getSimpleName(e); log.debug("status=circuitEvent, server={}, type={}", resolverAddress, clazz); this.status = String.format("%s for %s", clazz, resolverAddress); diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeServiceCompTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeServiceCompTest.java index 2ad265cd6..1565b1e82 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeServiceCompTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeServiceCompTest.java @@ -47,7 +47,7 @@ void mustOpenCircuitAfterThresholdFailures() { // assert final var result = this.service.safeHandle(req.getResolverAddress(), failureSup); assertTrue(result.isEmpty()); - assertEquals("CircuitBreakerOpenException for /8.8.8.8:53", this.service.getStatus()); + assertEquals("CircuitIsOpenException for /8.8.8.8:53", this.service.getStatus()); } From fda3d972d1a851844d7c7a617253cd324a9b9335 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 16:24:28 -0300 Subject: [PATCH 10/70] refactoring package --- .../circuitbreaker/CircuitIsOpenException.java | 2 +- .../application/failsafe/CircuitBreakerFailSafeService.java | 2 +- .../application/CircuitBreakerDelegateFailsafe.java | 2 +- .../application/CircuitBreakerDelegateFailsafeTest.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/main/java/com/mageddo/{dnsproxyserver/solver/remote => commons}/circuitbreaker/CircuitIsOpenException.java (66%) diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/CircuitIsOpenException.java b/src/main/java/com/mageddo/commons/circuitbreaker/CircuitIsOpenException.java similarity index 66% rename from src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/CircuitIsOpenException.java rename to src/main/java/com/mageddo/commons/circuitbreaker/CircuitIsOpenException.java index e47279db8..50b8cdd89 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/CircuitIsOpenException.java +++ b/src/main/java/com/mageddo/commons/circuitbreaker/CircuitIsOpenException.java @@ -1,4 +1,4 @@ -package com.mageddo.dnsproxyserver.solver.remote.circuitbreaker; +package com.mageddo.commons.circuitbreaker; public class CircuitIsOpenException extends RuntimeException { public CircuitIsOpenException(Throwable e) { diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeService.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeService.java index c2f42860a..64bcc0f4c 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeService.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeService.java @@ -4,7 +4,7 @@ import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; import com.mageddo.dnsproxyserver.solver.remote.Result; import com.mageddo.dnsproxyserver.solver.remote.application.CircuitBreakerService; -import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.CircuitIsOpenException; +import com.mageddo.commons.circuitbreaker.CircuitIsOpenException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ClassUtils; diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java index 2fb881a16..bfb7f30b4 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java @@ -3,7 +3,7 @@ import com.mageddo.circuitbreaker.failsafe.CircuitStatusRefresh; import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; import com.mageddo.dnsproxyserver.solver.remote.Result; -import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.CircuitIsOpenException; +import com.mageddo.commons.circuitbreaker.CircuitIsOpenException; import com.mageddo.dnsproxyserver.solver.remote.mapper.CircuitBreakerStateMapper; import dev.failsafe.CircuitBreaker; import dev.failsafe.CircuitBreakerOpenException; diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafeTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafeTest.java index 6fd390b27..425400fdb 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafeTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafeTest.java @@ -1,7 +1,7 @@ package com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application; import com.mageddo.commons.circuitbreaker.CircuitCheckException; -import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.CircuitIsOpenException; +import com.mageddo.commons.circuitbreaker.CircuitIsOpenException; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; import testing.templates.solver.remote.FailSafeCircuitBreakerTemplates; From 99588e018574977b477ac8285832b42656086e1e Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 16:36:23 -0300 Subject: [PATCH 11/70] [Gradle Release Plugin] - new version commit: '3.25.11-snapshot'. --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 483a14ec1..f981c9a15 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=3.25.10-snapshot +version=3.25.11-snapshot From 50bb180f794494492652a365b1429885c898d13b Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 16:37:51 -0300 Subject: [PATCH 12/70] release notes --- RELEASE-NOTES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index af66a1a42..e016f1105 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,3 +1,6 @@ +## 3.25.11 +* Agnostic interface to support multiple circuit breaker strategies config #533 + ## 3.25.10 * Create `IntTests` suite, they are comp tests which can be run within native image, see the docs #480 * Upgrading necessary deps From 10e6a776daffdbb1e0bc112827c5def730401b43 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 16:39:05 -0300 Subject: [PATCH 13/70] [Gradle Release Plugin] - new version commit: '3.25.12-snapshot'. --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index f981c9a15..a44f8fac5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=3.25.11-snapshot +version=3.25.12-snapshot From 3b17f26b0595fe5f97c2879f596c47be5fcc784b Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Fri, 30 Aug 2024 16:39:49 -0300 Subject: [PATCH 14/70] release notes --- RELEASE-NOTES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index e016f1105..48fc7af6e 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,3 +1,6 @@ +## 3.25.12 +* Creating an abstraction of circuit breaker implementation #533 + ## 3.25.11 * Agnostic interface to support multiple circuit breaker strategies config #533 From 928fcd36510aefe455bf0232bc0e2faf7b5e2433 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 09:01:34 -0300 Subject: [PATCH 15/70] fixme note --- .../solver/remote/application/CircuitBreakerService.java | 2 ++ .../application/failsafe/CircuitBreakerPingCheckerService.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerService.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerService.java index 1b5943907..a085a1035 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerService.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerService.java @@ -8,6 +8,8 @@ public interface CircuitBreakerService { + // fixme #533 esse padrão de strategy não é mais necessário aqui, foi movido para CircuitBreakerDelegate + // onde tem mais chances de reduzir duplicação Result safeHandle(final InetSocketAddress resolverAddress, Supplier sup); CircuitStatus findCircuitStatus(InetSocketAddress resolverAddress); diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerService.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerService.java index 0d99fbf06..b2c2ec9ab 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerService.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerService.java @@ -22,7 +22,7 @@ public boolean safeCheck(InetSocketAddress server, CircuitBreakerDelegate circui try { this.check(server, circuitBreaker); return true; - } catch (CircuitCheckException | CircuitBreakerOpenException e) { // fixme 533 excecao nao pode ser especifica + } catch (CircuitCheckException | CircuitBreakerOpenException e) { // fixme #533 excecao nao pode ser especifica log.debug("status=serverNotHealth, server={}, msg={}, class={}", server, e.getMessage(), ClassUtils.getSimpleName(e)); } catch (Exception e) { log.error("status=failedToCheckCircuit, server={}", server, e); From b817612c321e3e35902f25006cf7517d4dc28f18 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 09:02:16 -0300 Subject: [PATCH 16/70] fixme note --- .../remote/application/CircuitBreakerNonResilientService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerNonResilientService.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerNonResilientService.java index aa79c82bd..0ad2decf4 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerNonResilientService.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerNonResilientService.java @@ -6,6 +6,7 @@ import java.net.InetSocketAddress; import java.util.function.Supplier; +// todo #533 criar um CircuitBreakerDelegate para esta classe public class CircuitBreakerNonResilientService implements CircuitBreakerService { @Override public Result safeHandle(final InetSocketAddress resolverAddress, Supplier sup) { From a087aff5553b0a4e916d73f9ae843224e9f258ef Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 09:23:14 -0300 Subject: [PATCH 17/70] refactoring to support multiple delegates --- .../config/CircuitBreakerStrategy.java | 2 +- ...StaticThresholdCircuitBreakerStrategy.java | 2 +- .../config/application/ConfigService.java | 13 +++++++++ .../failsafe/CircuitBreakerFactory.java | 28 +++++++++++++------ 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java b/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java index 1cc48dc1b..a606cef24 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java @@ -2,7 +2,7 @@ public interface CircuitBreakerStrategy { - Name type(); + Name name(); enum Name { STATIC_THRESHOLD, diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java b/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java index f86ded7fb..9f08c8b18 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java @@ -31,7 +31,7 @@ public static StaticThresholdCircuitBreakerStrategy empty() { } @Override - public Name type() { + public Name name() { return Name.STATIC_THRESHOLD; } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/application/ConfigService.java b/src/main/java/com/mageddo/dnsproxyserver/config/application/ConfigService.java index 422b05a7b..42fb73808 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/application/ConfigService.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/application/ConfigService.java @@ -1,6 +1,8 @@ package com.mageddo.dnsproxyserver.config.application; +import com.mageddo.dnsproxyserver.config.CircuitBreakerStrategy; import com.mageddo.dnsproxyserver.config.Config; +import com.mageddo.dnsproxyserver.config.SolverRemote; import com.mageddo.dnsproxyserver.config.dataprovider.ConfigDAO; import com.mageddo.dnsproxyserver.config.mapper.ConfigMapper; import org.apache.commons.lang3.ClassUtils; @@ -29,6 +31,12 @@ public Config findCurrentConfig() { return ConfigMapper.mapFrom(this.findConfigs()); } + public SolverRemote findCurrentConfigRemote(){ + return this.findCurrentConfig() + .getSolverRemote() + ; + } + List findConfigs() { return this.findConfigDaos() .map(ConfigDAO::find) @@ -46,4 +54,9 @@ public List findConfigNames(){ .map(ClassUtils::getSimpleName) .toList(); } + + public CircuitBreakerStrategy findCurrentConfigCircuitBreaker() { + return this.findCurrentConfigRemote() + .getCircuitBreaker(); + } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java index 27fe05c54..5be2e83e8 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java @@ -1,6 +1,7 @@ package com.mageddo.dnsproxyserver.solver.remote.application.failsafe; import com.mageddo.commons.lang.tuple.Pair; +import com.mageddo.dnsproxyserver.config.CircuitBreakerStrategy; import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; import com.mageddo.dnsproxyserver.config.application.ConfigService; import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; @@ -37,18 +38,29 @@ public Result check(InetSocketAddress remoteAddress, Supplier sup) { } public CircuitBreakerDelegate findCircuitBreaker(InetSocketAddress address) { + final var strategy = this.findStrategy(address); + return this.circuitBreakerMap.computeIfAbsent(address, addr -> strategy); + } + + CircuitBreakerDelegate findStrategy(InetSocketAddress address) { final var config = this.findCircuitBreakerConfig(); - return this.circuitBreakerMap.computeIfAbsent( + return switch (config.name()) { + case STATIC_THRESHOLD -> this.buildFailSafeStrategy(address, config); + default -> throw new UnsupportedOperationException(); + }; + } + + private CircuitBreakerDelegateFailsafe buildFailSafeStrategy( + InetSocketAddress address, CircuitBreakerStrategy config + ) { + return new CircuitBreakerDelegateFailsafe(this.failsafeCircuitBreakerFactory.build( address, - addr -> new CircuitBreakerDelegateFailsafe(this.failsafeCircuitBreakerFactory.build(addr, config)) - ); + (StaticThresholdCircuitBreakerStrategy) config + )); } - StaticThresholdCircuitBreakerStrategy findCircuitBreakerConfig() { - // fixme #533 this could not work every time, check it - return (StaticThresholdCircuitBreakerStrategy) this.configService.findCurrentConfig() - .getSolverRemote() - .getCircuitBreaker(); + CircuitBreakerStrategy findCircuitBreakerConfig() { + return this.configService.findCurrentConfigCircuitBreaker(); } public Pair checkCreatedCircuits() { From 808c554beb341510f903d9189972139d950fe9b8 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 09:25:42 -0300 Subject: [PATCH 18/70] refactoring name --- .../config/CircuitBreakerStrategy.java | 12 ++++++++++++ .../application/failsafe/CircuitBreakerFactory.java | 6 +++--- ...rcuitBreakerDelegateStaticThresholdFailsafe.java} | 4 ++-- .../FailsafeCircuitBreakerFactoryTest.java | 4 ++-- .../CircuitBreakerPingCheckerServiceTest.java | 10 +++++----- ...tBreakerDelegateStaticThresholdFailsafeTest.java} | 4 ++-- 6 files changed, 26 insertions(+), 14 deletions(-) rename src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/{CircuitBreakerDelegateFailsafe.java => CircuitBreakerDelegateStaticThresholdFailsafe.java} (85%) rename src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/{CircuitBreakerDelegateFailsafeTest.java => CircuitBreakerDelegateStaticThresholdFailsafeTest.java} (80%) diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java b/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java index a606cef24..bc249f46f 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java @@ -1,11 +1,23 @@ package com.mageddo.dnsproxyserver.config; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateNonResilient; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateStaticThresholdFailsafe; + public interface CircuitBreakerStrategy { Name name(); enum Name { + /** + * @see CircuitBreakerDelegateStaticThresholdFailsafe + */ STATIC_THRESHOLD, + CANARY_RATE_THRESHOLD, + + /** + * @see CircuitBreakerDelegateNonResilient + */ + NON_RESILIENT, } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java index 5be2e83e8..196f83272 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java @@ -8,7 +8,7 @@ import com.mageddo.dnsproxyserver.solver.remote.Result; import com.mageddo.dnsproxyserver.solver.remote.application.FailsafeCircuitBreakerFactory; import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegate; -import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateFailsafe; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateStaticThresholdFailsafe; import lombok.RequiredArgsConstructor; import lombok.Value; import lombok.extern.slf4j.Slf4j; @@ -50,10 +50,10 @@ CircuitBreakerDelegate findStrategy(InetSocketAddress address) { }; } - private CircuitBreakerDelegateFailsafe buildFailSafeStrategy( + private CircuitBreakerDelegateStaticThresholdFailsafe buildFailSafeStrategy( InetSocketAddress address, CircuitBreakerStrategy config ) { - return new CircuitBreakerDelegateFailsafe(this.failsafeCircuitBreakerFactory.build( + return new CircuitBreakerDelegateStaticThresholdFailsafe(this.failsafeCircuitBreakerFactory.build( address, (StaticThresholdCircuitBreakerStrategy) config )); diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafe.java similarity index 85% rename from src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java rename to src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafe.java index bfb7f30b4..abfb15d0f 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafe.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafe.java @@ -11,11 +11,11 @@ import java.util.function.Supplier; -public class CircuitBreakerDelegateFailsafe implements CircuitBreakerDelegate { +public class CircuitBreakerDelegateStaticThresholdFailsafe implements CircuitBreakerDelegate { private final CircuitBreaker circuitBreaker; - public CircuitBreakerDelegateFailsafe(CircuitBreaker circuitBreaker) { + public CircuitBreakerDelegateStaticThresholdFailsafe(CircuitBreaker circuitBreaker) { this.circuitBreaker = circuitBreaker; } diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactoryTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactoryTest.java index 6f9c332a9..62ce0e31a 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactoryTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactoryTest.java @@ -4,7 +4,7 @@ import com.mageddo.commons.concurrent.Threads; import com.mageddo.dnsproxyserver.solver.remote.Result; import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegate; -import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateFailsafe; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateStaticThresholdFailsafe; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -42,7 +42,7 @@ void mustNotFlushCacheWhenChangeStateToHalfOpen() { final var supError = ResultSupplierTemplates.alwaysFail(); final var supSuccess = ResultSupplierTemplates.alwaysSuccess(); - final var circuitBreaker = new CircuitBreakerDelegateFailsafe(this.factory.build(addr, config)); + final var circuitBreaker = new CircuitBreakerDelegateStaticThresholdFailsafe(this.factory.build(addr, config)); assertEquals("CLOSED", circuitBreaker.findStatus().toString()); // act diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerServiceTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerServiceTest.java index af3b78031..169da8b60 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerServiceTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerPingCheckerServiceTest.java @@ -1,7 +1,7 @@ package com.mageddo.dnsproxyserver.solver.remote.application.failsafe; import com.mageddo.dnsproxyserver.solver.remote.Result; -import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateFailsafe; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateStaticThresholdFailsafe; import com.mageddo.net.SocketUtils; import dev.failsafe.CircuitBreaker; import org.junit.jupiter.api.Test; @@ -35,7 +35,7 @@ void mustReturnTrueWhenPingGetSuccess() { doReturn(true).when(this.service).ping(any()); // act - final var ok = this.service.safeCheck(addr, new CircuitBreakerDelegateFailsafe(circuitBreaker)); + final var ok = this.service.safeCheck(addr, new CircuitBreakerDelegateStaticThresholdFailsafe(circuitBreaker)); // assert assertTrue(ok); @@ -45,7 +45,7 @@ void mustReturnTrueWhenPingGetSuccess() { void mustReturnFalseWhenPingReturnsFalse() { // arrange final var addr = InetSocketAddressTemplates._8_8_8_8(); - final var circuitBreaker = new CircuitBreakerDelegateFailsafe(FailSafeCircuitBreakerTemplates.buildDefault()) ; + final var circuitBreaker = new CircuitBreakerDelegateStaticThresholdFailsafe(FailSafeCircuitBreakerTemplates.buildDefault()) ; doReturn(false).when(this.service).ping(any()); // act @@ -59,7 +59,7 @@ void mustReturnFalseWhenPingReturnsFalse() { void mustReturnFalseWhenThereIsAFatalException() { // arrange final var addr = InetSocketAddressTemplates._8_8_8_8(); - final var circuitBreaker = new CircuitBreakerDelegateFailsafe(FailSafeCircuitBreakerTemplates.buildDefault()); + final var circuitBreaker = new CircuitBreakerDelegateStaticThresholdFailsafe(FailSafeCircuitBreakerTemplates.buildDefault()); doThrow(new RuntimeException("unknown error")).when(this.service).ping(any()); // act @@ -75,7 +75,7 @@ void mustPingSpecifiedPort() throws Exception { // arrange final var server = SocketUtils.createServerOnRandomPort(); final var address = (InetSocketAddress) server.getLocalSocketAddress(); - final var circuitBreaker = new CircuitBreakerDelegateFailsafe(CircuitBreaker.builder().build()); + final var circuitBreaker = new CircuitBreakerDelegateStaticThresholdFailsafe(CircuitBreaker.builder().build()); try (server) { // act diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafeTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java similarity index 80% rename from src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafeTest.java rename to src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java index 425400fdb..6b4fdbe62 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateFailsafeTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java @@ -8,12 +8,12 @@ import static org.junit.jupiter.api.Assertions.assertThrows; -class CircuitBreakerDelegateFailsafeTest { +class CircuitBreakerDelegateStaticThresholdFailsafeTest { @Test void mustThrowAbstractOpenCircuitException() { // arrange - final var circuitBreaker = new CircuitBreakerDelegateFailsafe(FailSafeCircuitBreakerTemplates.fastCircuit()); + final var circuitBreaker = new CircuitBreakerDelegateStaticThresholdFailsafe(FailSafeCircuitBreakerTemplates.fastCircuit()); // act final Executable stm = () -> { From cfb30680ab9d9ebe8abac515fd3b814174ff919a Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 09:27:53 -0300 Subject: [PATCH 19/70] refactoring --- .../application/failsafe/CircuitBreakerFactory.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java index 196f83272..c7d18e0c9 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java @@ -38,19 +38,19 @@ public Result check(InetSocketAddress remoteAddress, Supplier sup) { } public CircuitBreakerDelegate findCircuitBreaker(InetSocketAddress address) { - final var strategy = this.findStrategy(address); + final var strategy = this.findCircuitBreakerHotLoad(address); return this.circuitBreakerMap.computeIfAbsent(address, addr -> strategy); } - CircuitBreakerDelegate findStrategy(InetSocketAddress address) { + CircuitBreakerDelegate findCircuitBreakerHotLoad(InetSocketAddress address) { final var config = this.findCircuitBreakerConfig(); return switch (config.name()) { - case STATIC_THRESHOLD -> this.buildFailSafeStrategy(address, config); + case STATIC_THRESHOLD -> this.buildStaticThresholdFailSafeCircuitBreaker(address, config); default -> throw new UnsupportedOperationException(); }; } - private CircuitBreakerDelegateStaticThresholdFailsafe buildFailSafeStrategy( + private CircuitBreakerDelegateStaticThresholdFailsafe buildStaticThresholdFailSafeCircuitBreaker( InetSocketAddress address, CircuitBreakerStrategy config ) { return new CircuitBreakerDelegateStaticThresholdFailsafe(this.failsafeCircuitBreakerFactory.build( From 86d9531f9b9846aa38bcee9b3e5b3a7e8e0f1655 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 09:32:41 -0300 Subject: [PATCH 20/70] implementing non resilient strategy --- ...java => CircuitBreakerStrategyConfig.java} | 2 +- .../mageddo/dnsproxyserver/config/Config.java | 2 +- ...ResilientCircuitBreakerStrategyConfig.java | 8 ++++++++ .../dnsproxyserver/config/SolverRemote.java | 2 +- ...hresholdCircuitBreakerStrategyConfig.java} | 6 +++--- .../config/application/ConfigService.java | 4 ++-- .../mapper/ConfigJsonV2Mapper.java | 4 ++-- .../config/mapper/ConfigMapper.java | 6 +++--- .../validator/CircuitBreakerValidator.java | 4 ++-- .../config/validator/ConfigValidator.java | 4 ++-- .../FailsafeCircuitBreakerFactory.java | 4 ++-- .../failsafe/CircuitBreakerFactory.java | 12 +++++++----- .../CircuitBreakerDelegateNonResilient.java | 19 +++++++++++++++++++ .../failsafe/CircuitBreakerFactoryTest.java | 18 ++++++++++++++++++ .../CircuitBreakerConfigTemplates.java | 15 +++++++++++---- 15 files changed, 82 insertions(+), 28 deletions(-) rename src/main/java/com/mageddo/dnsproxyserver/config/{CircuitBreakerStrategy.java => CircuitBreakerStrategyConfig.java} (91%) create mode 100644 src/main/java/com/mageddo/dnsproxyserver/config/NonResilientCircuitBreakerStrategyConfig.java rename src/main/java/com/mageddo/dnsproxyserver/config/{StaticThresholdCircuitBreakerStrategy.java => StaticThresholdCircuitBreakerStrategyConfig.java} (71%) create mode 100644 src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateNonResilient.java diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java b/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategyConfig.java similarity index 91% rename from src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java rename to src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategyConfig.java index bc249f46f..4dd4e42b1 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategy.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/CircuitBreakerStrategyConfig.java @@ -3,7 +3,7 @@ import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateNonResilient; import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateStaticThresholdFailsafe; -public interface CircuitBreakerStrategy { +public interface CircuitBreakerStrategyConfig { Name name(); diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java index e1ada8fe9..9b4183ee0 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java @@ -90,7 +90,7 @@ public void resetConfigFile() { } @JsonIgnore - public CircuitBreakerStrategy getSolverRemoteCircuitBreakerStrategy() { + public CircuitBreakerStrategyConfig getSolverRemoteCircuitBreakerStrategy() { if (this.solverRemote == null) { return null; } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/NonResilientCircuitBreakerStrategyConfig.java b/src/main/java/com/mageddo/dnsproxyserver/config/NonResilientCircuitBreakerStrategyConfig.java new file mode 100644 index 000000000..4b4f19b04 --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/config/NonResilientCircuitBreakerStrategyConfig.java @@ -0,0 +1,8 @@ +package com.mageddo.dnsproxyserver.config; + +public class NonResilientCircuitBreakerStrategyConfig implements CircuitBreakerStrategyConfig { + @Override + public Name name() { + return Name.NON_RESILIENT; + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/SolverRemote.java b/src/main/java/com/mageddo/dnsproxyserver/config/SolverRemote.java index f4613ab28..210da1c17 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/SolverRemote.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/SolverRemote.java @@ -9,5 +9,5 @@ public class SolverRemote { private Boolean active; - private CircuitBreakerStrategy circuitBreaker; + private CircuitBreakerStrategyConfig circuitBreaker; } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java b/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategyConfig.java similarity index 71% rename from src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java rename to src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategyConfig.java index 9f08c8b18..ccc9176ba 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategy.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/StaticThresholdCircuitBreakerStrategyConfig.java @@ -8,7 +8,7 @@ @Value @Builder -public class StaticThresholdCircuitBreakerStrategy implements CircuitBreakerStrategy { +public class StaticThresholdCircuitBreakerStrategyConfig implements CircuitBreakerStrategyConfig { /** * See {@link dev.failsafe.CircuitBreakerBuilder#withFailureThreshold(int, int)} @@ -26,8 +26,8 @@ public class StaticThresholdCircuitBreakerStrategy implements CircuitBreakerStra */ private Duration testDelay; - public static StaticThresholdCircuitBreakerStrategy empty() { - return StaticThresholdCircuitBreakerStrategy.builder().build(); + public static StaticThresholdCircuitBreakerStrategyConfig empty() { + return StaticThresholdCircuitBreakerStrategyConfig.builder().build(); } @Override diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/application/ConfigService.java b/src/main/java/com/mageddo/dnsproxyserver/config/application/ConfigService.java index 42fb73808..a1341eb15 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/application/ConfigService.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/application/ConfigService.java @@ -1,6 +1,6 @@ package com.mageddo.dnsproxyserver.config.application; -import com.mageddo.dnsproxyserver.config.CircuitBreakerStrategy; +import com.mageddo.dnsproxyserver.config.CircuitBreakerStrategyConfig; import com.mageddo.dnsproxyserver.config.Config; import com.mageddo.dnsproxyserver.config.SolverRemote; import com.mageddo.dnsproxyserver.config.dataprovider.ConfigDAO; @@ -55,7 +55,7 @@ public List findConfigNames(){ .toList(); } - public CircuitBreakerStrategy findCurrentConfigCircuitBreaker() { + public CircuitBreakerStrategyConfig findCurrentConfigCircuitBreaker() { return this.findCurrentConfigRemote() .getCircuitBreaker(); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java index 04e7deeaf..e3289973c 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java @@ -1,6 +1,6 @@ package com.mageddo.dnsproxyserver.config.dataprovider.mapper; -import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategyConfig; import com.mageddo.dnsproxyserver.config.Config; import com.mageddo.dnsproxyserver.config.SolverRemote; import com.mageddo.dnsproxyserver.config.dataprovider.vo.ConfigJson; @@ -65,7 +65,7 @@ static SolverRemote buildCompleteSolverRemote(ConfigJson json, ConfigJsonV2.Circ .active(Booleans.reverseWhenNotNull(json.getNoRemoteServers())) // fixme #533 need to create a dynamic json parser for different strategies, // then a dynamic mapper to the solver remote - .circuitBreaker(StaticThresholdCircuitBreakerStrategy + .circuitBreaker(StaticThresholdCircuitBreakerStrategyConfig .builder() .failureThreshold(circuitBreaker.getFailureThreshold()) .failureThresholdCapacity(circuitBreaker.getFailureThresholdCapacity()) diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java b/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java index e5263df84..681b260a4 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java @@ -1,6 +1,6 @@ package com.mageddo.dnsproxyserver.config.mapper; -import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategyConfig; import com.mageddo.dnsproxyserver.config.Config; import com.mageddo.dnsproxyserver.config.SolverRemote; import com.mageddo.dnsproxyserver.config.dataprovider.ConfigPropDAO; @@ -74,8 +74,8 @@ private static Config buildDefault() { .build(); } - public static StaticThresholdCircuitBreakerStrategy defaultCircuitBreaker() { - return StaticThresholdCircuitBreakerStrategy + public static StaticThresholdCircuitBreakerStrategyConfig defaultCircuitBreaker() { + return StaticThresholdCircuitBreakerStrategyConfig .builder() .failureThreshold(3) .failureThresholdCapacity(10) diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/validator/CircuitBreakerValidator.java b/src/main/java/com/mageddo/dnsproxyserver/config/validator/CircuitBreakerValidator.java index e8f917349..9f39b1dbf 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/validator/CircuitBreakerValidator.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/validator/CircuitBreakerValidator.java @@ -1,12 +1,12 @@ package com.mageddo.dnsproxyserver.config.validator; -import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategyConfig; import org.apache.commons.lang3.Validate; import static com.mageddo.dnsproxyserver.utils.Numbers.positiveOrNull; public class CircuitBreakerValidator { - public static void validate(StaticThresholdCircuitBreakerStrategy circuit) { + public static void validate(StaticThresholdCircuitBreakerStrategyConfig circuit) { Validate.notNull(positiveOrNull(circuit.getFailureThreshold()), genMsg("failure theshold must be a positive number")); Validate.notNull(positiveOrNull(circuit.getSuccessThreshold()), genMsg("success theshold must be positive number")); Validate.notNull(positiveOrNull(circuit.getFailureThresholdCapacity()), genMsg("success theshold capacity must be positive number")); diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/validator/ConfigValidator.java b/src/main/java/com/mageddo/dnsproxyserver/config/validator/ConfigValidator.java index 7dfcf33b6..deb7833af 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/validator/ConfigValidator.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/validator/ConfigValidator.java @@ -1,7 +1,7 @@ package com.mageddo.dnsproxyserver.config.validator; import com.mageddo.dnsproxyserver.config.Config; -import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategyConfig; import org.apache.commons.lang3.Validate; public class ConfigValidator { @@ -25,6 +25,6 @@ public static void validate(Config config) { Validate.notNull(config.isSolverRemoteActive(), "Solver remote active"); // fixme #533 this could not work every time after new types be created, check it - CircuitBreakerValidator.validate((StaticThresholdCircuitBreakerStrategy) config.getSolverRemoteCircuitBreakerStrategy()); + CircuitBreakerValidator.validate((StaticThresholdCircuitBreakerStrategyConfig) config.getSolverRemoteCircuitBreakerStrategy()); } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactory.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactory.java index 32b9fd988..8268df658 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactory.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/FailsafeCircuitBreakerFactory.java @@ -1,7 +1,7 @@ package com.mageddo.dnsproxyserver.solver.remote.application; import com.mageddo.commons.circuitbreaker.CircuitCheckException; -import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategyConfig; import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; import com.mageddo.dnsproxyserver.solver.remote.Result; import com.mageddo.dnsproxyserver.solver.remote.mapper.CircuitBreakerStateMapper; @@ -23,7 +23,7 @@ public class FailsafeCircuitBreakerFactory { private final OnCacheMustBeFlushedEvent onCacheMustBeFlushedEvent; public CircuitBreaker build( - InetSocketAddress address, StaticThresholdCircuitBreakerStrategy config + InetSocketAddress address, StaticThresholdCircuitBreakerStrategyConfig config ) { return CircuitBreaker.builder() .handle(CircuitCheckException.class) diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java index c7d18e0c9..23916d028 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java @@ -1,13 +1,14 @@ package com.mageddo.dnsproxyserver.solver.remote.application.failsafe; import com.mageddo.commons.lang.tuple.Pair; -import com.mageddo.dnsproxyserver.config.CircuitBreakerStrategy; -import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; +import com.mageddo.dnsproxyserver.config.CircuitBreakerStrategyConfig; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategyConfig; import com.mageddo.dnsproxyserver.config.application.ConfigService; import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; import com.mageddo.dnsproxyserver.solver.remote.Result; import com.mageddo.dnsproxyserver.solver.remote.application.FailsafeCircuitBreakerFactory; import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegate; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateNonResilient; import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateStaticThresholdFailsafe; import lombok.RequiredArgsConstructor; import lombok.Value; @@ -46,20 +47,21 @@ CircuitBreakerDelegate findCircuitBreakerHotLoad(InetSocketAddress address) { final var config = this.findCircuitBreakerConfig(); return switch (config.name()) { case STATIC_THRESHOLD -> this.buildStaticThresholdFailSafeCircuitBreaker(address, config); + case NON_RESILIENT -> new CircuitBreakerDelegateNonResilient(); default -> throw new UnsupportedOperationException(); }; } private CircuitBreakerDelegateStaticThresholdFailsafe buildStaticThresholdFailSafeCircuitBreaker( - InetSocketAddress address, CircuitBreakerStrategy config + InetSocketAddress address, CircuitBreakerStrategyConfig config ) { return new CircuitBreakerDelegateStaticThresholdFailsafe(this.failsafeCircuitBreakerFactory.build( address, - (StaticThresholdCircuitBreakerStrategy) config + (StaticThresholdCircuitBreakerStrategyConfig) config )); } - CircuitBreakerStrategy findCircuitBreakerConfig() { + CircuitBreakerStrategyConfig findCircuitBreakerConfig() { return this.configService.findCurrentConfigCircuitBreaker(); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateNonResilient.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateNonResilient.java new file mode 100644 index 000000000..96f7f10eb --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateNonResilient.java @@ -0,0 +1,19 @@ +package com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application; + +import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; +import com.mageddo.dnsproxyserver.solver.remote.Result; + +import java.util.function.Supplier; + +public class CircuitBreakerDelegateNonResilient implements CircuitBreakerDelegate { + + @Override + public Result execute(Supplier sup) { + return sup.get(); + } + + @Override + public CircuitStatus findStatus() { + return null; + } +} diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java index 32dd2b1d8..1b5cd364a 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java @@ -1,6 +1,7 @@ package com.mageddo.dnsproxyserver.solver.remote.application.failsafe; import com.mageddo.dnsproxyserver.solver.remote.application.FailsafeCircuitBreakerFactory; +import com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application.CircuitBreakerDelegateNonResilient; import dev.failsafe.CircuitBreaker; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -112,4 +113,21 @@ void mustCheckAndCountErrorWhenSafeCheckReturnsFalse() { assertEquals(1, result.getValue()); } + @Test + void mustBuildNonResilientCircuitBreaker(){ + + // arrange + final var addr = InetSocketAddressTemplates._8_8_8_8(); + doReturn(CircuitBreakerConfigTemplates.buildNonResilientConfig()) + .when(this.factory) + .findCircuitBreakerConfig(); + + // act + final var circuitBreaker = this.factory.findCircuitBreaker(addr); + + // assert + assertEquals(CircuitBreakerDelegateNonResilient.class, circuitBreaker.getClass()); + + } + } diff --git a/src/test/java/testing/templates/CircuitBreakerConfigTemplates.java b/src/test/java/testing/templates/CircuitBreakerConfigTemplates.java index f4a55a003..287c7d2b2 100644 --- a/src/test/java/testing/templates/CircuitBreakerConfigTemplates.java +++ b/src/test/java/testing/templates/CircuitBreakerConfigTemplates.java @@ -1,17 +1,20 @@ package testing.templates; -import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategy; +import com.mageddo.dnsproxyserver.config.CircuitBreakerStrategyConfig; +import com.mageddo.dnsproxyserver.config.NonResilientCircuitBreakerStrategyConfig; +import com.mageddo.dnsproxyserver.config.StaticThresholdCircuitBreakerStrategyConfig; import com.mageddo.dnsproxyserver.config.mapper.ConfigMapper; import java.time.Duration; public class CircuitBreakerConfigTemplates { - public static StaticThresholdCircuitBreakerStrategy buildDefault(){ + + public static StaticThresholdCircuitBreakerStrategyConfig buildDefault(){ return ConfigMapper.defaultCircuitBreaker(); } - public static StaticThresholdCircuitBreakerStrategy oneTryFailSuccess() { - return StaticThresholdCircuitBreakerStrategy + public static StaticThresholdCircuitBreakerStrategyConfig oneTryFailSuccess() { + return StaticThresholdCircuitBreakerStrategyConfig .builder() .successThreshold(1) .failureThreshold(1) @@ -19,4 +22,8 @@ public static StaticThresholdCircuitBreakerStrategy oneTryFailSuccess() { .testDelay(Duration.ofMillis(10)) .build(); } + + public static CircuitBreakerStrategyConfig buildNonResilientConfig() { + return new NonResilientCircuitBreakerStrategyConfig(); + } } From 6b5b0c4b9ef857153778b6585792a3eb76c6f572 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 09:47:44 -0300 Subject: [PATCH 21/70] refactoring and test --- .../CircuitBreakerNonResilientService.java | 20 ------ .../application/CircuitBreakerService.java | 47 ++++++++++-- .../CircuitBreakerFailSafeService.java | 54 -------------- .../configurator/SolverRemoteModule.java | 5 -- .../solver/SolverRemoteTest.java | 5 +- ...CircuitBreakerFailSafeServiceCompTest.java | 71 ------------------- ...erDelegateStaticThresholdFailsafeTest.java | 41 ++++++++++- 7 files changed, 84 insertions(+), 159 deletions(-) delete mode 100644 src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerNonResilientService.java delete mode 100644 src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeService.java delete mode 100644 src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeServiceCompTest.java diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerNonResilientService.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerNonResilientService.java deleted file mode 100644 index 0ad2decf4..000000000 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerNonResilientService.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.mageddo.dnsproxyserver.solver.remote.application; - -import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; -import com.mageddo.dnsproxyserver.solver.remote.Result; - -import java.net.InetSocketAddress; -import java.util.function.Supplier; - -// todo #533 criar um CircuitBreakerDelegate para esta classe -public class CircuitBreakerNonResilientService implements CircuitBreakerService { - @Override - public Result safeHandle(final InetSocketAddress resolverAddress, Supplier sup) { - return sup.get(); - } - - @Override - public CircuitStatus findCircuitStatus(InetSocketAddress resolverAddress) { - return null; - } -} diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerService.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerService.java index a085a1035..bbabc07e5 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerService.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerService.java @@ -1,16 +1,53 @@ package com.mageddo.dnsproxyserver.solver.remote.application; +import com.mageddo.commons.circuitbreaker.CircuitCheckException; +import com.mageddo.commons.circuitbreaker.CircuitIsOpenException; import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; import com.mageddo.dnsproxyserver.solver.remote.Result; +import com.mageddo.dnsproxyserver.solver.remote.application.failsafe.CircuitBreakerFactory; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ClassUtils; +import javax.inject.Inject; +import javax.inject.Singleton; import java.net.InetSocketAddress; import java.util.function.Supplier; -public interface CircuitBreakerService { - // fixme #533 esse padrão de strategy não é mais necessário aqui, foi movido para CircuitBreakerDelegate - // onde tem mais chances de reduzir duplicação - Result safeHandle(final InetSocketAddress resolverAddress, Supplier sup); +@Slf4j +@Singleton +@RequiredArgsConstructor(onConstructor = @__({@Inject})) +public class CircuitBreakerService { - CircuitStatus findCircuitStatus(InetSocketAddress resolverAddress); + private final CircuitBreakerFactory circuitBreakerFactory; + + private String status; + + public Result safeHandle(InetSocketAddress resolverAddress, Supplier sup) { + try { + return this.handle(resolverAddress, sup); + } catch (CircuitCheckException | CircuitIsOpenException e) { + final var clazz = ClassUtils.getSimpleName(e); + log.debug("status=circuitEvent, server={}, type={}", resolverAddress, clazz); + this.status = String.format("%s for %s", clazz, resolverAddress); + return Result.empty(); + } + } + + private Result handle(InetSocketAddress resolverAddress, Supplier sup) { + return this.circuitBreakerFactory.check(resolverAddress, sup); + } + + public String getStatus() { + return this.status; + } + + public void resetCircuitBreakerFactory() { + this.circuitBreakerFactory.reset(); + } + + public CircuitStatus findCircuitStatus(InetSocketAddress resolverAddress) { + return this.circuitBreakerFactory.findStatus(resolverAddress); + } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeService.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeService.java deleted file mode 100644 index 64bcc0f4c..000000000 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeService.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.mageddo.dnsproxyserver.solver.remote.application.failsafe; - -import com.mageddo.commons.circuitbreaker.CircuitCheckException; -import com.mageddo.dnsproxyserver.solver.remote.CircuitStatus; -import com.mageddo.dnsproxyserver.solver.remote.Result; -import com.mageddo.dnsproxyserver.solver.remote.application.CircuitBreakerService; -import com.mageddo.commons.circuitbreaker.CircuitIsOpenException; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ClassUtils; - -import javax.inject.Inject; -import javax.inject.Singleton; -import java.net.InetSocketAddress; -import java.util.function.Supplier; - -@Slf4j -@Singleton -@RequiredArgsConstructor(onConstructor = @__({@Inject})) -public class CircuitBreakerFailSafeService implements CircuitBreakerService { - - private final CircuitBreakerFactory circuitBreakerFactory; - - private String status; - - @Override - public Result safeHandle(InetSocketAddress resolverAddress, Supplier sup) { - try { - return this.handle(resolverAddress, sup); - } catch (CircuitCheckException | CircuitIsOpenException e) { - final var clazz = ClassUtils.getSimpleName(e); - log.debug("status=circuitEvent, server={}, type={}", resolverAddress, clazz); - this.status = String.format("%s for %s", clazz, resolverAddress); - return Result.empty(); - } - } - - private Result handle(InetSocketAddress resolverAddress, Supplier sup) { - return this.circuitBreakerFactory.check(resolverAddress, sup); - } - - public String getStatus() { - return this.status; - } - - public void resetCircuitBreakerFactory() { - this.circuitBreakerFactory.reset(); - } - - @Override - public CircuitStatus findCircuitStatus(InetSocketAddress resolverAddress) { - return this.circuitBreakerFactory.findStatus(resolverAddress); - } -} diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/configurator/SolverRemoteModule.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/configurator/SolverRemoteModule.java index 9714c2081..1d83d3809 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/configurator/SolverRemoteModule.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/configurator/SolverRemoteModule.java @@ -1,7 +1,5 @@ package com.mageddo.dnsproxyserver.solver.remote.configurator; -import com.mageddo.dnsproxyserver.solver.remote.application.CircuitBreakerService; -import com.mageddo.dnsproxyserver.solver.remote.application.failsafe.CircuitBreakerFailSafeService; import com.mageddo.dnsproxyserver.solver.remote.dataprovider.SolverConsistencyGuaranteeDAO; import com.mageddo.dnsproxyserver.solver.remote.dataprovider.SolverConsistencyGuaranteeDAOImpl; import dagger.Binds; @@ -11,9 +9,6 @@ @Module public interface SolverRemoteModule { - @Binds - @Singleton - CircuitBreakerService circuitBreakerService(CircuitBreakerFailSafeService impl); @Binds @Singleton diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteTest.java index d02699c32..50e3e038b 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteTest.java @@ -1,6 +1,5 @@ package com.mageddo.dnsproxyserver.solver; -import com.mageddo.dnsproxyserver.solver.remote.application.CircuitBreakerNonResilientService; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -25,8 +24,8 @@ @ExtendWith(MockitoExtension.class) class SolverRemoteTest { - @Spy - CircuitBreakerNonResilientService circuitBreakerService; +// @Spy +// CircuitBreakerNonResilientService circuitBreakerService; @Spy @InjectMocks diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeServiceCompTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeServiceCompTest.java deleted file mode 100644 index 1565b1e82..000000000 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFailSafeServiceCompTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.mageddo.dnsproxyserver.solver.remote.application.failsafe; - -import com.mageddo.commons.circuitbreaker.CircuitCheckException; -import com.mageddo.dnsproxyserver.solver.remote.Request; -import com.mageddo.dnsproxyserver.solver.remote.Result; -import com.mageddo.dnsproxyserver.solver.remote.dataprovider.SolverConsistencyGuaranteeDAO; -import dagger.sheath.InjectMock; -import dagger.sheath.junit.DaggerTest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import testing.ContextSupplier; -import testing.Events; -import testing.templates.solver.remote.RequestTemplates; - -import javax.inject.Inject; -import java.util.function.Supplier; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.verify; - -@DaggerTest(initializer = ContextSupplier.class, eventsHandler = Events.class) -class CircuitBreakerFailSafeServiceCompTest { - - @Inject - CircuitBreakerFailSafeService service; - - @InjectMock - SolverConsistencyGuaranteeDAO consistencyGuaranteeDAO; - - @BeforeEach - void beforeEach() { - this.service.resetCircuitBreakerFactory(); - } - - @Test - void mustOpenCircuitAfterThresholdFailures() { - // arrange - final var req = RequestTemplates.buildDefault(); - final Supplier failureSup = () -> { - throw new CircuitCheckException("mocked failure"); - }; - - // act - this.trySafeHandleReqThreeTimes(req, failureSup); - - // assert - final var result = this.service.safeHandle(req.getResolverAddress(), failureSup); - assertTrue(result.isEmpty()); - assertEquals("CircuitIsOpenException for /8.8.8.8:53", this.service.getStatus()); - - } - - @Test - void mustFlushCachesWhenCircuitBreakerStateChanges() { - // arrange // act - this.mustOpenCircuitAfterThresholdFailures(); - - // assert - verify(this.consistencyGuaranteeDAO).flushCachesFromCircuitBreakerStateChange(); - } - - void trySafeHandleReqThreeTimes(Request req, Supplier failureSup) { - for (int i = 0; i < 3; i++) { - final var result = this.service.safeHandle(req.getResolverAddress(), failureSup); - assertTrue(result.isEmpty()); - assertEquals("CircuitCheckException for /8.8.8.8:53", this.service.getStatus()); - } - } - -} diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java index 6b4fdbe62..5597bf7af 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java @@ -2,18 +2,27 @@ import com.mageddo.commons.circuitbreaker.CircuitCheckException; import com.mageddo.commons.circuitbreaker.CircuitIsOpenException; +import com.mageddo.dnsproxyserver.solver.remote.Result; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; import testing.templates.solver.remote.FailSafeCircuitBreakerTemplates; +import java.util.function.Supplier; + import static org.junit.jupiter.api.Assertions.assertThrows; class CircuitBreakerDelegateStaticThresholdFailsafeTest { +// @BeforeEach +// void beforeEach() { +// this.service.resetCircuitBreakerFactory(); +// } + + @Test void mustThrowAbstractOpenCircuitException() { // arrange - final var circuitBreaker = new CircuitBreakerDelegateStaticThresholdFailsafe(FailSafeCircuitBreakerTemplates.fastCircuit()); + final var circuitBreaker = buildCircuitBreaker(); // act final Executable stm = () -> { @@ -26,4 +35,34 @@ void mustThrowAbstractOpenCircuitException() { // assert } + + @Test + void mustOpenCircuitAfterThresholdFailures() { + // arrange + final var circuitBreaker = buildCircuitBreaker(); + final Supplier failureSup = () -> { + throw new CircuitCheckException("mocked failure"); + }; + + // act + assertThrows(CircuitCheckException.class, () -> circuitBreaker.execute(failureSup)); + + // assert + assertThrows(CircuitIsOpenException.class, () -> circuitBreaker.execute(failureSup)); + + } +// +// @Test +// void mustFlushCachesWhenCircuitBreakerStateChanges() { +// // arrange // act +// this.mustOpenCircuitAfterThresholdFailures(); +// +// // assert +// verify(this.consistencyGuaranteeDAO).flushCachesFromCircuitBreakerStateChange(); +// } + + + static CircuitBreakerDelegateStaticThresholdFailsafe buildCircuitBreaker() { + return new CircuitBreakerDelegateStaticThresholdFailsafe(FailSafeCircuitBreakerTemplates.fastCircuit()); + } } From 579093995e98f446c589169b523bf347cb472c94 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 09:49:43 -0300 Subject: [PATCH 22/70] removing unnecessary test --- ...cuitBreakerDelegateStaticThresholdFailsafeTest.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java index 5597bf7af..604b111d4 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java @@ -51,16 +51,6 @@ void mustOpenCircuitAfterThresholdFailures() { assertThrows(CircuitIsOpenException.class, () -> circuitBreaker.execute(failureSup)); } -// -// @Test -// void mustFlushCachesWhenCircuitBreakerStateChanges() { -// // arrange // act -// this.mustOpenCircuitAfterThresholdFailures(); -// -// // assert -// verify(this.consistencyGuaranteeDAO).flushCachesFromCircuitBreakerStateChange(); -// } - static CircuitBreakerDelegateStaticThresholdFailsafe buildCircuitBreaker() { return new CircuitBreakerDelegateStaticThresholdFailsafe(FailSafeCircuitBreakerTemplates.fastCircuit()); From a7704d63d26388e553d195d3bb89fab23a3aee23 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 10:15:22 -0300 Subject: [PATCH 23/70] refactoring and fixing test --- .../dnsproxyserver/solver/SolverRemote.java | 7 +++++- .../application/CircuitBreakerService.java | 4 ---- .../solver/SolverRemoteTest.java | 22 +++++++++++++++---- ...erDelegateStaticThresholdFailsafeTest.java | 6 ----- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/SolverRemote.java b/src/main/java/com/mageddo/dnsproxyserver/solver/SolverRemote.java index 18191602e..f7aa84310 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/SolverRemote.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/SolverRemote.java @@ -24,6 +24,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; import java.util.stream.Stream; import static com.mageddo.dns.utils.Messages.simplePrint; @@ -92,7 +93,11 @@ Request buildRequest(Message query, int resolverIndex, StopWatch stopWatch, Reso Result safeQueryResult(Request req) { req.splitStopWatch(); - return this.circuitBreakerService.safeHandle(req.getResolverAddress(), () -> this.queryResult(req)); + return this.queryUsingCircuitBreaker(req, () -> this.queryResult(req)); + } + + Result queryUsingCircuitBreaker(Request req, Supplier sup) { + return this.circuitBreakerService.safeHandle(req.getResolverAddress(), sup); } Result queryResult(Request req) { diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerService.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerService.java index bbabc07e5..375c2d42d 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerService.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/CircuitBreakerService.java @@ -43,10 +43,6 @@ public String getStatus() { return this.status; } - public void resetCircuitBreakerFactory() { - this.circuitBreakerFactory.reset(); - } - public CircuitStatus findCircuitStatus(InetSocketAddress resolverAddress) { return this.circuitBreakerFactory.findStatus(resolverAddress); } diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteTest.java index 50e3e038b..bbaa85170 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteTest.java @@ -11,6 +11,7 @@ import java.net.SocketTimeoutException; import java.util.concurrent.CompletableFuture; +import java.util.function.Supplier; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -18,15 +19,13 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; @ExtendWith(MockitoExtension.class) class SolverRemoteTest { -// @Spy -// CircuitBreakerNonResilientService circuitBreakerService; - @Spy @InjectMocks SolverRemote solverRemote; @@ -46,6 +45,8 @@ void mustCacheSolvedQueryFor5Minutes() { .when(this.solverRemote) .sendQueryAsyncToResolver(any()); + this.excludeCircuitBreakerStrategyAndCallQueryMethodDirectly(); + // act final var res = this.solverRemote.handle(query); @@ -68,6 +69,8 @@ void mustCacheNxDomainQueryFor1Hour() { .when(this.solverRemote) .sendQueryAsyncToResolver(any()); + this.excludeCircuitBreakerStrategyAndCallQueryMethodDirectly(); + // act final var res = this.solverRemote.handle(query); @@ -88,6 +91,8 @@ void mustReturnNullWhenGetTimeout() { .when(this.solverRemote) .sendQueryAsyncToResolver(any()); + this.excludeCircuitBreakerStrategyAndCallQueryMethodDirectly(); + final var query = MessageTemplates.acmeAQuery(); // act @@ -113,6 +118,8 @@ void mustReturnRaEvenWhenRemoteServerDoesntReturnsRA() { .when(this.solverRemote) .sendQueryAsyncToResolver(any()); + this.excludeCircuitBreakerStrategyAndCallQueryMethodDirectly(); + // act final var result = this.solverRemote.handle(query); @@ -139,6 +146,8 @@ void mustPingRemoteServerWhileQueryingWhenFeatureIsActive(){ .when(this.solverRemote) .sendQueryAsyncToResolver(any()); + this.excludeCircuitBreakerStrategyAndCallQueryMethodDirectly(); + // act final var res = this.solverRemote.handle(query); @@ -159,5 +168,10 @@ void pingRemoteServerWhileQueryingDisabledByDefault(){ } - + void excludeCircuitBreakerStrategyAndCallQueryMethodDirectly() { + doAnswer(iom -> Supplier.class.cast(iom.getArgument(1)).get()) + .when(this.solverRemote) + .queryUsingCircuitBreaker(any(), any()) + ; + } } diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java index 604b111d4..e2fb5e748 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/circuitbreaker/application/CircuitBreakerDelegateStaticThresholdFailsafeTest.java @@ -13,12 +13,6 @@ class CircuitBreakerDelegateStaticThresholdFailsafeTest { -// @BeforeEach -// void beforeEach() { -// this.service.resetCircuitBreakerFactory(); -// } - - @Test void mustThrowAbstractOpenCircuitException() { // arrange From 4bf6cf68389078dae85bdc067a5a4ad76e7719fc Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 10:38:17 -0300 Subject: [PATCH 24/70] creating a comp test to check integratio between modules --- .../solver/SolverRemoteCompTest.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteCompTest.java diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteCompTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteCompTest.java new file mode 100644 index 000000000..21c4d5fad --- /dev/null +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteCompTest.java @@ -0,0 +1,33 @@ +package com.mageddo.dnsproxyserver.solver; + +import dagger.sheath.junit.DaggerTest; +import org.junit.jupiter.api.Test; +import testing.ContextSupplier; +import testing.Events; +import testing.templates.MessageTemplates; + +import javax.inject.Inject; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@DaggerTest(initializer = ContextSupplier.class, eventsHandler = Events.class) +class SolverRemoteCompTest { + + @Inject + SolverRemote solver; + + @Test + void mustSolveFromAvailableResolvers(){ + + // arrange + final var query = MessageTemplates.acmeAQuery(); + + // act + final var res = this.solver.handle(query); + + + // assert + assertNotNull(res); + + } +} From 940f72d2858d66206f834ee516afa76f14e1caed Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 10:39:43 -0300 Subject: [PATCH 25/70] new test detecting bug --- .../failsafe/CircuitBreakerFactoryTest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java index 1b5cd364a..37bb2d5a0 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactoryTest.java @@ -14,6 +14,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -130,4 +131,14 @@ void mustBuildNonResilientCircuitBreaker(){ } + @Test + void mustReturnNullWhenNoStatusIsFound(){ + + final var addr = InetSocketAddressTemplates._8_8_8_8(); + + final var status = this.factory.findStatus(addr); + + assertNull(status); + } + } From 3780b1437baf68f70d519276557d2ba32b3c0272 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 10:43:44 -0300 Subject: [PATCH 26/70] fixing bug and release notes --- RELEASE-NOTES.md | 3 +++ .../application/failsafe/CircuitBreakerFactory.java | 13 ++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 015cccc4f..2de6544bd 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,3 +1,6 @@ +## 3.25.14 +* Fixing SolverRemote NPE #533 + ## 3.25.13 * Unifying circuit breaker abstractions #553 diff --git a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java index 23916d028..0159b1595 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java +++ b/src/main/java/com/mageddo/dnsproxyserver/solver/remote/application/failsafe/CircuitBreakerFactory.java @@ -99,16 +99,23 @@ public List stats() { } public CircuitStatus findStatus(InetSocketAddress remoteAddress) { - return this.circuitBreakerMap.get(remoteAddress) - .findStatus(); + final var circuitBreaker = this.findCircuitBreakerFromCache(remoteAddress); + if (circuitBreaker == null) { + return null; + } + return circuitBreaker.findStatus(); } private Stats toStats(InetSocketAddress remoteAddr) { - final var circuitBreaker = this.circuitBreakerMap.get(remoteAddr); + final var circuitBreaker = this.findCircuitBreakerFromCache(remoteAddr); final var state = circuitBreaker.findStatus().name(); return Stats.of(remoteAddr.toString(), state); } + private CircuitBreakerDelegate findCircuitBreakerFromCache(InetSocketAddress remoteAddress) { + return this.circuitBreakerMap.get(remoteAddress); + } + @Value public static class Stats { From 4d4dd8fd99cf2b54aac5c7545bca3aa7407797d9 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 10:43:53 -0300 Subject: [PATCH 27/70] [Gradle Release Plugin] - new version commit: '3.25.14-snapshot'. --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9ffa1d8d5..9bf694fac 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=3.25.13-snapshot +version=3.25.14-snapshot From 3ed7e55bd09488543d78dee8c1df7dcbc5b8da5c Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 10:58:40 -0300 Subject: [PATCH 28/70] comp test wont be able to be mocked, creating a int test instead --- .../mageddo/dnsproxyserver/AppIntTest.java | 24 ++++++++++++-- .../solver/SolverRemoteCompTest.java | 33 ------------------- .../remote/RemoteResolversTemplates.java | 12 +++++++ .../solver/remote/ResolverTemplates.java | 25 ++++++++++++++ 4 files changed, 59 insertions(+), 35 deletions(-) delete mode 100644 src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteCompTest.java create mode 100644 src/test/java/testing/templates/solver/remote/RemoteResolversTemplates.java diff --git a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java index d9c1db6e6..9804fd695 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java @@ -29,12 +29,32 @@ void beforeEach() { } @AfterAll - static void afterAll(){ + static void afterAll() { Starter.setMustStartFlagActive(false); } @Test - void appMustStartAndQuerySampleWithSuccess() { + void appMustStartAndQuerySampleWithSuccessFromLocalDbSolver() { + + final var hostToQuery = "dps-sample.dev"; + final var args = ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDns(); + final var app = new App(args); + + try (final var executor = Executors.newThreadExecutor()) { + + executor.submit(app::start); + + Threads.sleep(Duration.ofSeconds(2)); + + final var port = app.getDnsServerPort(); + final var res = queryStartedServer(port, hostToQuery); + assertTrue(Messages.isSuccess(res)); + + } + } + + @Test + void mustQueryRemoteSolverPassingThroughAllModulesAndGetSuccess() { final var hostToQuery = "dps-sample.dev"; final var args = ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDns(); diff --git a/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteCompTest.java b/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteCompTest.java deleted file mode 100644 index 21c4d5fad..000000000 --- a/src/test/java/com/mageddo/dnsproxyserver/solver/SolverRemoteCompTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.mageddo.dnsproxyserver.solver; - -import dagger.sheath.junit.DaggerTest; -import org.junit.jupiter.api.Test; -import testing.ContextSupplier; -import testing.Events; -import testing.templates.MessageTemplates; - -import javax.inject.Inject; - -import static org.junit.jupiter.api.Assertions.assertNotNull; - -@DaggerTest(initializer = ContextSupplier.class, eventsHandler = Events.class) -class SolverRemoteCompTest { - - @Inject - SolverRemote solver; - - @Test - void mustSolveFromAvailableResolvers(){ - - // arrange - final var query = MessageTemplates.acmeAQuery(); - - // act - final var res = this.solver.handle(query); - - - // assert - assertNotNull(res); - - } -} diff --git a/src/test/java/testing/templates/solver/remote/RemoteResolversTemplates.java b/src/test/java/testing/templates/solver/remote/RemoteResolversTemplates.java new file mode 100644 index 000000000..563f04423 --- /dev/null +++ b/src/test/java/testing/templates/solver/remote/RemoteResolversTemplates.java @@ -0,0 +1,12 @@ +package testing.templates.solver.remote; + +import com.mageddo.dnsproxyserver.solver.Resolver; + +import java.util.List; + +public class RemoteResolversTemplates { + + public static List buildSuccessAnswerResolverStub() { + return List.of(ResolverTemplates.successAAcmeAnswer()); + } +} diff --git a/src/test/java/testing/templates/solver/remote/ResolverTemplates.java b/src/test/java/testing/templates/solver/remote/ResolverTemplates.java index 65f815f89..7d7dd7cef 100644 --- a/src/test/java/testing/templates/solver/remote/ResolverTemplates.java +++ b/src/test/java/testing/templates/solver/remote/ResolverTemplates.java @@ -2,12 +2,37 @@ import com.mageddo.dnsproxyserver.solver.Resolver; import com.mageddo.dnsproxyserver.solver.SimpleResolver; +import lombok.SneakyThrows; import testing.templates.InetSocketAddressTemplates; +import testing.templates.MessageTemplates; import java.util.List; +import java.util.concurrent.Executor; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; public class ResolverTemplates { public static List googleDnsAsList() { return List.of(new SimpleResolver(InetSocketAddressTemplates._8_8_8_8())); } + + @SneakyThrows + public static Resolver successAAcmeAnswer() { + final var resolver = new SimpleResolver(); + + doReturn(MessageTemplates.acmeAResponse()) + .when(resolver) + .send(any()); + ; + doReturn(MessageTemplates.acmeAResponse()) + .when(resolver) + .sendAsync(any()) + ; + doReturn(MessageTemplates.acmeAResponse()) + .when(resolver) + .sendAsync(any(), any(Executor.class)); + ; + return resolver; + } } From 556d3a58a9478ea607114bca76a0fc680462ba26 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 13:40:33 -0300 Subject: [PATCH 29/70] creating dps binary executable finder --- build.gradle | 2 +- .../java/com/mageddo/dnsproxyserver/App.java | 2 +- .../mageddo/dnsproxyserver/config/Config.java | 8 +++ .../config/application/ConfigService.java | 6 ++- .../config/dataprovider/ConfigDAOEnv.java | 1 + .../dataprovider/mapper/ConfigFlagMapper.java | 1 + .../mapper/ConfigJsonV2Mapper.java | 1 + .../config/mapper/ConfigMapper.java | 2 + .../sandbox/DpsBinaryExecutableFinder.java | 50 +++++++++++++++++++ .../sandbox/GradleTestsSandbox.java | 9 ++++ .../dnsproxyserver/sandbox/Instance.java | 13 +++++ .../dnsproxyserver/sandbox/Sandbox.java | 10 ++++ .../mageddo/dnsproxyserver/AppIntTest.java | 41 ++++++++++++--- .../DpsBinaryExecutableFinderIntTest.java | 31 ++++++++++++ .../java/com/mageddo/net/SocketUtilsTest.java | 13 ++++- .../templates/ConfigFlagArgsTemplates.java | 42 ++++++++++++++++ 16 files changed, 220 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/sandbox/GradleTestsSandbox.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java create mode 100644 src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java diff --git a/build.gradle b/build.gradle index b84c1ff58..1ad652588 100644 --- a/build.gradle +++ b/build.gradle @@ -92,7 +92,7 @@ dependencies { test { useJUnitPlatform() - exclude "**/*CompTest.class" + exclude "**/*CompTest.class", "**/*IntTest.class" testLogging { events "passed", "skipped", "failed" } diff --git a/src/main/java/com/mageddo/dnsproxyserver/App.java b/src/main/java/com/mageddo/dnsproxyserver/App.java index 4e32b66cb..08345b029 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/App.java +++ b/src/main/java/com/mageddo/dnsproxyserver/App.java @@ -51,7 +51,7 @@ void mustStart() { this.checkExitCommands(); - this.config = this.findConfig(args); + this.config = this.findConfig(this.args); this.setupLogs(); diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java index 9b4183ee0..a5880064b 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java @@ -73,6 +73,9 @@ public class Config { private SolverRemote solverRemote; + @NonNull + private Source source; + @JsonIgnore public Boolean isSolverRemoteActive() { if (this.solverRemote == null) { @@ -97,6 +100,11 @@ public CircuitBreakerStrategyConfig getSolverRemoteCircuitBreakerStrategy() { return this.solverRemote.getCircuitBreaker(); } + public enum Source { + JSON, FLAG, DEFAULT, MERGED, ENV + + } + @Value public static class Env { diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/application/ConfigService.java b/src/main/java/com/mageddo/dnsproxyserver/config/application/ConfigService.java index a1341eb15..a02ea3614 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/application/ConfigService.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/application/ConfigService.java @@ -5,6 +5,7 @@ import com.mageddo.dnsproxyserver.config.SolverRemote; import com.mageddo.dnsproxyserver.config.dataprovider.ConfigDAO; import com.mageddo.dnsproxyserver.config.mapper.ConfigMapper; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ClassUtils; import javax.enterprise.inject.Instance; @@ -14,6 +15,7 @@ import java.util.List; import java.util.stream.Stream; +@Slf4j @Singleton public class ConfigService { @@ -28,7 +30,9 @@ public ConfigService(Instance configDAOS) { } public Config findCurrentConfig() { - return ConfigMapper.mapFrom(this.findConfigs()); + final var configs = this.findConfigs(); + log.trace("baseConfigs={}", configs); + return ConfigMapper.mapFrom(configs); } public SolverRemote findCurrentConfigRemote(){ diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/ConfigDAOEnv.java b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/ConfigDAOEnv.java index 798f1398b..bf842eea1 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/ConfigDAOEnv.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/ConfigDAOEnv.java @@ -46,6 +46,7 @@ static Config toConfig(ConfigEnv config) { .builder() .active(Booleans.reverseWhenNotNull(config.getNoRemoteServers())) .build()) + .source(Config.Source.ENV) .build(); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigFlagMapper.java b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigFlagMapper.java index 97f19c072..520a78a93 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigFlagMapper.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigFlagMapper.java @@ -29,6 +29,7 @@ public static Config toConfig(ConfigFlag config) { .active(Booleans.reverseWhenNotNull(config.getNoRemoteServers())) .build() ) + .source(Config.Source.FLAG) .build(); } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java index e3289973c..94480215c 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/mapper/ConfigJsonV2Mapper.java @@ -32,6 +32,7 @@ public static Config toConfig(ConfigJson json, Path configFileAbsolutePath) { .dockerSolverHostMachineFallbackActive(json.getDockerSolverHostMachineFallbackActive()) .configPath(configFileAbsolutePath) .solverRemote(toSolverRemote(json)) + .source(Config.Source.JSON) .build(); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java b/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java index 681b260a4..2931ef449 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/mapper/ConfigMapper.java @@ -54,6 +54,7 @@ private static Config mapFrom0(List configs) { .circuitBreaker(firstNonNullRequiring(mapField(Config::getSolverRemoteCircuitBreakerStrategy, configs))) .build() ) + .source(Config.Source.MERGED) .build(); ConfigValidator.validate(config); return config; @@ -71,6 +72,7 @@ private static Config buildDefault() { .circuitBreaker(defaultCircuitBreaker()) .build() ) + .source(Config.Source.DEFAULT) .build(); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java new file mode 100644 index 000000000..818d3243a --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java @@ -0,0 +1,50 @@ +package com.mageddo.dnsproxyserver.sandbox; + +import com.mageddo.utils.Runtime; +import lombok.SneakyThrows; +import org.apache.commons.lang3.Validate; +import org.graalvm.nativeimage.ImageInfo; + +import java.nio.file.Files; +import java.nio.file.Path; + +public class DpsBinaryExecutableFinder { + + public static Path find() { + return new DpsBinaryExecutableFinder().findBestExecutablePath(); + } + + Path findBestExecutablePath() { + if (ImageInfo.inImageRuntimeCode()) { + return findBuiltNativeExecutablePath(); + } + return findBuiltJarPath(); + } + + Path findBuiltNativeExecutablePath() { + final var buildPath = this.findBuilPath(); + final var path = buildPath.resolve("build/native/generateIntTestResourcesConfigFile/nativeIntTestCompile"); + Validate.isTrue(Files.exists(path), "Native executable not found at: " + path); + return path; + } + + Path findBuiltJarPath() { + final var buildPath = this.findBuilPath(); + final var libsPath = buildPath.resolve("libs"); + return findFirstMatchInPath(libsPath); + } + + @SneakyThrows + private Path findFirstMatchInPath(Path libsPath) { + try (var stream = Files.list(libsPath)) { + return stream + .filter(path -> path.toString().endsWith("-all.jar")) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Unable to find fat jar at libs path")); + } + } + + private Path findBuilPath() { + return Runtime.getRunningDir().getParent().getParent().getParent(); + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/GradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/GradleTestsSandbox.java new file mode 100644 index 000000000..e323414a2 --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/GradleTestsSandbox.java @@ -0,0 +1,9 @@ +package com.mageddo.dnsproxyserver.sandbox; + +public class GradleTestsSandbox { + public void run(String[] args) { + final var executablePath = DpsBinaryExecutableFinder.find(); + } + + +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java new file mode 100644 index 000000000..32cd733af --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java @@ -0,0 +1,13 @@ +package com.mageddo.dnsproxyserver.sandbox; + +import com.mageddo.commons.exec.CommandLines; +import lombok.Builder; +import lombok.NonNull; +import lombok.Value; + +@Value +@Builder +public class Instance { + @NonNull + CommandLines.Result result; +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java new file mode 100644 index 000000000..89a14c74a --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java @@ -0,0 +1,10 @@ +package com.mageddo.dnsproxyserver.sandbox; + +public class Sandbox { + public Instance runFromGradleTests(String[] args){ + + return Instance + .builder() + .build(); + } +} diff --git a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java index 9804fd695..0593f3fc6 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java @@ -7,15 +7,20 @@ import com.mageddo.dnsproxyserver.solver.SimpleResolver; import com.mageddo.dnsproxyserver.utils.Ips; import com.mageddo.utils.Executors; +import com.mageddo.utils.Runtime; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.xbill.DNS.Message; import testing.templates.ConfigFlagArgsTemplates; import java.time.Duration; +import java.util.Arrays; +import java.util.concurrent.ExecutorService; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -53,27 +58,49 @@ void appMustStartAndQuerySampleWithSuccessFromLocalDbSolver() { } } + @Disabled @Test void mustQueryRemoteSolverPassingThroughAllModulesAndGetSuccess() { - final var hostToQuery = "dps-sample.dev"; - final var args = ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDns(); - final var app = new App(args); - try (final var executor = Executors.newThreadExecutor()) { + System.out.println(Runtime.getRunningDir()); - executor.submit(app::start); + Assertions.fail(); - Threads.sleep(Duration.ofSeconds(2)); + final var hostToQuery = "dps-int-test.dev"; - final var port = app.getDnsServerPort(); + try (final var executor = Executors.newThreadExecutor()) { + + final var clientApp = buildClientAppAndWait(executor); + final var serverApp = buildServerAppAndWait(executor, hostToQuery); + + final var port = clientApp.getDnsServerPort(); final var res = queryStartedServer(port, hostToQuery); + assertTrue(Messages.isSuccess(res)); } } + private static App buildClientAppAndWait(ExecutorService executor) { + return buildAppAndWait(executor, ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDns()); + } + + private static App buildServerAppAndWait(ExecutorService executor, String hostToQuery) { + return buildAppAndWait( + executor, ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(hostToQuery) + ); + } + + private static App buildAppAndWait(ExecutorService executor, final String[] params) { + log.debug("app={}", Arrays.toString(params)); + final var app = new App(params); + executor.submit(app::start); + Threads.sleep(Duration.ofSeconds(2)); + return app; + } + @SneakyThrows static Message queryStartedServer(Integer port, String host) { final var dnsServerAddress = Ips.getAnyLocalAddress(port); diff --git a/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java new file mode 100644 index 000000000..c29c1a032 --- /dev/null +++ b/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java @@ -0,0 +1,31 @@ +package com.mageddo.dnsproxyserver.sandbox; + +import org.graalvm.nativeimage.ImageInfo; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +class DpsBinaryExecutableFinderIntTest { + + @Test + void mustFindDpsNativeExecutablePath(){ + assumeTrue(ImageInfo.inImageRuntimeCode()); + + final var found = DpsBinaryExecutableFinder.find(); + + assertTrue(found.toString().endsWith("-tests")); + } + + @Test + void mustFindDpsJarPath(){ + assertFalse(ImageInfo.inImageRuntimeCode()); + + final var found = DpsBinaryExecutableFinder.find(); + + assertTrue(found.toString().endsWith(".jar")); + } + + +} diff --git a/src/test/java/com/mageddo/net/SocketUtilsTest.java b/src/test/java/com/mageddo/net/SocketUtilsTest.java index ce4aa51d9..c6b31cdd0 100644 --- a/src/test/java/com/mageddo/net/SocketUtilsTest.java +++ b/src/test/java/com/mageddo/net/SocketUtilsTest.java @@ -2,12 +2,13 @@ import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; class SocketUtilsTest { @Test - void mustFindRandomFreePort(){ + void mustFindRandomFreePort() { // arrange // act @@ -16,4 +17,12 @@ void mustFindRandomFreePort(){ // assert assertTrue(port > 0); } + + @Test + void mustFindTwoDifferentPortsForConsecutiveCalls() { + for (int i = 0; i < 3; i++) { + assertNotEquals(SocketUtils.findRandomFreePort(), SocketUtils.findRandomFreePort()); + } + } + } diff --git a/src/test/java/testing/templates/ConfigFlagArgsTemplates.java b/src/test/java/testing/templates/ConfigFlagArgsTemplates.java index a1ed7c0ee..492afbb29 100644 --- a/src/test/java/testing/templates/ConfigFlagArgsTemplates.java +++ b/src/test/java/testing/templates/ConfigFlagArgsTemplates.java @@ -1,6 +1,10 @@ package testing.templates; import com.mageddo.net.SocketUtils; +import lombok.SneakyThrows; + +import java.nio.file.Files; +import java.nio.file.Path; public class ConfigFlagArgsTemplates { public static String[] withRandomPortsAndNotAsDefaultDns() { @@ -14,4 +18,42 @@ public static String[] withRandomPortsAndNotAsDefaultDns() { "--log-level=TRACE", }; } + + public static String[] withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(String host) { + final var configPath = makeConfigFile(host); + final var webServerPort = SocketUtils.findRandomFreePort(); + final var dnsServerPort = SocketUtils.findRandomFreePort(); + return new String[]{ + "--default-dns=false", + "--web-server-port=" + webServerPort, + "--server-port=" + dnsServerPort, + "--log-level=TRACE", + "--conf-path=" + configPath.toString() + }; + } + + @SneakyThrows + private static Path makeConfigFile(String host) { + final var configJsonContent = """ + { + "version": 2, + "remoteDnsServers": [], + "envs": [ + { + "name": "", + "hostnames": + { + "type": "A", + "hostname": "%s", + "ip": "192.168.0.1", + "ttl": 255 + } + ] + } + ] + } + """.formatted(host); + final var config = Files.createTempFile("config", ".json"); + return Files.writeString(config, configJsonContent); + } } From 0eb121241260d04629d22cac44f3ea325c1ad640 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 13:45:57 -0300 Subject: [PATCH 30/70] configuring sandbox --- .../sandbox/BinaryFromGradleTestsSandbox.java | 15 +++++++++++++++ .../sandbox/GradleTestsSandbox.java | 9 --------- .../mageddo/dnsproxyserver/sandbox/Instance.java | 8 ++++++++ .../sandbox/DpsBinaryExecutableFinderIntTest.java | 4 ++-- 4 files changed, 25 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java delete mode 100644 src/main/java/com/mageddo/dnsproxyserver/sandbox/GradleTestsSandbox.java diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java new file mode 100644 index 000000000..3c3fff670 --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -0,0 +1,15 @@ +package com.mageddo.dnsproxyserver.sandbox; + +import com.mageddo.commons.exec.CommandLines; +import org.apache.commons.exec.CommandLine; + +public class BinaryFromGradleTestsSandbox { + public Instance run(String[] args) { + final var executablePath = DpsBinaryExecutableFinder.find(); + final var commandLine = new CommandLine(executablePath.toFile()) + .addArguments(args); + return Instance.of(CommandLines.exec(commandLine)); + } + + +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/GradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/GradleTestsSandbox.java deleted file mode 100644 index e323414a2..000000000 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/GradleTestsSandbox.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.mageddo.dnsproxyserver.sandbox; - -public class GradleTestsSandbox { - public void run(String[] args) { - final var executablePath = DpsBinaryExecutableFinder.find(); - } - - -} diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java index 32cd733af..01e9dfa82 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java @@ -8,6 +8,14 @@ @Value @Builder public class Instance { + @NonNull CommandLines.Result result; + + public static Instance of(CommandLines.Result result) { + return Instance.builder() + .result(result) + .build() + ; + } } diff --git a/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java index c29c1a032..6953e96fc 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java @@ -3,8 +3,8 @@ import org.graalvm.nativeimage.ImageInfo; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeTrue; class DpsBinaryExecutableFinderIntTest { @@ -20,7 +20,7 @@ void mustFindDpsNativeExecutablePath(){ @Test void mustFindDpsJarPath(){ - assertFalse(ImageInfo.inImageRuntimeCode()); + assumeFalse(ImageInfo.inImageRuntimeCode()); final var found = DpsBinaryExecutableFinder.find(); From 1e86f1960f47145ff68c27f73a16059d18519857 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 13:50:30 -0300 Subject: [PATCH 31/70] creating sandbox and tests --- .../sandbox/BinaryFromGradleTestsSandbox.java | 11 ++++++++++- .../sandbox/DpsBinaryExecutableFinder.java | 2 +- .../mageddo/dnsproxyserver/sandbox/Sandbox.java | 7 ++----- .../com/mageddo/dnsproxyserver/AppIntTest.java | 17 +++++------------ 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java index 3c3fff670..e23a1ebdc 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -1,14 +1,23 @@ package com.mageddo.dnsproxyserver.sandbox; +import com.mageddo.commons.concurrent.Threads; import com.mageddo.commons.exec.CommandLines; import org.apache.commons.exec.CommandLine; +import java.time.Duration; + public class BinaryFromGradleTestsSandbox { public Instance run(String[] args) { final var executablePath = DpsBinaryExecutableFinder.find(); final var commandLine = new CommandLine(executablePath.toFile()) .addArguments(args); - return Instance.of(CommandLines.exec(commandLine)); + final var instance = Instance.of(CommandLines.exec(commandLine)); + waitForStartup(instance); + return instance; + } + + private void waitForStartup(Instance instance) { + Threads.sleep(Duration.ofSeconds(2)); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java index 818d3243a..4fdfdb506 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java @@ -23,7 +23,7 @@ Path findBestExecutablePath() { Path findBuiltNativeExecutablePath() { final var buildPath = this.findBuilPath(); - final var path = buildPath.resolve("build/native/generateIntTestResourcesConfigFile/nativeIntTestCompile"); + final var path = buildPath.resolve("native/nativeIntTestCompile/dns-proxy-server-tests"); Validate.isTrue(Files.exists(path), "Native executable not found at: " + path); return path; } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java index 89a14c74a..df6572968 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java @@ -1,10 +1,7 @@ package com.mageddo.dnsproxyserver.sandbox; public class Sandbox { - public Instance runFromGradleTests(String[] args){ - - return Instance - .builder() - .build(); + public static Instance runFromGradleTests(String[] args) { + return new BinaryFromGradleTestsSandbox().run(args); } } diff --git a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java index 0593f3fc6..40c6b5ae9 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java @@ -3,15 +3,14 @@ import com.mageddo.commons.concurrent.Threads; import com.mageddo.dns.utils.Messages; import com.mageddo.dnsproxyserver.config.application.Configs; +import com.mageddo.dnsproxyserver.sandbox.Sandbox; import com.mageddo.dnsproxyserver.server.Starter; import com.mageddo.dnsproxyserver.solver.SimpleResolver; import com.mageddo.dnsproxyserver.utils.Ips; import com.mageddo.utils.Executors; -import com.mageddo.utils.Runtime; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -62,17 +61,12 @@ void appMustStartAndQuerySampleWithSuccessFromLocalDbSolver() { @Test void mustQueryRemoteSolverPassingThroughAllModulesAndGetSuccess() { - - System.out.println(Runtime.getRunningDir()); - - Assertions.fail(); - final var hostToQuery = "dps-int-test.dev"; try (final var executor = Executors.newThreadExecutor()) { final var clientApp = buildClientAppAndWait(executor); - final var serverApp = buildServerAppAndWait(executor, hostToQuery); + buildServerAppAndWait(executor, hostToQuery); final var port = clientApp.getDnsServerPort(); final var res = queryStartedServer(port, hostToQuery); @@ -87,10 +81,9 @@ private static App buildClientAppAndWait(ExecutorService executor) { return buildAppAndWait(executor, ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDns()); } - private static App buildServerAppAndWait(ExecutorService executor, String hostToQuery) { - return buildAppAndWait( - executor, ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(hostToQuery) - ); + private static void buildServerAppAndWait(ExecutorService executor, String hostToQuery) { + final var args = ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(hostToQuery); + final var instance = Sandbox.runFromGradleTests(args); } private static App buildAppAndWait(ExecutorService executor, final String[] params) { From bedd1c07e01315a99e98827b6bcc38c4e85ade56 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Mon, 2 Sep 2024 13:57:05 -0300 Subject: [PATCH 32/70] fixing test --- .../sandbox/DpsBinaryExecutableFinder.java | 18 ++++++++++++++---- .../com/mageddo/dnsproxyserver/AppIntTest.java | 1 + 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java index 4fdfdb506..df844705d 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java @@ -2,12 +2,14 @@ import com.mageddo.utils.Runtime; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.Validate; import org.graalvm.nativeimage.ImageInfo; import java.nio.file.Files; import java.nio.file.Path; +@Slf4j public class DpsBinaryExecutableFinder { public static Path find() { @@ -22,14 +24,14 @@ Path findBestExecutablePath() { } Path findBuiltNativeExecutablePath() { - final var buildPath = this.findBuilPath(); + final var buildPath = this.findBuildPath(); final var path = buildPath.resolve("native/nativeIntTestCompile/dns-proxy-server-tests"); Validate.isTrue(Files.exists(path), "Native executable not found at: " + path); return path; } Path findBuiltJarPath() { - final var buildPath = this.findBuilPath(); + final var buildPath = this.findBuildPath(); final var libsPath = buildPath.resolve("libs"); return findFirstMatchInPath(libsPath); } @@ -44,7 +46,15 @@ private Path findFirstMatchInPath(Path libsPath) { } } - private Path findBuilPath() { - return Runtime.getRunningDir().getParent().getParent().getParent(); + private Path findBuildPath() { + var path = Runtime.getRunningDir(); + while (path != null) { + if (path.endsWith("build")) { + log.trace("buildPath={}", path); + return path; + } + path = path.getParent(); + } + return null; } } diff --git a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java index 40c6b5ae9..b43c2721f 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java @@ -65,6 +65,7 @@ void mustQueryRemoteSolverPassingThroughAllModulesAndGetSuccess() { try (final var executor = Executors.newThreadExecutor()) { + // fixme must configure the remote server created as a remote for this one final var clientApp = buildClientAppAndWait(executor); buildServerAppAndWait(executor, hostToQuery); From 46bd9a5b42663ad29da39c347ee2ebaa0ced51d6 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 09:06:39 -0300 Subject: [PATCH 33/70] setup execution --- .../mageddo/commons/exec/CommandLines.java | 17 ++++++++++ .../sandbox/BinaryFromGradleTestsSandbox.java | 31 +++++++++++++++++-- .../dnsproxyserver/sandbox/Instance.java | 8 ++--- .../BinaryFromGradleTestsSandboxIntTest.java | 19 ++++++++++++ .../dnsproxyserver/sandbox/SandboxTest.java | 5 +++ 5 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 src/test/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandboxIntTest.java create mode 100644 src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java diff --git a/src/main/java/com/mageddo/commons/exec/CommandLines.java b/src/main/java/com/mageddo/commons/exec/CommandLines.java index 452d8622e..4a40233ad 100644 --- a/src/main/java/com/mageddo/commons/exec/CommandLines.java +++ b/src/main/java/com/mageddo/commons/exec/CommandLines.java @@ -7,6 +7,7 @@ import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.DaemonExecutor; import org.apache.commons.exec.ExecuteException; +import org.apache.commons.exec.ExecuteResultHandler; import org.apache.commons.exec.ExecuteWatchdog; import org.apache.commons.exec.Executor; import org.apache.commons.exec.PumpStreamHandler; @@ -53,6 +54,22 @@ public static Result exec(CommandLine commandLine, long timeout) { .build(); } + public static DaemonExecutor exec(CommandLine commandLine, ExecuteResultHandler handler) { + final var out = new ByteArrayOutputStream(); + final var executor = new DaemonExecutor(); + final var streamHandler = new PumpStreamHandler(out); + executor.setStreamHandler(streamHandler); + try { + executor.setWatchdog(new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT)); + executor.execute(commandLine, handler); + } catch (ExecuteException e) { + handler.onProcessFailed(e); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + return executor; + } + @Getter @Builder @ToString(of = {"exitCode"}) diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java index e23a1ebdc..85eb06b6b 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -3,21 +3,48 @@ import com.mageddo.commons.concurrent.Threads; import com.mageddo.commons.exec.CommandLines; import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.ExecuteException; +import org.apache.commons.exec.ExecuteResultHandler; import java.time.Duration; public class BinaryFromGradleTestsSandbox { public Instance run(String[] args) { + final var javaCommandPath = findJavaCommand(); final var executablePath = DpsBinaryExecutableFinder.find(); - final var commandLine = new CommandLine(executablePath.toFile()) + + final var commandLine = new CommandLine(javaCommandPath) + .addArgument("-jar") + .addArgument(executablePath.toFile().toString()) .addArguments(args); - final var instance = Instance.of(CommandLines.exec(commandLine)); + + final var executor = CommandLines.exec(commandLine, new ExecuteResultHandler() { + public void onProcessComplete(int exitValue) { + + } + + public void onProcessFailed(ExecuteException e) { + + } + }); + final var instance = Instance.of(executor); + executor.getWatchdog().; + waitForStartup(instance); return instance; } + private static String findJavaCommand() { + return ProcessHandle.current() + .info() + .command() + .orElseThrow(() -> new IllegalStateException("Couldn't find current java process command")) + ; + } + private void waitForStartup(Instance instance) { Threads.sleep(Duration.ofSeconds(2)); + System.out.println(instance.getExecutor().getOutAsString()); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java index 01e9dfa82..08b726bbf 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java @@ -1,20 +1,20 @@ package com.mageddo.dnsproxyserver.sandbox; -import com.mageddo.commons.exec.CommandLines; import lombok.Builder; import lombok.NonNull; import lombok.Value; +import org.apache.commons.exec.DaemonExecutor; @Value @Builder public class Instance { @NonNull - CommandLines.Result result; + DaemonExecutor executor; - public static Instance of(CommandLines.Result result) { + public static Instance of(DaemonExecutor executor) { return Instance.builder() - .result(result) + .executor(executor) .build() ; } diff --git a/src/test/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandboxIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandboxIntTest.java new file mode 100644 index 000000000..ff5e1586e --- /dev/null +++ b/src/test/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandboxIntTest.java @@ -0,0 +1,19 @@ +package com.mageddo.dnsproxyserver.sandbox; + +import org.junit.jupiter.api.Test; + +class BinaryFromGradleTestsSandboxIntTest { + + BinaryFromGradleTestsSandbox sandbox = new BinaryFromGradleTestsSandbox(); + + @Test + void mustRunFromGradleTests(){ + // arrange + final var args = new String[]{}; + + // act + this.sandbox.run(args); + + // assert + } +} diff --git a/src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java b/src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java new file mode 100644 index 000000000..a1ddfc758 --- /dev/null +++ b/src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java @@ -0,0 +1,5 @@ +package com.mageddo.dnsproxyserver.sandbox; + +class SandboxTest { + +} From 05188d19aee2250cd0d5e161999b0b4dc743fc40 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 09:40:35 -0300 Subject: [PATCH 34/70] creating a dummy signal based healthcheck --- .../mageddo/commons/exec/CommandLines.java | 10 +++-- .../healthcheck/HealthCheck.java | 16 ++++++++ .../HealthCheckSignalEntrypoint.java | 36 +++++++++++++++++ .../sandbox/BinaryFromGradleTestsSandbox.java | 10 ++--- .../dnsproxyserver/sandbox/Instance.java | 8 ++-- .../HealthCheckSignalEntrypointTest.java | 39 +++++++++++++++++++ 6 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/mageddo/dnsproxyserver/healthcheck/HealthCheck.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java create mode 100644 src/test/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypointTest.java diff --git a/src/main/java/com/mageddo/commons/exec/CommandLines.java b/src/main/java/com/mageddo/commons/exec/CommandLines.java index 4a40233ad..f8bf56caf 100644 --- a/src/main/java/com/mageddo/commons/exec/CommandLines.java +++ b/src/main/java/com/mageddo/commons/exec/CommandLines.java @@ -54,7 +54,7 @@ public static Result exec(CommandLine commandLine, long timeout) { .build(); } - public static DaemonExecutor exec(CommandLine commandLine, ExecuteResultHandler handler) { + public static Result exec(CommandLine commandLine, ExecuteResultHandler handler) { final var out = new ByteArrayOutputStream(); final var executor = new DaemonExecutor(); final var streamHandler = new PumpStreamHandler(out); @@ -67,7 +67,11 @@ public static DaemonExecutor exec(CommandLine commandLine, ExecuteResultHandler } catch (IOException e) { throw new UncheckedIOException(e); } - return executor; + return Result + .builder() + .executor(executor) + .out(out) + .build(); } @Getter @@ -81,7 +85,7 @@ public static class Result { @NonNull private ByteArrayOutputStream out; - private int exitCode; + private Integer exitCode; public String getOutAsString() { return this.out.toString(); diff --git a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/HealthCheck.java b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/HealthCheck.java new file mode 100644 index 000000000..93f352c5c --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/HealthCheck.java @@ -0,0 +1,16 @@ +package com.mageddo.dnsproxyserver.healthcheck; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Slf4j +@Singleton +@RequiredArgsConstructor(onConstructor = @__({@Inject})) +public class HealthCheck { + public boolean isHealth(){ + return true; + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java new file mode 100644 index 000000000..604412dbc --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java @@ -0,0 +1,36 @@ +package com.mageddo.dnsproxyserver.healthcheck.entrypoint; + +import com.mageddo.dnsproxyserver.healthcheck.HealthCheck; +import lombok.extern.slf4j.Slf4j; +import sun.misc.Signal; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Slf4j +@Singleton +public class HealthCheckSignalEntrypoint { + + private static final String USER_DEFINED_SIGNAL = "USR1"; + private final HealthCheck healthCheck; + + @Inject + public HealthCheckSignalEntrypoint(HealthCheck healthCheck) { + this.healthCheck = healthCheck; + this.safeRegisterHandler(); + } + + void safeRegisterHandler() { + try { + this.registerHandler(); + } catch (Throwable t){ + log.warn("status=couldntRegisterHandler, msg={}", t.getMessage(), t); + } + } + + void registerHandler() { + Signal.handle(new Signal(USER_DEFINED_SIGNAL), sig -> { + System.out.printf("dps.healthcheck=%b%n", this.healthCheck.isHealth()); + }); + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java index 85eb06b6b..098e0b3bf 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -18,7 +18,7 @@ public Instance run(String[] args) { .addArgument(executablePath.toFile().toString()) .addArguments(args); - final var executor = CommandLines.exec(commandLine, new ExecuteResultHandler() { + final var result = CommandLines.exec(commandLine, new ExecuteResultHandler() { public void onProcessComplete(int exitValue) { } @@ -27,10 +27,8 @@ public void onProcessFailed(ExecuteException e) { } }); - final var instance = Instance.of(executor); - executor.getWatchdog().; - - waitForStartup(instance); + final var instance = Instance.of(result); + this.waitForStartup(instance); return instance; } @@ -44,7 +42,7 @@ private static String findJavaCommand() { private void waitForStartup(Instance instance) { Threads.sleep(Duration.ofSeconds(2)); - System.out.println(instance.getExecutor().getOutAsString()); + System.out.println(instance.getResult().getOutAsString()); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java index 08b726bbf..01e9dfa82 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java @@ -1,20 +1,20 @@ package com.mageddo.dnsproxyserver.sandbox; +import com.mageddo.commons.exec.CommandLines; import lombok.Builder; import lombok.NonNull; import lombok.Value; -import org.apache.commons.exec.DaemonExecutor; @Value @Builder public class Instance { @NonNull - DaemonExecutor executor; + CommandLines.Result result; - public static Instance of(DaemonExecutor executor) { + public static Instance of(CommandLines.Result result) { return Instance.builder() - .executor(executor) + .result(result) .build() ; } diff --git a/src/test/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypointTest.java b/src/test/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypointTest.java new file mode 100644 index 000000000..106fc9983 --- /dev/null +++ b/src/test/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypointTest.java @@ -0,0 +1,39 @@ +package com.mageddo.dnsproxyserver.healthcheck.entrypoint; + +import com.mageddo.dnsproxyserver.healthcheck.HealthCheck; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.Mockito.doThrow; + +@ExtendWith(MockitoExtension.class) +class HealthCheckSignalEntrypointTest { + + @Mock + HealthCheck healthCheck; + + @Spy + @InjectMocks + HealthCheckSignalEntrypoint entrypoint; + + @Test + void mustRegisterHandler() { + this.entrypoint.registerHandler(); + } + + @Test + void mustCatchFatalErrorsWhenRegisteringHandler() { + + doThrow(new AssertionError("mocked error")) + .when(this.entrypoint) + .registerHandler(); + + this.entrypoint.safeRegisterHandler(); + + } + +} From 29873574126ebe631129ada4173163d64827d928 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 09:41:10 -0300 Subject: [PATCH 35/70] creating a dummy signal based healthcheck --- .../healthcheck/entrypoint/HealthCheckSignalEntrypoint.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java index 604412dbc..e7d35ebf5 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java +++ b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java @@ -30,7 +30,7 @@ void safeRegisterHandler() { void registerHandler() { Signal.handle(new Signal(USER_DEFINED_SIGNAL), sig -> { - System.out.printf("dps.healthcheck=%b%n", this.healthCheck.isHealth()); + System.out.printf("dps.healthCheck.isHealth=%b%n", this.healthCheck.isHealth()); }); } } From 82ff1d4d26fde3cd829ce904f195668989eda21f Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 09:41:16 -0300 Subject: [PATCH 36/70] creating a dummy signal based healthcheck --- .../healthcheck/entrypoint/HealthCheckSignalEntrypoint.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java index e7d35ebf5..207e022db 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java +++ b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java @@ -30,7 +30,7 @@ void safeRegisterHandler() { void registerHandler() { Signal.handle(new Signal(USER_DEFINED_SIGNAL), sig -> { - System.out.printf("dps.healthCheck.isHealth=%b%n", this.healthCheck.isHealth()); + System.out.printf("dps.healthCheck.health=%b%n", this.healthCheck.isHealth()); }); } } From 5d5f883269ce81a34f36ff05870bf47a753070fd Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 10:20:48 -0300 Subject: [PATCH 37/70] registering and testing eager beans --- build.gradle | 1 + src/main/java/com/mageddo/di/Eager.java | 5 ++ .../java/com/mageddo/dnsproxyserver/App.java | 15 +++++- .../mageddo/dnsproxyserver/di/Context.java | 10 +++- .../dnsproxyserver/di/module/ModuleEager.java | 24 +++++++++ .../di/module/ModuleStartup.java | 4 +- .../HealthCheckSignalEntrypoint.java | 8 ++- src/main/java/com/mageddo/json/JsonUtils.java | 9 +++- .../dnsproxyserver/di/ContextCompTest.java | 50 +++++++++++++++++++ 9 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/mageddo/di/Eager.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java create mode 100644 src/test/java/com/mageddo/dnsproxyserver/di/ContextCompTest.java diff --git a/build.gradle b/build.gradle index 1ad652588..2eea4fcd8 100644 --- a/build.gradle +++ b/build.gradle @@ -87,6 +87,7 @@ dependencies { testImplementation('org.mockito:mockito-junit-jupiter:5.12.+') testImplementation('org.hamcrest:hamcrest:3.0') testImplementation('io.rest-assured:rest-assured:5.5.0') + testImplementation('org.reflections:reflections:0.10.2') } diff --git a/src/main/java/com/mageddo/di/Eager.java b/src/main/java/com/mageddo/di/Eager.java new file mode 100644 index 000000000..cb13c33eb --- /dev/null +++ b/src/main/java/com/mageddo/di/Eager.java @@ -0,0 +1,5 @@ +package com.mageddo.di; + +public interface Eager { + default void run(){} +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/App.java b/src/main/java/com/mageddo/dnsproxyserver/App.java index 08345b029..3e39ac46b 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/App.java +++ b/src/main/java/com/mageddo/dnsproxyserver/App.java @@ -20,6 +20,7 @@ public class App { private final String[] args; private Config config; private ConfigFlag flags; + private Context context; public App(String[] args) { this.args = args; @@ -55,6 +56,8 @@ void mustStart() { this.setupLogs(); + log.trace("pid={}", ProcessHandle.current().pid()); + this.startContext(); // todo install as service @@ -79,11 +82,15 @@ void setupLogs() { } void startContext() { - final var context = Context.create(); + createContext(); // start webserver // start dns server - context.start(); + this.context.start(); + } + + private void createContext() { + this.context = Context.create(); } void checkExitCommands() { @@ -115,6 +122,10 @@ int getDnsServerPort() { return getConfig().getDnsServerPort(); } + Context getContext() { + return context; + } + static class SystemExitException extends RuntimeException { public SystemExitException(String reason) { super(reason); diff --git a/src/main/java/com/mageddo/dnsproxyserver/di/Context.java b/src/main/java/com/mageddo/dnsproxyserver/di/Context.java index 4683e0383..ca466bf91 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/di/Context.java +++ b/src/main/java/com/mageddo/dnsproxyserver/di/Context.java @@ -1,9 +1,11 @@ package com.mageddo.dnsproxyserver.di; import com.mageddo.di.CDIImpl; +import com.mageddo.di.Eager; import com.mageddo.dnsproxyserver.config.di.module.ModuleConfigDAO; import com.mageddo.dnsproxyserver.di.module.ModuleDao; import com.mageddo.dnsproxyserver.di.module.ModuleDockerClient; +import com.mageddo.dnsproxyserver.di.module.ModuleEager; import com.mageddo.dnsproxyserver.di.module.ModuleHttpMapper; import com.mageddo.dnsproxyserver.di.module.ModuleMain; import com.mageddo.dnsproxyserver.di.module.ModuleMap; @@ -38,13 +40,17 @@ ModuleStartup.class, ModuleMap.class, ModuleConfigDAO.class, - SolverRemoteModule.class + SolverRemoteModule.class, + ModuleEager.class }) public interface Context { static Context create() { final var context = DaggerContext.create(); CDI.setCDIProvider(() -> new CDIImpl(context)); + context.eagerBeans() + .forEach(Eager::run) + ; return context; } @@ -52,6 +58,8 @@ static Context create() { Set events(); + Set eagerBeans(); + default void start() { this.starter().start(); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java b/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java new file mode 100644 index 000000000..579aa8c35 --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java @@ -0,0 +1,24 @@ +package com.mageddo.dnsproxyserver.di.module; + +import com.mageddo.di.Eager; +import com.mageddo.dnsproxyserver.healthcheck.entrypoint.HealthCheckSignalEntrypoint; +import dagger.Module; +import dagger.Provides; +import dagger.multibindings.ElementsIntoSet; + +import javax.inject.Singleton; +import java.util.Set; + +@Module +public class ModuleEager { + @Provides + @Singleton + @ElementsIntoSet + Set beans( + HealthCheckSignalEntrypoint b1 + ) { + return Set.of( + + ); + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleStartup.java b/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleStartup.java index 9d778aea7..e335f05a7 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleStartup.java +++ b/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleStartup.java @@ -17,7 +17,9 @@ public interface ModuleStartup { @Provides @Singleton @ElementsIntoSet - static Set startupBeans(DnsConfigurators b1, EventListener b2, CircuitBreakerWatchDogScheduler b3){ + static Set startupBeans( + DnsConfigurators b1, EventListener b2, CircuitBreakerWatchDogScheduler b3 + ){ return Set.of(b1, b2, b3); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java index 207e022db..b497efd53 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java +++ b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java @@ -1,5 +1,6 @@ package com.mageddo.dnsproxyserver.healthcheck.entrypoint; +import com.mageddo.di.Eager; import com.mageddo.dnsproxyserver.healthcheck.HealthCheck; import lombok.extern.slf4j.Slf4j; import sun.misc.Signal; @@ -9,7 +10,7 @@ @Slf4j @Singleton -public class HealthCheckSignalEntrypoint { +public class HealthCheckSignalEntrypoint implements Eager { private static final String USER_DEFINED_SIGNAL = "USR1"; private final HealthCheck healthCheck; @@ -17,6 +18,10 @@ public class HealthCheckSignalEntrypoint { @Inject public HealthCheckSignalEntrypoint(HealthCheck healthCheck) { this.healthCheck = healthCheck; + } + + @Override + public void run() { this.safeRegisterHandler(); } @@ -32,5 +37,6 @@ void registerHandler() { Signal.handle(new Signal(USER_DEFINED_SIGNAL), sig -> { System.out.printf("dps.healthCheck.health=%b%n", this.healthCheck.isHealth()); }); + log.debug("status=healthCheckSignalRegistered, signal={}", USER_DEFINED_SIGNAL); } } diff --git a/src/main/java/com/mageddo/json/JsonUtils.java b/src/main/java/com/mageddo/json/JsonUtils.java index f5072158a..3b787af04 100644 --- a/src/main/java/com/mageddo/json/JsonUtils.java +++ b/src/main/java/com/mageddo/json/JsonUtils.java @@ -11,7 +11,6 @@ import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; - import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -175,4 +174,12 @@ static String readFirstLine() { } } + public static String prettyWriteValueAsString(Object v) { + try { + return prettyInstance().writeValueAsString(v); + } catch (JsonProcessingException e) { + throw new UncheckedIOException(e); + } + } + } diff --git a/src/test/java/com/mageddo/dnsproxyserver/di/ContextCompTest.java b/src/test/java/com/mageddo/dnsproxyserver/di/ContextCompTest.java new file mode 100644 index 000000000..ecee2d71c --- /dev/null +++ b/src/test/java/com/mageddo/dnsproxyserver/di/ContextCompTest.java @@ -0,0 +1,50 @@ +package com.mageddo.dnsproxyserver.di; + +import com.mageddo.di.Eager; +import com.mageddo.json.JsonUtils; +import lombok.SneakyThrows; +import org.junit.jupiter.api.Test; +import org.reflections.Reflections; +import org.reflections.scanners.Scanners; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ContextCompTest { + + Context context = Context.create(); + + @Test + @SneakyThrows + void mustRegisterAllEagerBeans(){ + + final var registeredBeanNames = this.findRegisteredBeanNames(); + final var existingEagerClasses = this.findExistingEagerClasses(); + + assertEquals( + JsonUtils.prettyWriteValueAsString(existingEagerClasses), + JsonUtils.prettyWriteValueAsString(registeredBeanNames) + ); + + } + + List findExistingEagerClasses() { + final var reflections = new Reflections("com.mageddo"); + return reflections.get(Scanners.SubTypes.of(Eager.class).asClass()) + .stream() + .map(Class::getName) + .sorted() + .toList(); + } + + private List findRegisteredBeanNames() { + return this.context + .eagerBeans() + .stream() + .map(Object::getClass) + .map(Class::getName) + .sorted() + .toList(); + } +} From 97dd0eb0fa9c6d8868923ac3407aaca8f89f978e Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 10:21:04 -0300 Subject: [PATCH 38/70] fixing test --- .../java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java b/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java index 579aa8c35..1d5a9b16e 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java +++ b/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java @@ -18,7 +18,7 @@ Set beans( HealthCheckSignalEntrypoint b1 ) { return Set.of( - + b1 ); } } From 37cf1a3844aaf6d26e0071fb7dc2220d93055ffa Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 12:15:14 -0300 Subject: [PATCH 39/70] creating a lot of features related to watch process execution --- .../mageddo/commons/exec/CommandLines.java | 113 +++++++++++++++--- .../commons/exec/DelegateOutputStream.java | 36 ++++++ .../commons/exec/NopResultHandler.java | 16 +++ .../com/mageddo/commons/exec/PipedStream.java | 42 +++++++ .../sandbox/BinaryFromGradleTestsSandbox.java | 15 ++- .../dnsproxyserver/sandbox/Instance.java | 26 ++++ .../java/com/mageddo/os/linux/kill/Kill.java | 18 +++ .../com/mageddo/wait/ExpectedConditions.java | 5 + .../wait/UnsatisfiedConditionException.java | 10 ++ src/main/java/com/mageddo/wait/Wait.java | 76 ++++++++++++ .../commons/exec/CommandLinesTest.java | 30 +++++ .../exec/DelegateOutputStreamTest.java | 26 ++++ .../mageddo/commons/exec/PipedStreamTest.java | 25 ++++ .../mageddo/dnsproxyserver/AppIntTest.java | 2 - .../BinaryFromGradleTestsSandboxIntTest.java | 19 --- .../templates/ConfigFlagArgsTemplates.java | 2 +- 16 files changed, 419 insertions(+), 42 deletions(-) create mode 100644 src/main/java/com/mageddo/commons/exec/DelegateOutputStream.java create mode 100644 src/main/java/com/mageddo/commons/exec/NopResultHandler.java create mode 100644 src/main/java/com/mageddo/commons/exec/PipedStream.java create mode 100644 src/main/java/com/mageddo/os/linux/kill/Kill.java create mode 100644 src/main/java/com/mageddo/wait/ExpectedConditions.java create mode 100644 src/main/java/com/mageddo/wait/UnsatisfiedConditionException.java create mode 100644 src/main/java/com/mageddo/wait/Wait.java create mode 100644 src/test/java/com/mageddo/commons/exec/CommandLinesTest.java create mode 100644 src/test/java/com/mageddo/commons/exec/DelegateOutputStreamTest.java create mode 100644 src/test/java/com/mageddo/commons/exec/PipedStreamTest.java delete mode 100644 src/test/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandboxIntTest.java diff --git a/src/main/java/com/mageddo/commons/exec/CommandLines.java b/src/main/java/com/mageddo/commons/exec/CommandLines.java index f8bf56caf..76d28a9ee 100644 --- a/src/main/java/com/mageddo/commons/exec/CommandLines.java +++ b/src/main/java/com/mageddo/commons/exec/CommandLines.java @@ -1,9 +1,13 @@ package com.mageddo.commons.exec; +import com.mageddo.commons.concurrent.Threads; +import com.mageddo.wait.Wait; import lombok.Builder; import lombok.Getter; import lombok.NonNull; +import lombok.SneakyThrows; import lombok.ToString; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.DaemonExecutor; import org.apache.commons.exec.ExecuteException; @@ -11,16 +15,23 @@ import org.apache.commons.exec.ExecuteWatchdog; import org.apache.commons.exec.Executor; import org.apache.commons.exec.PumpStreamHandler; +import org.apache.commons.lang3.Validate; +import java.io.BufferedReader; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; +import java.io.InputStreamReader; import java.io.UncheckedIOException; +import java.util.Map; +import java.util.function.Supplier; +@Slf4j public class CommandLines { public static Result exec(String commandLine, Object... args) { return exec(CommandLine.parse(String.format(commandLine, args)), - ExecuteWatchdog.INFINITE_TIMEOUT + ExecuteWatchdog.INFINITE_TIMEOUT ); } @@ -33,9 +44,10 @@ public static Result exec(CommandLine commandLine) { } public static Result exec(CommandLine commandLine, long timeout) { - final var out = new ByteArrayOutputStream(); - final var executor = new DaemonExecutor(); - final var streamHandler = new PumpStreamHandler(out); + + final var stream = new PipedStream(); + final var executor = createExecutor(); + final var streamHandler = new PumpStreamHandler(stream.getOut()); executor.setStreamHandler(streamHandler); int exitCode; try { @@ -47,17 +59,19 @@ public static Result exec(CommandLine commandLine, long timeout) { throw new UncheckedIOException(e); } return Result - .builder() - .executor(executor) - .out(out) - .exitCode(exitCode) - .build(); + .builder() + .executor(executor) + .stream(stream) + .out(stream.getBout()) + .exitCode(exitCode) + .processSupplier(executor::getProcess) + .build(); } public static Result exec(CommandLine commandLine, ExecuteResultHandler handler) { - final var out = new ByteArrayOutputStream(); - final var executor = new DaemonExecutor(); - final var streamHandler = new PumpStreamHandler(out); + final var stream = new PipedStream(); + final var executor = createExecutor(); + final var streamHandler = new PumpStreamHandler(stream.getOut()); executor.setStreamHandler(streamHandler); try { executor.setWatchdog(new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT)); @@ -70,10 +84,27 @@ public static Result exec(CommandLine commandLine, ExecuteResultHandler handler) return Result .builder() .executor(executor) - .out(out) + .processSupplier(executor::getProcess) + .out(stream.getBout()) + .stream(stream) .build(); } + private static ProcessAccessibleDaemonExecutor createExecutor() { + return new ProcessAccessibleDaemonExecutor(); + } + + @Getter + static class ProcessAccessibleDaemonExecutor extends DaemonExecutor { + + private Process process = null; + + @Override + protected Process launch(CommandLine command, Map env, File dir) throws IOException { + return this.process = super.launch(command, env, dir); + } + } + @Getter @Builder @ToString(of = {"exitCode"}) @@ -82,11 +113,36 @@ public static class Result { @NonNull private Executor executor; + @NonNull + private PipedStream stream; + @NonNull private ByteArrayOutputStream out; + @NonNull + private Supplier processSupplier; + private Integer exitCode; + public void watchOutputInDaemonThread() { + final var thread = Threads.createDaemonThread(() -> { + final var bf = new BufferedReader(new InputStreamReader(this.stream.getPipedInputStream())); + while (true) { + try { + final var line = bf.readLine(); + if (line == null) { + log.debug("status=outputEnded"); + break; + } + log.debug(">>> {}", line); + } catch (IOException e) { + + } + } + }); + thread.start(); + } + public String getOutAsString() { return this.out.toString(); } @@ -100,9 +156,36 @@ public Result checkExecution() { public String toString(boolean printOut) { return String.format( - "code=%d, out=%s", - this.exitCode, printOut ? this.getOutAsString() : null + "code=%d, out=%s", + this.exitCode, printOut ? this.getOutAsString() : null ); } + + @SneakyThrows + public Process getProcess() { + return this.processSupplier.get(); + } + + public Long getProcessId() { + final var process = this.getProcess(); + if (process == null) { + return null; + } + return process.pid(); + } + + public void waitProcessToFinish() { + new Wait<>() + .infinityTimeout() + .ignoreException(IllegalArgumentException.class) + .until(() -> { + Validate.isTrue(this.isProcessFinished(), "Process not finished yet"); + return true; + }); + } + + private boolean isProcessFinished() { + return getProcess() != null && !getProcess().isAlive(); + } } } diff --git a/src/main/java/com/mageddo/commons/exec/DelegateOutputStream.java b/src/main/java/com/mageddo/commons/exec/DelegateOutputStream.java new file mode 100644 index 000000000..0fddc4ffe --- /dev/null +++ b/src/main/java/com/mageddo/commons/exec/DelegateOutputStream.java @@ -0,0 +1,36 @@ +package com.mageddo.commons.exec; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; +import java.util.stream.Stream; + +public class DelegateOutputStream extends OutputStream { + + private final List delegateOuts; + + public DelegateOutputStream(OutputStream... delegateOuts) { + this.delegateOuts = Stream.of(delegateOuts).toList(); + } + + public DelegateOutputStream(List delegateOuts) { + this.delegateOuts = delegateOuts; + } + + @Override + public void write(int b) throws IOException { + for (final var delegateOut : this.delegateOuts) { + delegateOut.write(b); + } + } + + @Override + public void close() throws IOException { + for (final var out : this.delegateOuts) { + try { + out.close(); + } catch (IOException e) { + } + } + } +} diff --git a/src/main/java/com/mageddo/commons/exec/NopResultHandler.java b/src/main/java/com/mageddo/commons/exec/NopResultHandler.java new file mode 100644 index 000000000..382d65b74 --- /dev/null +++ b/src/main/java/com/mageddo/commons/exec/NopResultHandler.java @@ -0,0 +1,16 @@ +package com.mageddo.commons.exec; + +import org.apache.commons.exec.ExecuteException; +import org.apache.commons.exec.ExecuteResultHandler; + +public class NopResultHandler implements ExecuteResultHandler { + @Override + public void onProcessComplete(int exitValue) { + + } + + @Override + public void onProcessFailed(ExecuteException e) { + + } +} diff --git a/src/main/java/com/mageddo/commons/exec/PipedStream.java b/src/main/java/com/mageddo/commons/exec/PipedStream.java new file mode 100644 index 000000000..42a2971d0 --- /dev/null +++ b/src/main/java/com/mageddo/commons/exec/PipedStream.java @@ -0,0 +1,42 @@ +package com.mageddo.commons.exec; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.io.UncheckedIOException; + +public class PipedStream { + + private final PipedInputStream pipedInputStream; + private final ByteArrayOutputStream bout; + private final DelegateOutputStream out; + + public PipedStream() { + try { + this.pipedInputStream = new PipedInputStream(); + final var pout = new PipedOutputStream(this.pipedInputStream); + this.bout = new ByteArrayOutputStream(); + this.out = new DelegateOutputStream(this.bout, pout); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public OutputStream getOut() { + return this.out; + } + + public ByteArrayOutputStream getBout() { + return bout; + } + + public PipedInputStream getPipedInputStream() { + return this.pipedInputStream; + } + + public void close() throws IOException { + this.out.close(); + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java index 098e0b3bf..4bda68069 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -1,13 +1,13 @@ package com.mageddo.dnsproxyserver.sandbox; -import com.mageddo.commons.concurrent.Threads; import com.mageddo.commons.exec.CommandLines; +import com.mageddo.wait.Wait; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.ExecuteException; import org.apache.commons.exec.ExecuteResultHandler; -import java.time.Duration; - +@Slf4j public class BinaryFromGradleTestsSandbox { public Instance run(String[] args) { final var javaCommandPath = findJavaCommand(); @@ -41,8 +41,13 @@ private static String findJavaCommand() { } private void waitForStartup(Instance instance) { - Threads.sleep(Duration.ofSeconds(2)); - System.out.println(instance.getResult().getOutAsString()); + instance.getResult().watchOutputInDaemonThread(); + new Wait() + .ignoreException(IllegalArgumentException.class) + .until(() -> { + instance.sendHealthCheckSignal(); + return null; + }); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java index 01e9dfa82..8a1629ac3 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java @@ -1,10 +1,14 @@ package com.mageddo.dnsproxyserver.sandbox; import com.mageddo.commons.exec.CommandLines; +import com.mageddo.os.linux.kill.Kill; import lombok.Builder; import lombok.NonNull; import lombok.Value; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.Validate; +@Slf4j @Value @Builder public class Instance { @@ -18,4 +22,26 @@ public static Instance of(CommandLines.Result result) { .build() ; } + + public void sendHealthCheckSignal() { + this.sendHealthCheckSignalValidatingResult(); + this.validateIsHealth(); + } + + private void validateIsHealth() { + final var out = this.getResult().getOutAsString(); + final var isHealth = out.contains("dps.healthCheck.health=true"); + Validate.isTrue(isHealth, "App not health yet, content=%s", out); + } + + private void sendHealthCheckSignalValidatingResult() { + final var processId = this.getProcessId(); + Validate.isTrue(processId != null, "Process not started yet"); + log.debug("is alive: {}", this.result.getProcess().isAlive()); + Kill.sendSignal(10, processId); + } + + private Long getProcessId() { + return this.result.getProcessId(); + } } diff --git a/src/main/java/com/mageddo/os/linux/kill/Kill.java b/src/main/java/com/mageddo/os/linux/kill/Kill.java new file mode 100644 index 000000000..bb4b6e376 --- /dev/null +++ b/src/main/java/com/mageddo/os/linux/kill/Kill.java @@ -0,0 +1,18 @@ +package com.mageddo.os.linux.kill; + +import com.mageddo.commons.exec.CommandLines; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.exec.CommandLine; + +@Slf4j +public class Kill { + public static void sendSignal(int signal, long pid) { + final var result = CommandLines.exec( + new CommandLine("kill") + .addArgument("-" + signal) + .addArgument(pid + "") + ); + result.checkExecution(); + log.debug("status=signalSentWithSuccess, signal={}, pid={}", signal, pid); + } +} diff --git a/src/main/java/com/mageddo/wait/ExpectedConditions.java b/src/main/java/com/mageddo/wait/ExpectedConditions.java new file mode 100644 index 000000000..65da42baf --- /dev/null +++ b/src/main/java/com/mageddo/wait/ExpectedConditions.java @@ -0,0 +1,5 @@ +package com.mageddo.wait; + +public class ExpectedConditions { + +} diff --git a/src/main/java/com/mageddo/wait/UnsatisfiedConditionException.java b/src/main/java/com/mageddo/wait/UnsatisfiedConditionException.java new file mode 100644 index 000000000..c99225925 --- /dev/null +++ b/src/main/java/com/mageddo/wait/UnsatisfiedConditionException.java @@ -0,0 +1,10 @@ +package com.mageddo.wait; + +public class UnsatisfiedConditionException extends RuntimeException { + public UnsatisfiedConditionException() { + } + + public UnsatisfiedConditionException(Throwable t) { + super(t); + } +} diff --git a/src/main/java/com/mageddo/wait/Wait.java b/src/main/java/com/mageddo/wait/Wait.java new file mode 100644 index 000000000..1dcafb412 --- /dev/null +++ b/src/main/java/com/mageddo/wait/Wait.java @@ -0,0 +1,76 @@ +package com.mageddo.wait; + +import com.mageddo.commons.concurrent.Threads; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.time.StopWatch; + +import java.time.Duration; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; + +@Accessors(chain = true, fluent = true) +public class Wait { + + @Setter + private Duration timeout = Duration.ofSeconds(1); + @Setter + private Duration pollingEvery = Duration.ofMillis(1000 / 60); + + private final T obj; + private Set> ignoredExceptions = new HashSet<>(); + private Throwable lastException = null; + + public Wait() { + this.obj = null; + } + + public Wait(T obj) { + this.obj = obj; + } + + public R until(Supplier sup) { + return this.until((obj) -> sup.get()); + } + + public R until(Function fn) { + final var stopWatch = StopWatch.createStarted(); + while (this.shouldContinue(stopWatch)) { + try { + final var result = fn.apply(this.obj); + if (result != null) { + return result; + } + } catch (final Exception e) { + if (!this.ignoredExceptions.contains(e.getClass())) { + throw e; + } else { + this.lastException = e; + } + } + + Threads.sleep(this.pollingEvery); + } + if(this.lastException != null){ + throw new UnsatisfiedConditionException(this.lastException); + } + throw new UnsatisfiedConditionException(); + } + + private boolean shouldContinue(StopWatch stopWatch) { + final var notInterrupted = !Thread.currentThread().isInterrupted(); + return notInterrupted && stopWatch.getTime() < this.timeout.toMillis(); + } + + public Wait ignoreException(Class t) { + this.ignoredExceptions.add(t); + return this; + } + + public Wait infinityTimeout() { + this.timeout = Duration.ofMillis(Long.MAX_VALUE); + return this; + } +} diff --git a/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java b/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java new file mode 100644 index 000000000..d5d711762 --- /dev/null +++ b/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java @@ -0,0 +1,30 @@ +package com.mageddo.commons.exec; + +import org.apache.commons.exec.CommandLine; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class CommandLinesTest { + + @Test + void mustExecuteAndPrintOutputConcurrently() { + + final var result = CommandLines.exec( + new CommandLine("bash") + .addArgument("-c") + .addArgument("echo hi && sleep 0.2 && echo hi2", false), + new NopResultHandler() + ); + + result.watchOutputInDaemonThread(); + + result.waitProcessToFinish(); + + final var expectedOut = """ + hi + hi2 + """; + assertEquals(expectedOut, result.getOutAsString()); + } +} diff --git a/src/test/java/com/mageddo/commons/exec/DelegateOutputStreamTest.java b/src/test/java/com/mageddo/commons/exec/DelegateOutputStreamTest.java new file mode 100644 index 000000000..86b07f4ca --- /dev/null +++ b/src/test/java/com/mageddo/commons/exec/DelegateOutputStreamTest.java @@ -0,0 +1,26 @@ +package com.mageddo.commons.exec; + +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +class DelegateOutputStreamTest { + @Test + void mustWriteToTheTwoOuts() throws IOException { + + final var out1 = new ByteArrayOutputStream(); + final var out2 = new ByteArrayOutputStream(); + final var arr = new byte[]{1, 2, 3}; + + // act + final var delegateOut = new DelegateOutputStream(out1, out2); + delegateOut.write(arr); + + // assert + assertArrayEquals(arr, out1.toByteArray()); + assertArrayEquals(arr, out2.toByteArray()); + } +} diff --git a/src/test/java/com/mageddo/commons/exec/PipedStreamTest.java b/src/test/java/com/mageddo/commons/exec/PipedStreamTest.java new file mode 100644 index 000000000..a797bde2b --- /dev/null +++ b/src/test/java/com/mageddo/commons/exec/PipedStreamTest.java @@ -0,0 +1,25 @@ +package com.mageddo.commons.exec; + +import org.junit.jupiter.api.Test; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +class PipedStreamTest { + + @Test + void mustWriteToOutAndBeAbleToReadWhatIsBeingWritten() throws IOException { + // arrange + final var bytes = new byte[]{1, 2, 3}; + + // act + final var stream = new PipedStream(); + stream.getOut().write(bytes); + stream.close(); + + // assert + assertArrayEquals(bytes, stream.getBout().toByteArray()); + assertArrayEquals(bytes, stream.getPipedInputStream().readAllBytes()); + } +} diff --git a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java index b43c2721f..d0871ea23 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java @@ -12,7 +12,6 @@ import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.xbill.DNS.Message; import testing.templates.ConfigFlagArgsTemplates; @@ -57,7 +56,6 @@ void appMustStartAndQuerySampleWithSuccessFromLocalDbSolver() { } } - @Disabled @Test void mustQueryRemoteSolverPassingThroughAllModulesAndGetSuccess() { diff --git a/src/test/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandboxIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandboxIntTest.java deleted file mode 100644 index ff5e1586e..000000000 --- a/src/test/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandboxIntTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.mageddo.dnsproxyserver.sandbox; - -import org.junit.jupiter.api.Test; - -class BinaryFromGradleTestsSandboxIntTest { - - BinaryFromGradleTestsSandbox sandbox = new BinaryFromGradleTestsSandbox(); - - @Test - void mustRunFromGradleTests(){ - // arrange - final var args = new String[]{}; - - // act - this.sandbox.run(args); - - // assert - } -} diff --git a/src/test/java/testing/templates/ConfigFlagArgsTemplates.java b/src/test/java/testing/templates/ConfigFlagArgsTemplates.java index 492afbb29..af2e3b185 100644 --- a/src/test/java/testing/templates/ConfigFlagArgsTemplates.java +++ b/src/test/java/testing/templates/ConfigFlagArgsTemplates.java @@ -41,7 +41,7 @@ private static Path makeConfigFile(String host) { "envs": [ { "name": "", - "hostnames": + "hostnames": [ { "type": "A", "hostname": "%s", From 8564b43db33ae167e58591012a8538449aabe44a Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 13:13:29 -0300 Subject: [PATCH 40/70] new way to excute command line and specify stream handler --- .../mageddo/commons/exec/CommandLines.java | 58 +++++++++++++++++-- .../java/com/mageddo/dnsproxyserver/App.java | 2 +- .../dnsproxyserver/di/module/ModuleEager.java | 5 +- .../HealthCheckSignalEntrypoint.java | 14 ++--- .../HealthCheckStreamEntrypoint.java | 18 ++++++ .../in/entrypoint/InputStreamEntrypoint.java | 58 +++++++++++++++++++ .../sandbox/BinaryFromGradleTestsSandbox.java | 17 ++---- .../dnsproxyserver/sandbox/Instance.java | 15 ++++- .../commons/exec/CommandLinesTest.java | 2 +- 9 files changed, 157 insertions(+), 32 deletions(-) create mode 100644 src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckStreamEntrypoint.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/in/entrypoint/InputStreamEntrypoint.java diff --git a/src/main/java/com/mageddo/commons/exec/CommandLines.java b/src/main/java/com/mageddo/commons/exec/CommandLines.java index 76d28a9ee..d8b941ce4 100644 --- a/src/main/java/com/mageddo/commons/exec/CommandLines.java +++ b/src/main/java/com/mageddo/commons/exec/CommandLines.java @@ -1,12 +1,12 @@ package com.mageddo.commons.exec; -import com.mageddo.commons.concurrent.Threads; import com.mageddo.wait.Wait; import lombok.Builder; import lombok.Getter; import lombok.NonNull; import lombok.SneakyThrows; import lombok.ToString; +import lombok.Value; import lombok.extern.slf4j.Slf4j; import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.DaemonExecutor; @@ -90,6 +90,37 @@ public static Result exec(CommandLine commandLine, ExecuteResultHandler handler) .build(); } + public static Result exec(Request request) { + final var stream = new PipedStream(); + final var executor = createExecutor(); + executor.setStreamHandler(request.getStreamHandler()); + Integer exitCode = null; + try { + executor.setWatchdog(new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT)); + if (request.getHandler() != null) { + executor.execute(request.getCommandLine(), request.getHandler()); + } else { + exitCode = executor.execute(request.getCommandLine()); + } + } catch (ExecuteException e) { + if(request.getHandler() != null){ + request.getHandler().onProcessFailed(e); + } else { + exitCode = e.getExitValue(); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + return Result + .builder() + .executor(executor) + .processSupplier(executor::getProcess) + .out(stream.getBout()) + .stream(stream) + .exitCode(exitCode) + .build(); + } + private static ProcessAccessibleDaemonExecutor createExecutor() { return new ProcessAccessibleDaemonExecutor(); } @@ -105,6 +136,15 @@ protected Process launch(CommandLine command, Map env, File dir) } } + + @Value + @Builder + public static class Request { + CommandLine commandLine; + ExecuteResultHandler handler; + PumpStreamHandler streamHandler; + } + @Getter @Builder @ToString(of = {"exitCode"}) @@ -125,7 +165,7 @@ public static class Result { private Integer exitCode; public void watchOutputInDaemonThread() { - final var thread = Threads.createDaemonThread(() -> { + final var task = (Runnable) () -> { final var bf = new BufferedReader(new InputStreamReader(this.stream.getPipedInputStream())); while (true) { try { @@ -139,8 +179,10 @@ public void watchOutputInDaemonThread() { } } - }); - thread.start(); + }; + Thread + .ofVirtual() + .start(task); } public String getOutAsString() { @@ -187,5 +229,13 @@ public void waitProcessToFinish() { private boolean isProcessFinished() { return getProcess() != null && !getProcess().isAlive(); } + + public Integer getProcessExitCodeWhenAvailable() { + try { + return getProcess().exitValue(); + } catch (IllegalThreadStateException e) { + return null; + } + } } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/App.java b/src/main/java/com/mageddo/dnsproxyserver/App.java index 3e39ac46b..2f5469000 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/App.java +++ b/src/main/java/com/mageddo/dnsproxyserver/App.java @@ -82,7 +82,7 @@ void setupLogs() { } void startContext() { - createContext(); + this.createContext(); // start webserver // start dns server diff --git a/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java b/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java index 1d5a9b16e..9169a64c0 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java +++ b/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java @@ -2,6 +2,7 @@ import com.mageddo.di.Eager; import com.mageddo.dnsproxyserver.healthcheck.entrypoint.HealthCheckSignalEntrypoint; +import com.mageddo.dnsproxyserver.in.entrypoint.InputStreamEntrypoint; import dagger.Module; import dagger.Provides; import dagger.multibindings.ElementsIntoSet; @@ -15,10 +16,10 @@ public class ModuleEager { @Singleton @ElementsIntoSet Set beans( - HealthCheckSignalEntrypoint b1 + HealthCheckSignalEntrypoint b1, InputStreamEntrypoint b2 ) { return Set.of( - b1 + b1, b2 ); } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java index b497efd53..aa55fe52a 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java +++ b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java @@ -1,7 +1,7 @@ package com.mageddo.dnsproxyserver.healthcheck.entrypoint; import com.mageddo.di.Eager; -import com.mageddo.dnsproxyserver.healthcheck.HealthCheck; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import sun.misc.Signal; @@ -10,15 +10,11 @@ @Slf4j @Singleton +@RequiredArgsConstructor(onConstructor = @__({@Inject})) public class HealthCheckSignalEntrypoint implements Eager { private static final String USER_DEFINED_SIGNAL = "USR1"; - private final HealthCheck healthCheck; - - @Inject - public HealthCheckSignalEntrypoint(HealthCheck healthCheck) { - this.healthCheck = healthCheck; - } + private final HealthCheckStreamEntrypoint streamEntrypoint; @Override public void run() { @@ -34,9 +30,7 @@ void safeRegisterHandler() { } void registerHandler() { - Signal.handle(new Signal(USER_DEFINED_SIGNAL), sig -> { - System.out.printf("dps.healthCheck.health=%b%n", this.healthCheck.isHealth()); - }); + Signal.handle(new Signal(USER_DEFINED_SIGNAL), sig -> this.streamEntrypoint.printHealthCheck()); log.debug("status=healthCheckSignalRegistered, signal={}", USER_DEFINED_SIGNAL); } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckStreamEntrypoint.java b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckStreamEntrypoint.java new file mode 100644 index 000000000..c482959a4 --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckStreamEntrypoint.java @@ -0,0 +1,18 @@ +package com.mageddo.dnsproxyserver.healthcheck.entrypoint; + +import com.mageddo.dnsproxyserver.healthcheck.HealthCheck; +import lombok.RequiredArgsConstructor; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +@RequiredArgsConstructor(onConstructor = @__({@Inject})) +public class HealthCheckStreamEntrypoint { + + private final HealthCheck healthCheck; + + public void printHealthCheck() { + System.out.printf("dps.healthCheck.health=%b%n", this.healthCheck.isHealth()); + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/in/entrypoint/InputStreamEntrypoint.java b/src/main/java/com/mageddo/dnsproxyserver/in/entrypoint/InputStreamEntrypoint.java new file mode 100644 index 000000000..8e7338b90 --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/in/entrypoint/InputStreamEntrypoint.java @@ -0,0 +1,58 @@ +package com.mageddo.dnsproxyserver.in.entrypoint; + +import com.mageddo.commons.concurrent.Threads; +import com.mageddo.di.Eager; +import com.mageddo.dnsproxyserver.healthcheck.entrypoint.HealthCheckStreamEntrypoint; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.NoSuchElementException; +import java.util.Scanner; + +@Slf4j +@Singleton +@RequiredArgsConstructor(onConstructor = @__({@Inject})) +public class InputStreamEntrypoint implements Eager { + + private final HealthCheckStreamEntrypoint healthCheckStreamEntrypoint; + private boolean inShell; + + @Override + public void run() { + Thread.ofVirtual() + .start(this::readInputStream) + ; + } + + private void readInputStream() { + log.debug("status=scanningInputStream"); + final var scanner = new Scanner(System.in); + while (true) { + final var line = safeReadLine(scanner); + if (line == null) { + break; + } + this.checkHealthCheck(line); + Threads.sleep(1000 / 15); + } + } + + private static String safeReadLine(Scanner scanner) { + try { + return scanner.nextLine(); + } catch (NoSuchElementException e) { + return null; + } + } + + private void checkHealthCheck(String line) { + if (line.equals("shell")) { + this.inShell = true; + } + if (this.inShell && line.equals("dps.healthCheck.health")) { + this.healthCheckStreamEntrypoint.printHealthCheck(); + } + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java index 4bda68069..11994b4a9 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -1,11 +1,10 @@ package com.mageddo.dnsproxyserver.sandbox; import com.mageddo.commons.exec.CommandLines; +import com.mageddo.commons.exec.NopResultHandler; import com.mageddo.wait.Wait; import lombok.extern.slf4j.Slf4j; import org.apache.commons.exec.CommandLine; -import org.apache.commons.exec.ExecuteException; -import org.apache.commons.exec.ExecuteResultHandler; @Slf4j public class BinaryFromGradleTestsSandbox { @@ -18,15 +17,7 @@ public Instance run(String[] args) { .addArgument(executablePath.toFile().toString()) .addArguments(args); - final var result = CommandLines.exec(commandLine, new ExecuteResultHandler() { - public void onProcessComplete(int exitValue) { - - } - - public void onProcessFailed(ExecuteException e) { - - } - }); + final var result = CommandLines.exec(commandLine, new NopResultHandler()); final var instance = Instance.of(result); this.waitForStartup(instance); return instance; @@ -45,8 +36,8 @@ private void waitForStartup(Instance instance) { new Wait() .ignoreException(IllegalArgumentException.class) .until(() -> { - instance.sendHealthCheckSignal(); - return null; + instance.sendHealthCheckStreamCommand(); + return true; }); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java index 8a1629ac3..f8db6a1b7 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java @@ -23,6 +23,11 @@ public static Instance of(CommandLines.Result result) { ; } + public void sendHealthCheckStreamCommand() { + this.sendHealthCheckStreamCommandValidatingResult(); + this.validateIsHealth(); + } + public void sendHealthCheckSignal() { this.sendHealthCheckSignalValidatingResult(); this.validateIsHealth(); @@ -37,7 +42,15 @@ private void validateIsHealth() { private void sendHealthCheckSignalValidatingResult() { final var processId = this.getProcessId(); Validate.isTrue(processId != null, "Process not started yet"); - log.debug("is alive: {}", this.result.getProcess().isAlive()); + log.trace("is alive: {}, exitcode={}", this.result.getProcess().isAlive(), this.result.getProcessExitCodeWhenAvailable()); + Kill.sendSignal(10, processId); + } + + private void sendHealthCheckStreamCommandValidatingResult() { + this.result.getExecutor().getStreamHandler().setProcessErrorStream(); + final var processId = this.getProcessId(); + Validate.isTrue(processId != null, "Process not started yet"); + log.trace("is alive: {}, exitcode={}", this.result.getProcess().isAlive(), this.result.getProcessExitCodeWhenAvailable()); Kill.sendSignal(10, processId); } diff --git a/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java b/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java index d5d711762..dd3ba4afb 100644 --- a/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java +++ b/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java @@ -11,7 +11,7 @@ class CommandLinesTest { void mustExecuteAndPrintOutputConcurrently() { final var result = CommandLines.exec( - new CommandLine("bash") + new CommandLine("sh") .addArgument("-c") .addArgument("echo hi && sleep 0.2 && echo hi2", false), new NopResultHandler() From cee15ac74a25d1c5fbc9e81d8b191f5ab9df8274 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 13:59:34 -0300 Subject: [PATCH 41/70] killing processes after test execution --- .../mageddo/commons/exec/CommandLines.java | 7 ++ .../commons/exec/ProcessesWatchDog.java | 49 ++++++++++++ .../java/com/mageddo/dns/utils/Messages.java | 4 + .../sandbox/BinaryFromGradleTestsSandbox.java | 15 +--- .../dnsproxyserver/sandbox/Instance.java | 16 +--- .../mageddo/dnsproxyserver/AppIntTest.java | 44 +++++++++-- .../templates/ConfigFlagArgsTemplates.java | 78 ++++++++++++++++--- 7 files changed, 167 insertions(+), 46 deletions(-) create mode 100644 src/main/java/com/mageddo/commons/exec/ProcessesWatchDog.java diff --git a/src/main/java/com/mageddo/commons/exec/CommandLines.java b/src/main/java/com/mageddo/commons/exec/CommandLines.java index d8b941ce4..057ddd386 100644 --- a/src/main/java/com/mageddo/commons/exec/CommandLines.java +++ b/src/main/java/com/mageddo/commons/exec/CommandLines.java @@ -53,6 +53,7 @@ public static Result exec(CommandLine commandLine, long timeout) { try { executor.setWatchdog(new ExecuteWatchdog(timeout)); exitCode = executor.execute(commandLine); + registerProcessWatch(executor); } catch (ExecuteException e) { exitCode = e.getExitValue(); } catch (IOException e) { @@ -68,6 +69,10 @@ public static Result exec(CommandLine commandLine, long timeout) { .build(); } + private static void registerProcessWatch(ProcessAccessibleDaemonExecutor executor) { + ProcessesWatchDog.instance().watch(executor::getProcess); + } + public static Result exec(CommandLine commandLine, ExecuteResultHandler handler) { final var stream = new PipedStream(); final var executor = createExecutor(); @@ -76,6 +81,7 @@ public static Result exec(CommandLine commandLine, ExecuteResultHandler handler) try { executor.setWatchdog(new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT)); executor.execute(commandLine, handler); + registerProcessWatch(executor); } catch (ExecuteException e) { handler.onProcessFailed(e); } catch (IOException e) { @@ -99,6 +105,7 @@ public static Result exec(Request request) { executor.setWatchdog(new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT)); if (request.getHandler() != null) { executor.execute(request.getCommandLine(), request.getHandler()); + registerProcessWatch(executor); } else { exitCode = executor.execute(request.getCommandLine()); } diff --git a/src/main/java/com/mageddo/commons/exec/ProcessesWatchDog.java b/src/main/java/com/mageddo/commons/exec/ProcessesWatchDog.java new file mode 100644 index 000000000..9fbb57388 --- /dev/null +++ b/src/main/java/com/mageddo/commons/exec/ProcessesWatchDog.java @@ -0,0 +1,49 @@ +package com.mageddo.commons.exec; + +import com.mageddo.commons.lang.Singletons; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Supplier; + +@Slf4j +public class ProcessesWatchDog { + + private List> processes = new ArrayList<>(); + + public static ProcessesWatchDog instance() { + return Singletons.createOrGet(ProcessesWatchDog.class, ProcessesWatchDog::new); + } + + public void watch(Supplier sup) { + this.processes.add(sup); + } + + public void watch(Process process) { + this.processes.add(() -> process); + } + + public void killAllProcesses() { + final var validProcesses = this.findValidProcesses(); + + log.debug("status=killing all processes, processes={}, valid={}", this.processes.size(), validProcesses.size()); + + validProcesses.forEach(process -> { + try { + process.destroy(); + log.trace("status=killed, pid={}", process.pid()); + } catch (Exception e) { + log.warn("status=unable to destroy, processId={}, msg={}", process.pid(), e.getMessage(), e); + } + }); + } + + private List findValidProcesses() { + return this.processes.stream() + .map(Supplier::get) + .filter(Objects::nonNull) + .toList(); + } +} diff --git a/src/main/java/com/mageddo/dns/utils/Messages.java b/src/main/java/com/mageddo/dns/utils/Messages.java index 8780eef15..e4827453d 100644 --- a/src/main/java/com/mageddo/dns/utils/Messages.java +++ b/src/main/java/com/mageddo/dns/utils/Messages.java @@ -301,4 +301,8 @@ public static HostnameQuery toHostnameQuery(Message query) { public static boolean isSuccess(Message res) { return res.getRcode() == Rcode.NOERROR; } + + public static String findAnswerRawIP(Message res) { + return findFirstAnswerRecord(res).rdataToString(); + } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java index 11994b4a9..09682fa27 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -2,7 +2,6 @@ import com.mageddo.commons.exec.CommandLines; import com.mageddo.commons.exec.NopResultHandler; -import com.mageddo.wait.Wait; import lombok.extern.slf4j.Slf4j; import org.apache.commons.exec.CommandLine; @@ -18,9 +17,7 @@ public Instance run(String[] args) { .addArguments(args); final var result = CommandLines.exec(commandLine, new NopResultHandler()); - final var instance = Instance.of(result); - this.waitForStartup(instance); - return instance; + return Instance.of(result); } private static String findJavaCommand() { @@ -31,15 +28,5 @@ private static String findJavaCommand() { ; } - private void waitForStartup(Instance instance) { - instance.getResult().watchOutputInDaemonThread(); - new Wait() - .ignoreException(IllegalArgumentException.class) - .until(() -> { - instance.sendHealthCheckStreamCommand(); - return true; - }); - } - } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java index f8db6a1b7..cc9f0b598 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java @@ -23,10 +23,6 @@ public static Instance of(CommandLines.Result result) { ; } - public void sendHealthCheckStreamCommand() { - this.sendHealthCheckStreamCommandValidatingResult(); - this.validateIsHealth(); - } public void sendHealthCheckSignal() { this.sendHealthCheckSignalValidatingResult(); @@ -46,15 +42,11 @@ private void sendHealthCheckSignalValidatingResult() { Kill.sendSignal(10, processId); } - private void sendHealthCheckStreamCommandValidatingResult() { - this.result.getExecutor().getStreamHandler().setProcessErrorStream(); - final var processId = this.getProcessId(); - Validate.isTrue(processId != null, "Process not started yet"); - log.trace("is alive: {}, exitcode={}", this.result.getProcess().isAlive(), this.result.getProcessExitCodeWhenAvailable()); - Kill.sendSignal(10, processId); - } - private Long getProcessId() { return this.result.getProcessId(); } + + public void watchOutputInDaemonThread() { + getResult().watchOutputInDaemonThread(); + } } diff --git a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java index d0871ea23..efab6375b 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java @@ -1,14 +1,18 @@ package com.mageddo.dnsproxyserver; import com.mageddo.commons.concurrent.Threads; +import com.mageddo.commons.exec.ProcessesWatchDog; import com.mageddo.dns.utils.Messages; import com.mageddo.dnsproxyserver.config.application.Configs; +import com.mageddo.dnsproxyserver.sandbox.Instance; import com.mageddo.dnsproxyserver.sandbox.Sandbox; import com.mageddo.dnsproxyserver.server.Starter; import com.mageddo.dnsproxyserver.solver.SimpleResolver; import com.mageddo.dnsproxyserver.utils.Ips; +import com.mageddo.net.IpAddr; import com.mageddo.utils.Executors; import lombok.SneakyThrows; +import lombok.Value; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; @@ -20,6 +24,7 @@ import java.util.Arrays; import java.util.concurrent.ExecutorService; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @Slf4j @@ -34,6 +39,7 @@ void beforeEach() { @AfterAll static void afterAll() { Starter.setMustStartFlagActive(false); + ProcessesWatchDog.instance().killAllProcesses(); } @Test @@ -63,26 +69,29 @@ void mustQueryRemoteSolverPassingThroughAllModulesAndGetSuccess() { try (final var executor = Executors.newThreadExecutor()) { - // fixme must configure the remote server created as a remote for this one - final var clientApp = buildClientAppAndWait(executor); - buildServerAppAndWait(executor, hostToQuery); + final var serverAppConfig = buildAndStartServerApp(hostToQuery); + final var clientApp = buildClientAppAndWait(executor, serverAppConfig.getDnsServerPort()); final var port = clientApp.getDnsServerPort(); final var res = queryStartedServer(port, hostToQuery); assertTrue(Messages.isSuccess(res)); + assertEquals("192.168.0.1", Messages.findAnswerRawIP(res)); } } - private static App buildClientAppAndWait(ExecutorService executor) { - return buildAppAndWait(executor, ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDns()); + private static App buildClientAppAndWait(ExecutorService executor, Integer serverPort) { + final var remoteAddr = IpAddr.of("127.0.0.1", serverPort); + return buildAppAndWait(executor, ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDnsUsingRemote(remoteAddr)); } - private static void buildServerAppAndWait(ExecutorService executor, String hostToQuery) { - final var args = ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(hostToQuery); - final var instance = Sandbox.runFromGradleTests(args); + private static Result buildAndStartServerApp(String hostToQuery) { + final var config = ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(hostToQuery); + final var instance = Sandbox.runFromGradleTests(config.args()); + instance.watchOutputInDaemonThread(); + return Result.of(config, instance); } private static App buildAppAndWait(ExecutorService executor, final String[] params) { @@ -99,4 +108,23 @@ static Message queryStartedServer(Integer port, String host) { final var dnsClient = new SimpleResolver(dnsServerAddress); return dnsClient.send(Messages.aQuestion(host)); } + + @Value + static class Result { + + private final ConfigFlagArgsTemplates.Config config; + private final Instance instance; + + public static Result of(ConfigFlagArgsTemplates.Config config, Instance instance) { + return new Result(config, instance); + } + + public Integer getDnsServerPort() { + return this.config.getDnsServerPort(); + } + + public void watchInstanceOutputInDaemonThread() { + this.getInstance().watchOutputInDaemonThread(); + } + } } diff --git a/src/test/java/testing/templates/ConfigFlagArgsTemplates.java b/src/test/java/testing/templates/ConfigFlagArgsTemplates.java index af2e3b185..d88442808 100644 --- a/src/test/java/testing/templates/ConfigFlagArgsTemplates.java +++ b/src/test/java/testing/templates/ConfigFlagArgsTemplates.java @@ -1,48 +1,68 @@ package testing.templates; +import com.mageddo.dnsproxyserver.config.dataprovider.JsonConfigs; +import com.mageddo.dnsproxyserver.config.dataprovider.vo.ConfigJson; +import com.mageddo.net.IpAddr; import com.mageddo.net.SocketUtils; +import lombok.Builder; import lombok.SneakyThrows; +import lombok.Value; +import lombok.experimental.Accessors; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; public class ConfigFlagArgsTemplates { - public static String[] withRandomPortsAndNotAsDefaultDns() { - final var webServerPort = SocketUtils.findRandomFreePort(); - final var dnsServerPort = SocketUtils.findRandomFreePort(); + public static String[] withRandomPortsAndNotAsDefaultDnsUsingRemote(IpAddr addr) { + final var configPath = makeConfigFileRandomPortAndCustomRemote(addr); return new String[]{ - "--default-dns=false", - "--web-server-port=" + webServerPort, - "--server-port=" + dnsServerPort, - "--log-level=TRACE", + "--conf-path=" + configPath.toString() }; } - public static String[] withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(String host) { - final var configPath = makeConfigFile(host); + public static String[] withRandomPortsAndNotAsDefaultDns() { final var webServerPort = SocketUtils.findRandomFreePort(); final var dnsServerPort = SocketUtils.findRandomFreePort(); + return new String[]{ "--default-dns=false", "--web-server-port=" + webServerPort, "--server-port=" + dnsServerPort, "--log-level=TRACE", + }; + } + + public static Config withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(String host) { + final var configPath = makeConfigFileRandomPortAndCustomLocalEntry(host); + final var args = new String[]{ "--conf-path=" + configPath.toString() }; + return Config.builder() + .args(args) + .config(JsonConfigs.loadConfig(configPath)) + .build(); } @SneakyThrows - private static Path makeConfigFile(String host) { + private static Path makeConfigFileRandomPortAndCustomLocalEntry(String host) { + final var webServerPort = SocketUtils.findRandomFreePort(); + final var dnsServerPort = SocketUtils.findRandomFreePort(); final var configJsonContent = """ { "version": 2, + "webServerPort" : %d, + "dnsServerPort" : %d, + "defaultDns" : false, + "logLevel" : "TRACE", "remoteDnsServers": [], "envs": [ { "name": "", "hostnames": [ { + "id" : 1, "type": "A", "hostname": "%s", "ip": "192.168.0.1", @@ -52,8 +72,42 @@ private static Path makeConfigFile(String host) { } ] } - """.formatted(host); + """.formatted(webServerPort, dnsServerPort, host); + return writeToTempPath(configJsonContent); + } + + @SneakyThrows + private static Path makeConfigFileRandomPortAndCustomRemote(IpAddr remoteAddr) { + final var webServerPort = SocketUtils.findRandomFreePort(); + final var dnsServerPort = SocketUtils.findRandomFreePort(); + final var configJsonContent = """ + { + "version": 2, + "webServerPort" : %d, + "dnsServerPort" : %d, + "defaultDns" : false, + "logLevel" : "TRACE", + "remoteDnsServers": ["%s"], + "envs": [] + } + """.formatted(webServerPort, dnsServerPort, remoteAddr.toString()); + return writeToTempPath(configJsonContent); + } + + private static Path writeToTempPath(String content) throws IOException { final var config = Files.createTempFile("config", ".json"); - return Files.writeString(config, configJsonContent); + return Files.writeString(config, content); + } + + @Value + @Builder + @Accessors(fluent = true) + public static class Config { + private String[] args; + private ConfigJson config; + + public Integer getDnsServerPort() { + return config().getDnsServerPort(); + } } } From fa4f3531217ece5b2959a332075c65f84bd299d2 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 14:38:12 -0300 Subject: [PATCH 42/70] fixing test --- .../com/mageddo/dnsproxyserver/config/Config.java | 12 +++++++++++- .../com/mageddo/dnsproxyserver/AppSettingsTest.java | 2 +- .../dagger/sheath/templates/SignatureTemplates.java | 2 +- src/test/java/testing/templates/ConfigTemplates.java | 1 + 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java index a5880064b..be34ac8af 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java @@ -101,7 +101,17 @@ public CircuitBreakerStrategyConfig getSolverRemoteCircuitBreakerStrategy() { } public enum Source { - JSON, FLAG, DEFAULT, MERGED, ENV + JSON, + FLAG, + DEFAULT, + MERGED, + ENV, + + /** + * Used for testing only; + */ + @Deprecated + TESTS_TEMPLATE, } diff --git a/src/test/java/com/mageddo/dnsproxyserver/AppSettingsTest.java b/src/test/java/com/mageddo/dnsproxyserver/AppSettingsTest.java index 50d18a476..63153c968 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/AppSettingsTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/AppSettingsTest.java @@ -9,7 +9,7 @@ class AppSettingsTest { @Test - void mustLogLevelInSl4jConvetion(){ + void mustLogLevelInSl4jConversion(){ // arrange final var config = ConfigTemplates.defaultWithoutId(); diff --git a/src/test/java/dagger/sheath/templates/SignatureTemplates.java b/src/test/java/dagger/sheath/templates/SignatureTemplates.java index 35dac0370..52ba4239c 100644 --- a/src/test/java/dagger/sheath/templates/SignatureTemplates.java +++ b/src/test/java/dagger/sheath/templates/SignatureTemplates.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import dagger.sheath.reflection.Signature; import org.apache.commons.lang3.reflect.MethodUtils; -import org.graalvm.collections.Pair; +import org.graalvm.collections.Pair; // fixme #533 wrong pair, use apache commons lang3 import java.lang.reflect.Method; import java.util.List; diff --git a/src/test/java/testing/templates/ConfigTemplates.java b/src/test/java/testing/templates/ConfigTemplates.java index cad440fb5..42043a303 100644 --- a/src/test/java/testing/templates/ConfigTemplates.java +++ b/src/test/java/testing/templates/ConfigTemplates.java @@ -40,6 +40,7 @@ private static Config.ConfigBuilder defaultBuilder() { ) .noEntriesResponseCode(3) .dockerSolverHostMachineFallbackActive(true) + .source(Config.Source.TESTS_TEMPLATE) ; } From bf8d077807cc54a5773880df5b76f0b40564a8f9 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 14:41:11 -0300 Subject: [PATCH 43/70] fixing test --- src/test/resources/configs-test/004.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/resources/configs-test/004.json b/src/test/resources/configs-test/004.json index b48333bd5..1ac7a6c63 100644 --- a/src/test/resources/configs-test/004.json +++ b/src/test/resources/configs-test/004.json @@ -13,6 +13,7 @@ "remoteDnsServers" : [ ], "resolvConfOverrideNameServers" : null, "serverProtocol" : null, + "source" : "JSON", "solverRemote" : { "active" : null, "circuitBreaker" : { From 32a8a768cfc7cfcf691fecc3ff3f1c4d149a6f0b Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 14:43:27 -0300 Subject: [PATCH 44/70] fixing test --- .../dnsproxyserver/config/dataprovider/ConfigDAOJsonTest.java | 2 +- src/test/resources/configs-test/004.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/com/mageddo/dnsproxyserver/config/dataprovider/ConfigDAOJsonTest.java b/src/test/java/com/mageddo/dnsproxyserver/config/dataprovider/ConfigDAOJsonTest.java index d0240201f..a1793d656 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/config/dataprovider/ConfigDAOJsonTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/config/dataprovider/ConfigDAOJsonTest.java @@ -23,7 +23,7 @@ class ConfigDAOJsonTest { static final String[] excludingFields = new String[]{ "version", "configPath", "resolvConfPaths", - "dockerHost" + "dockerHost", "source" }; final ConfigDAOJson configDAOJson = new ConfigDAOJson(null, null); diff --git a/src/test/resources/configs-test/004.json b/src/test/resources/configs-test/004.json index 1ac7a6c63..b48333bd5 100644 --- a/src/test/resources/configs-test/004.json +++ b/src/test/resources/configs-test/004.json @@ -13,7 +13,6 @@ "remoteDnsServers" : [ ], "resolvConfOverrideNameServers" : null, "serverProtocol" : null, - "source" : "JSON", "solverRemote" : { "active" : null, "circuitBreaker" : { From 57edb56be3d7c48731677307e8bc5b88550d96fb Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 14:45:46 -0300 Subject: [PATCH 45/70] fixing test --- .../dnsproxyserver/config/dataprovider/ConfigDAOJsonTest.java | 2 +- src/test/resources/configs-test/001.json | 1 + src/test/resources/configs-test/004.json | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/mageddo/dnsproxyserver/config/dataprovider/ConfigDAOJsonTest.java b/src/test/java/com/mageddo/dnsproxyserver/config/dataprovider/ConfigDAOJsonTest.java index a1793d656..d0240201f 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/config/dataprovider/ConfigDAOJsonTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/config/dataprovider/ConfigDAOJsonTest.java @@ -23,7 +23,7 @@ class ConfigDAOJsonTest { static final String[] excludingFields = new String[]{ "version", "configPath", "resolvConfPaths", - "dockerHost", "source" + "dockerHost" }; final ConfigDAOJson configDAOJson = new ConfigDAOJson(null, null); diff --git a/src/test/resources/configs-test/001.json b/src/test/resources/configs-test/001.json index 1ab4abd39..865b32c0b 100644 --- a/src/test/resources/configs-test/001.json +++ b/src/test/resources/configs-test/001.json @@ -17,6 +17,7 @@ } ], "resolvConfOverrideNameServers" : true, "serverProtocol" : "UDP_TCP", + "source" : "MERGED", "solverRemote" : { "active" : true, "circuitBreaker" : { diff --git a/src/test/resources/configs-test/004.json b/src/test/resources/configs-test/004.json index b48333bd5..1ac7a6c63 100644 --- a/src/test/resources/configs-test/004.json +++ b/src/test/resources/configs-test/004.json @@ -13,6 +13,7 @@ "remoteDnsServers" : [ ], "resolvConfOverrideNameServers" : null, "serverProtocol" : null, + "source" : "JSON", "solverRemote" : { "active" : null, "circuitBreaker" : { From 6d79c1aa8ad0c3523750bca0f6825fbf2d670752 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 14:52:10 -0300 Subject: [PATCH 46/70] generating all jar dep for int test automatically --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index 2eea4fcd8..bd4269307 100644 --- a/build.gradle +++ b/build.gradle @@ -115,12 +115,16 @@ def compTest = tasks.register("compTest", Test) { } def intTest = tasks.register("intTest", Test) { + + dependsOn shadowJar useJUnitPlatform() include "**/*IntTest.class" failFast = true + testLogging { events "passed", "skipped", "failed" } + testLogging { showStandardStreams = true } From a97c34f8de6fcb2874f0c45209698ef0082a5686 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 15:28:24 -0300 Subject: [PATCH 47/70] Fixing int test binary executor --- .../sandbox/BinaryFromGradleTestsSandbox.java | 19 +++++--------- .../sandbox/DpsBinaryExecutableFinder.java | 26 ++++++++++++++++++- .../DpsBinaryExecutableFinderIntTest.java | 4 +-- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java index 09682fa27..8b6834356 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -3,29 +3,22 @@ import com.mageddo.commons.exec.CommandLines; import com.mageddo.commons.exec.NopResultHandler; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.exec.CommandLine; @Slf4j public class BinaryFromGradleTestsSandbox { public Instance run(String[] args) { - final var javaCommandPath = findJavaCommand(); - final var executablePath = DpsBinaryExecutableFinder.find(); - - final var commandLine = new CommandLine(javaCommandPath) - .addArgument("-jar") - .addArgument(executablePath.toFile().toString()) - .addArguments(args); - + final var commandLine = DpsBinaryExecutableFinder.buildCommandLine() + .addArguments(args); final var result = CommandLines.exec(commandLine, new NopResultHandler()); return Instance.of(result); } private static String findJavaCommand() { return ProcessHandle.current() - .info() - .command() - .orElseThrow(() -> new IllegalStateException("Couldn't find current java process command")) - ; + .info() + .command() + .orElseThrow(() -> new IllegalStateException("Couldn't find current java process command")) + ; } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java index df844705d..a446bfc8e 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java @@ -3,6 +3,7 @@ import com.mageddo.utils.Runtime; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.exec.CommandLine; import org.apache.commons.lang3.Validate; import org.graalvm.nativeimage.ImageInfo; @@ -12,7 +13,30 @@ @Slf4j public class DpsBinaryExecutableFinder { - public static Path find() { + public static CommandLine buildCommandLine() { + return new DpsBinaryExecutableFinder().buildCommandLineForBestExecutable(); + } + + private CommandLine buildCommandLineForBestExecutable() { + final var executablePath = this.findBestExecutablePath(); + if (ImageInfo.inImageRuntimeCode()) { + return new CommandLine(executablePath.toString()); + } + final var javaCommandPath = this.findJavaCommand(); + return new CommandLine(javaCommandPath) + .addArgument("-jar") + .addArgument(executablePath.toFile().toString()); + } + + private String findJavaCommand() { + return ProcessHandle.current() + .info() + .command() + .orElseThrow(() -> new IllegalStateException("Couldn't find current java process command")) + ; + } + + public static Path findPath() { return new DpsBinaryExecutableFinder().findBestExecutablePath(); } diff --git a/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java index 6953e96fc..b6e8a6ec0 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java @@ -13,7 +13,7 @@ class DpsBinaryExecutableFinderIntTest { void mustFindDpsNativeExecutablePath(){ assumeTrue(ImageInfo.inImageRuntimeCode()); - final var found = DpsBinaryExecutableFinder.find(); + final var found = DpsBinaryExecutableFinder.findPath(); assertTrue(found.toString().endsWith("-tests")); } @@ -22,7 +22,7 @@ void mustFindDpsNativeExecutablePath(){ void mustFindDpsJarPath(){ assumeFalse(ImageInfo.inImageRuntimeCode()); - final var found = DpsBinaryExecutableFinder.find(); + final var found = DpsBinaryExecutableFinder.findPath(); assertTrue(found.toString().endsWith(".jar")); } From 8207f51da4c91c3063779b157fd723567270d379 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 15:37:14 -0300 Subject: [PATCH 48/70] unnecessary method --- .../sandbox/BinaryFromGradleTestsSandbox.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java index 8b6834356..b57a3ac99 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -13,13 +13,4 @@ public Instance run(String[] args) { return Instance.of(result); } - private static String findJavaCommand() { - return ProcessHandle.current() - .info() - .command() - .orElseThrow(() -> new IllegalStateException("Couldn't find current java process command")) - ; - } - - } From ff0718f0790b6fea47aab91f7e0c9b8bea5a4cfa Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 18:56:48 -0300 Subject: [PATCH 49/70] refactoring test to use json config file only --- .../config/dataprovider/vo/ConfigEnv.java | 8 ++-- .../sandbox/BinaryFromGradleTestsSandbox.java | 7 +-- .../sandbox/DpsBinaryExecutableFinder.java | 2 +- .../dnsproxyserver/sandbox/Sandbox.java | 6 ++- .../mageddo/dnsproxyserver/AppIntTest.java | 19 ++++---- .../templates/ConfigFlagArgsTemplates.java | 46 ++----------------- .../templates/ConfigJsonFileTemplates.java | 28 +++++++++++ src/test/resources/configs-test/009.json | 22 +++++++++ 8 files changed, 76 insertions(+), 62 deletions(-) create mode 100644 src/test/java/testing/templates/ConfigJsonFileTemplates.java create mode 100644 src/test/resources/configs-test/009.json diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/vo/ConfigEnv.java b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/vo/ConfigEnv.java index 1d376933f..a0d54f10f 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/vo/ConfigEnv.java +++ b/src/main/java/com/mageddo/dnsproxyserver/config/dataprovider/vo/ConfigEnv.java @@ -41,13 +41,13 @@ public class ConfigEnv { public static final String MG_RESOLVCONF_OVERRIDE_NAMESERVERS = "MG_RESOLVCONF_OVERRIDE_NAMESERVERS"; - private static final String MG_NO_REMOTE_SERVERS = "MG_NO_REMOTE_SERVERS"; + public static final String MG_NO_REMOTE_SERVERS = "MG_NO_REMOTE_SERVERS"; - private static final String MG_NO_ENTRIES_RESPONSE_CODE = "MG_NO_ENTRIES_RESPONSE_CODE"; + public static final String MG_NO_ENTRIES_RESPONSE_CODE = "MG_NO_ENTRIES_RESPONSE_CODE"; - private static final String MG_DOCKER_SOLVER_HOST_MACHINE_FALLBACK_ACTIVE = "MG_DOCKER_SOLVER_HOST_MACHINE_FALLBACK_ACTIVE"; + public static final String MG_DOCKER_SOLVER_HOST_MACHINE_FALLBACK_ACTIVE = "MG_DOCKER_SOLVER_HOST_MACHINE_FALLBACK_ACTIVE"; - private static final String MG_CONFIG_FILE_PATH = "MG_CONFIG_FILE_PATH"; + public static final String MG_CONFIG_FILE_PATH = "MG_CONFIG_FILE_PATH"; private Path workingDir; private String resolvConfPath; diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java index b57a3ac99..3a651a779 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -4,11 +4,12 @@ import com.mageddo.commons.exec.NopResultHandler; import lombok.extern.slf4j.Slf4j; +import java.nio.file.Path; + @Slf4j public class BinaryFromGradleTestsSandbox { - public Instance run(String[] args) { - final var commandLine = DpsBinaryExecutableFinder.buildCommandLine() - .addArguments(args); + public Instance run(Path configFile) { + final var commandLine = DpsBinaryExecutableFinder.buildCommandLine(configFile); final var result = CommandLines.exec(commandLine, new NopResultHandler()); return Instance.of(result); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java index a446bfc8e..22cf58050 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java @@ -13,7 +13,7 @@ @Slf4j public class DpsBinaryExecutableFinder { - public static CommandLine buildCommandLine() { + public static CommandLine buildCommandLine(Path configFile) { return new DpsBinaryExecutableFinder().buildCommandLineForBestExecutable(); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java index df6572968..4196377a9 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java @@ -1,7 +1,9 @@ package com.mageddo.dnsproxyserver.sandbox; +import java.nio.file.Path; + public class Sandbox { - public static Instance runFromGradleTests(String[] args) { - return new BinaryFromGradleTestsSandbox().run(args); + public static Instance runFromGradleTests(Path configFile) { + return new BinaryFromGradleTestsSandbox().run(configFile); } } diff --git a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java index efab6375b..2676a6d89 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java @@ -4,6 +4,8 @@ import com.mageddo.commons.exec.ProcessesWatchDog; import com.mageddo.dns.utils.Messages; import com.mageddo.dnsproxyserver.config.application.Configs; +import com.mageddo.dnsproxyserver.config.dataprovider.JsonConfigs; +import com.mageddo.dnsproxyserver.config.dataprovider.vo.ConfigJson; import com.mageddo.dnsproxyserver.sandbox.Instance; import com.mageddo.dnsproxyserver.sandbox.Sandbox; import com.mageddo.dnsproxyserver.server.Starter; @@ -19,7 +21,9 @@ import org.junit.jupiter.api.Test; import org.xbill.DNS.Message; import testing.templates.ConfigFlagArgsTemplates; +import testing.templates.ConfigJsonFileTemplates; +import java.nio.file.Path; import java.time.Duration; import java.util.Arrays; import java.util.concurrent.ExecutorService; @@ -88,10 +92,10 @@ private static App buildClientAppAndWait(ExecutorService executor, Integer serve } private static Result buildAndStartServerApp(String hostToQuery) { - final var config = ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(hostToQuery); - final var instance = Sandbox.runFromGradleTests(config.args()); + final var configFile = ConfigJsonFileTemplates.withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(hostToQuery); + final var instance = Sandbox.runFromGradleTests(configFile); instance.watchOutputInDaemonThread(); - return Result.of(config, instance); + return Result.of(configFile, instance); } private static App buildAppAndWait(ExecutorService executor, final String[] params) { @@ -112,19 +116,16 @@ static Message queryStartedServer(Integer port, String host) { @Value static class Result { - private final ConfigFlagArgsTemplates.Config config; + private final ConfigJson config; private final Instance instance; - public static Result of(ConfigFlagArgsTemplates.Config config, Instance instance) { - return new Result(config, instance); + public static Result of(Path configFile, Instance instance) { + return new Result(JsonConfigs.loadConfig(configFile), instance); } public Integer getDnsServerPort() { return this.config.getDnsServerPort(); } - public void watchInstanceOutputInDaemonThread() { - this.getInstance().watchOutputInDaemonThread(); - } } } diff --git a/src/test/java/testing/templates/ConfigFlagArgsTemplates.java b/src/test/java/testing/templates/ConfigFlagArgsTemplates.java index abd3a4911..674b2f75a 100644 --- a/src/test/java/testing/templates/ConfigFlagArgsTemplates.java +++ b/src/test/java/testing/templates/ConfigFlagArgsTemplates.java @@ -1,6 +1,5 @@ package testing.templates; -import com.mageddo.dnsproxyserver.config.dataprovider.JsonConfigs; import com.mageddo.dnsproxyserver.config.dataprovider.vo.ConfigJson; import com.mageddo.net.IpAddr; import com.mageddo.net.SocketUtils; @@ -12,6 +11,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Map; public class ConfigFlagArgsTemplates { @@ -34,48 +34,6 @@ public static String[] withRandomPortsAndNotAsDefaultDns() { }; } - public static Config withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(String host) { - final var configPath = makeConfigFileRandomPortAndCustomLocalEntry(host); - final var args = new String[]{ - "--conf-path=" + configPath.toString() - }; - return Config.builder() - .args(args) - .config(JsonConfigs.loadConfig(configPath)) - .build(); - } - - @SneakyThrows - private static Path makeConfigFileRandomPortAndCustomLocalEntry(String host) { - final var webServerPort = SocketUtils.findRandomFreePort(); - final var dnsServerPort = SocketUtils.findRandomFreePort(); - final var configJsonContent = """ - { - "version": 2, - "webServerPort" : %d, - "dnsServerPort" : %d, - "defaultDns" : false, - "logLevel" : "TRACE", - "remoteDnsServers": [], - "envs": [ - { - "name": "", - "hostnames": [ - { - "id" : 1, - "type": "A", - "hostname": "%s", - "ip": "192.168.0.1", - "ttl": 255 - } - ] - } - ] - } - """.formatted(webServerPort, dnsServerPort, host); - return writeToTempPath(configJsonContent); - } - @SneakyThrows private static Path makeConfigFileRandomPortAndCustomRemote(IpAddr remoteAddr) { final var webServerPort = SocketUtils.findRandomFreePort(); @@ -113,8 +71,10 @@ public static String[] empty() { @Builder @Accessors(fluent = true) public static class Config { + private String[] args; private ConfigJson config; + private Map envs; public Integer getDnsServerPort() { return config().getDnsServerPort(); diff --git a/src/test/java/testing/templates/ConfigJsonFileTemplates.java b/src/test/java/testing/templates/ConfigJsonFileTemplates.java new file mode 100644 index 000000000..af9c33c74 --- /dev/null +++ b/src/test/java/testing/templates/ConfigJsonFileTemplates.java @@ -0,0 +1,28 @@ +package testing.templates; + +import com.mageddo.net.SocketUtils; +import com.mageddo.utils.TestUtils; +import lombok.SneakyThrows; + +import java.nio.file.Files; +import java.nio.file.Path; + +public class ConfigJsonFileTemplates { + + public static Path withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(String host) { + final var webServerPort = SocketUtils.findRandomFreePort(); + final var dnsServerPort = SocketUtils.findRandomFreePort(); + return writeToTempPathReplacing("/configs-test/009.json", webServerPort, dnsServerPort, host); + } + + private static Path writeToTempPathReplacing(final String resourceTemplatePath, Object ... args) { + final var jsonTemplate = TestUtils.readString(resourceTemplatePath); + return writeToTempPath(jsonTemplate.formatted(args)); + } + + @SneakyThrows + private static Path writeToTempPath(String content) { + final var config = Files.createTempFile("config", ".json"); + return Files.writeString(config, content); + } +} diff --git a/src/test/resources/configs-test/009.json b/src/test/resources/configs-test/009.json new file mode 100644 index 000000000..04bb04488 --- /dev/null +++ b/src/test/resources/configs-test/009.json @@ -0,0 +1,22 @@ +{ + "version": 2, + "webServerPort" : %d, + "dnsServerPort" : %d, + "defaultDns" : false, + "logLevel" : "TRACE", + "remoteDnsServers": [], + "envs": [ + { + "name": "", + "hostnames": [ + { + "id" : 1, + "type": "A", + "hostname": "%s", + "ip": "192.168.0.1", + "ttl": 255 + } + ] + } + ] +} From 9fb069f1ce4a4921643a56d899bfdc4f305f590c Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 20:22:47 -0300 Subject: [PATCH 50/70] all working --- .../mageddo/commons/exec/CommandLines.java | 154 +++++++++++++----- .../com/mageddo/commons/exec/PipedStream.java | 40 ++--- .../com/mageddo/concurrent/ThreadsV2.java | 7 + .../sandbox/BinaryFromGradleTestsSandbox.java | 15 +- .../sandbox/DpsBinaryExecutableFinder.java | 2 +- .../dnsproxyserver/sandbox/Instance.java | 2 +- src/main/java/com/mageddo/io/LogPrinter.java | 35 ++++ .../commons/exec/CommandLinesTest.java | 2 +- .../mageddo/commons/exec/PipedStreamTest.java | 10 +- 9 files changed, 193 insertions(+), 74 deletions(-) create mode 100644 src/main/java/com/mageddo/concurrent/ThreadsV2.java create mode 100644 src/main/java/com/mageddo/io/LogPrinter.java diff --git a/src/main/java/com/mageddo/commons/exec/CommandLines.java b/src/main/java/com/mageddo/commons/exec/CommandLines.java index 057ddd386..35b9eae63 100644 --- a/src/main/java/com/mageddo/commons/exec/CommandLines.java +++ b/src/main/java/com/mageddo/commons/exec/CommandLines.java @@ -1,5 +1,6 @@ package com.mageddo.commons.exec; +import com.mageddo.io.LogPrinter; import com.mageddo.wait.Wait; import lombok.Builder; import lombok.Getter; @@ -7,21 +8,23 @@ import lombok.SneakyThrows; import lombok.ToString; import lombok.Value; +import lombok.experimental.NonFinal; import lombok.extern.slf4j.Slf4j; import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.DaemonExecutor; import org.apache.commons.exec.ExecuteException; import org.apache.commons.exec.ExecuteResultHandler; +import org.apache.commons.exec.ExecuteStreamHandler; import org.apache.commons.exec.ExecuteWatchdog; import org.apache.commons.exec.Executor; import org.apache.commons.exec.PumpStreamHandler; import org.apache.commons.lang3.Validate; -import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; -import java.io.InputStreamReader; +import java.io.InputStream; +import java.io.OutputStream; import java.io.UncheckedIOException; import java.util.Map; import java.util.function.Supplier; @@ -45,10 +48,10 @@ public static Result exec(CommandLine commandLine) { public static Result exec(CommandLine commandLine, long timeout) { - final var stream = new PipedStream(); + final var bout = new ByteArrayOutputStream(); + final var stream = new PipedStream(bout); final var executor = createExecutor(); - final var streamHandler = new PumpStreamHandler(stream.getOut()); - executor.setStreamHandler(streamHandler); + executor.setStreamHandler(new PumpStreamHandler(stream)); int exitCode; try { executor.setWatchdog(new ExecuteWatchdog(timeout)); @@ -62,8 +65,7 @@ public static Result exec(CommandLine commandLine, long timeout) { return Result .builder() .executor(executor) - .stream(stream) - .out(stream.getBout()) + .out(bout) .exitCode(exitCode) .processSupplier(executor::getProcess) .build(); @@ -74,10 +76,10 @@ private static void registerProcessWatch(ProcessAccessibleDaemonExecutor executo } public static Result exec(CommandLine commandLine, ExecuteResultHandler handler) { - final var stream = new PipedStream(); + final var bout = new ByteArrayOutputStream(); + final var stream = new PipedStream(bout); final var executor = createExecutor(); - final var streamHandler = new PumpStreamHandler(stream.getOut()); - executor.setStreamHandler(streamHandler); + executor.setStreamHandler(new PumpStreamHandler(stream)); try { executor.setWatchdog(new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT)); executor.execute(commandLine, handler); @@ -91,26 +93,24 @@ public static Result exec(CommandLine commandLine, ExecuteResultHandler handler) .builder() .executor(executor) .processSupplier(executor::getProcess) - .out(stream.getBout()) - .stream(stream) + .out(bout) .build(); } public static Result exec(Request request) { - final var stream = new PipedStream(); final var executor = createExecutor(); executor.setStreamHandler(request.getStreamHandler()); Integer exitCode = null; try { executor.setWatchdog(new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT)); if (request.getHandler() != null) { - executor.execute(request.getCommandLine(), request.getHandler()); + executor.execute(request.getCommandLine(), request.getEnv(), request.getHandler()); registerProcessWatch(executor); } else { - exitCode = executor.execute(request.getCommandLine()); + exitCode = executor.execute(request.getCommandLine(), request.getEnv()); } } catch (ExecuteException e) { - if(request.getHandler() != null){ + if (request.getHandler() != null) { request.getHandler().onProcessFailed(e); } else { exitCode = e.getExitValue(); @@ -122,9 +122,9 @@ public static Result exec(Request request) { .builder() .executor(executor) .processSupplier(executor::getProcess) - .out(stream.getBout()) - .stream(stream) + .out(request.getBestOut()) .exitCode(exitCode) + .request(request) .build(); } @@ -143,13 +143,92 @@ protected Process launch(CommandLine command, Map env, File dir) } } - @Value - @Builder + @Builder(toBuilder = true, builderClassName = "RequestBuilder", buildMethodName = "build0") public static class Request { - CommandLine commandLine; - ExecuteResultHandler handler; - PumpStreamHandler streamHandler; + + private final CommandLine commandLine; + private final ExecuteResultHandler handler; + private Map env; + + @NonFinal + private boolean watchingOutput; + + @Builder.Default + private final Streams streams = Streams.builder() + .outAndErr(new ByteArrayOutputStream()) + .build(); + + public ExecuteStreamHandler getStreamHandler() { + return this.streams.toStreamHandler(); + } + + private Request printOutToLogsInBackground() { + if (this.watchingOutput) { + throw new IllegalStateException("Already watching output"); + } + this.watchingOutput = true; + LogPrinter.printInBackground(this.streams.outAndErr.getPipedIn()); + return this; + } + + public OutputStream getBestOut() { + return this.streams.getBestOriginalOutput(); + } + + public static class RequestBuilder { + + private boolean printLogsInBackground = false; + + public Request build() { + final var request = this.build0(); + if (this.printLogsInBackground) { + request.printOutToLogsInBackground(); + } + return request; + } + + public RequestBuilder printLogsInBackground() { + this.printLogsInBackground = true; + return this; + } + } + + + @Value + @Builder(toBuilder = true, builderClassName = "StreamsBuilder") + public static class Streams { + + private final PipedStream outAndErr; + private final OutputStream out; + private final OutputStream err; + private final InputStream input; + + public PipedStream getBestOut() { + if (this.outAndErr != null) { + return this.outAndErr; + } + throw new UnsupportedOperationException(); + } + + public OutputStream getBestOriginalOutput() { + return this.getBestOut(); + } + + public static class StreamsBuilder { + public StreamsBuilder outAndErr(OutputStream outAndErr) { + this.outAndErr = new PipedStream(outAndErr); + return this; + } + } + + public ExecuteStreamHandler toStreamHandler() { + if (this.outAndErr != null) { + return new PumpStreamHandler(this.outAndErr); + } + return new PumpStreamHandler(this.out, this.err, this.input); + } + } } @Getter @@ -158,41 +237,26 @@ public static class Request { public static class Result { @NonNull - private Executor executor; + private Request request; @NonNull - private PipedStream stream; + private Executor executor; @NonNull - private ByteArrayOutputStream out; + private OutputStream out; @NonNull private Supplier processSupplier; private Integer exitCode; - public void watchOutputInDaemonThread() { - final var task = (Runnable) () -> { - final var bf = new BufferedReader(new InputStreamReader(this.stream.getPipedInputStream())); - while (true) { - try { - final var line = bf.readLine(); - if (line == null) { - log.debug("status=outputEnded"); - break; - } - log.debug(">>> {}", line); - } catch (IOException e) { - - } - } - }; - Thread - .ofVirtual() - .start(task); + public Result printOutToLogsInBackground() { + this.request.printOutToLogsInBackground(); + return this; } public String getOutAsString() { + Validate.isTrue(this.out instanceof ByteArrayOutputStream, "Only ByteArrayOutputStream is supported"); return this.out.toString(); } diff --git a/src/main/java/com/mageddo/commons/exec/PipedStream.java b/src/main/java/com/mageddo/commons/exec/PipedStream.java index 42a2971d0..78164fd80 100644 --- a/src/main/java/com/mageddo/commons/exec/PipedStream.java +++ b/src/main/java/com/mageddo/commons/exec/PipedStream.java @@ -1,42 +1,42 @@ package com.mageddo.commons.exec; -import java.io.ByteArrayOutputStream; +import lombok.Getter; + import java.io.IOException; import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.io.UncheckedIOException; -public class PipedStream { +public class PipedStream extends OutputStream { + + @Getter + private final PipedInputStream pipedIn; - private final PipedInputStream pipedInputStream; - private final ByteArrayOutputStream bout; - private final DelegateOutputStream out; + private final DelegateOutputStream delegateOut; + private final OutputStream originalOut; - public PipedStream() { + public PipedStream(final OutputStream out) { try { - this.pipedInputStream = new PipedInputStream(); - final var pout = new PipedOutputStream(this.pipedInputStream); - this.bout = new ByteArrayOutputStream(); - this.out = new DelegateOutputStream(this.bout, pout); + this.pipedIn = new PipedInputStream(); + this.originalOut = out; + final var pout = new PipedOutputStream(this.pipedIn); + this.delegateOut = new DelegateOutputStream(out, pout); } catch (IOException e) { throw new UncheckedIOException(e); } } - public OutputStream getOut() { - return this.out; - } - - public ByteArrayOutputStream getBout() { - return bout; + @Override + public void write(int b) throws IOException { + this.delegateOut.write(b); } - public PipedInputStream getPipedInputStream() { - return this.pipedInputStream; + public void close() throws IOException { + this.delegateOut.close(); } - public void close() throws IOException { - this.out.close(); + OutputStream getOriginalOut() { + return originalOut; } } diff --git a/src/main/java/com/mageddo/concurrent/ThreadsV2.java b/src/main/java/com/mageddo/concurrent/ThreadsV2.java new file mode 100644 index 000000000..4c59f6b7f --- /dev/null +++ b/src/main/java/com/mageddo/concurrent/ThreadsV2.java @@ -0,0 +1,7 @@ +package com.mageddo.concurrent; + +public class ThreadsV2 { + public static boolean isInterrupted() { + return Thread.currentThread().isInterrupted(); + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java index 3a651a779..ab42a1f49 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -1,16 +1,27 @@ package com.mageddo.dnsproxyserver.sandbox; +import com.google.common.collect.Maps; import com.mageddo.commons.exec.CommandLines; import com.mageddo.commons.exec.NopResultHandler; +import com.mageddo.dnsproxyserver.config.dataprovider.vo.ConfigEnv; import lombok.extern.slf4j.Slf4j; import java.nio.file.Path; +import java.util.Map; @Slf4j public class BinaryFromGradleTestsSandbox { public Instance run(Path configFile) { - final var commandLine = DpsBinaryExecutableFinder.buildCommandLine(configFile); - final var result = CommandLines.exec(commandLine, new NopResultHandler()); + final var commandLine = DpsBinaryExecutableFinder.buildCommandLine(); + final var request = CommandLines.Request.builder() + .commandLine(commandLine) + .handler(new NopResultHandler()) + .env(Map.of(ConfigEnv.MG_CONFIG_FILE_PATH, configFile.toString())) + .build(); + + final var result = CommandLines.exec(request) + .printOutToLogsInBackground(); + return Instance.of(result); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java index 22cf58050..a446bfc8e 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java @@ -13,7 +13,7 @@ @Slf4j public class DpsBinaryExecutableFinder { - public static CommandLine buildCommandLine(Path configFile) { + public static CommandLine buildCommandLine() { return new DpsBinaryExecutableFinder().buildCommandLineForBestExecutable(); } diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java index cc9f0b598..ceaed4b72 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java @@ -47,6 +47,6 @@ private Long getProcessId() { } public void watchOutputInDaemonThread() { - getResult().watchOutputInDaemonThread(); + getResult().printOutToLogsInBackground(); } } diff --git a/src/main/java/com/mageddo/io/LogPrinter.java b/src/main/java/com/mageddo/io/LogPrinter.java new file mode 100644 index 000000000..3ded49a69 --- /dev/null +++ b/src/main/java/com/mageddo/io/LogPrinter.java @@ -0,0 +1,35 @@ +package com.mageddo.io; + +import com.mageddo.concurrent.ThreadsV2; +import lombok.extern.slf4j.Slf4j; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +@Slf4j +public class LogPrinter { + + public static void printInBackground(InputStream in) { + final var task = (Runnable) () -> { + final var bf = new BufferedReader(new InputStreamReader(in)); + while (!ThreadsV2.isInterrupted()) { + try { + final var line = bf.readLine(); + if (line == null) { + log.debug("status=outputEnded"); + break; + } + log.debug(">>> {}", line); + } catch (IOException e) { + + } + } + }; + Thread + .ofVirtual() + .start(task); + } + +} diff --git a/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java b/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java index dd3ba4afb..ac31d0c5a 100644 --- a/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java +++ b/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java @@ -17,7 +17,7 @@ void mustExecuteAndPrintOutputConcurrently() { new NopResultHandler() ); - result.watchOutputInDaemonThread(); + result.printOutToLogsInBackground(); result.waitProcessToFinish(); diff --git a/src/test/java/com/mageddo/commons/exec/PipedStreamTest.java b/src/test/java/com/mageddo/commons/exec/PipedStreamTest.java index a797bde2b..b93f1121a 100644 --- a/src/test/java/com/mageddo/commons/exec/PipedStreamTest.java +++ b/src/test/java/com/mageddo/commons/exec/PipedStreamTest.java @@ -2,6 +2,7 @@ import org.junit.jupiter.api.Test; +import java.io.ByteArrayOutputStream; import java.io.IOException; import static org.junit.jupiter.api.Assertions.assertArrayEquals; @@ -14,12 +15,13 @@ void mustWriteToOutAndBeAbleToReadWhatIsBeingWritten() throws IOException { final var bytes = new byte[]{1, 2, 3}; // act - final var stream = new PipedStream(); - stream.getOut().write(bytes); + final var stream = new PipedStream(new ByteArrayOutputStream()); + stream.write(bytes); stream.close(); // assert - assertArrayEquals(bytes, stream.getBout().toByteArray()); - assertArrayEquals(bytes, stream.getPipedInputStream().readAllBytes()); + final var bout = (ByteArrayOutputStream) stream.getOriginalOut(); + assertArrayEquals(bytes, bout.toByteArray()); + assertArrayEquals(bytes, stream.getPipedIn().readAllBytes()); } } From 5837b4cb233c7d2e20fe48f8f736c47d62a5652e Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 20:24:52 -0300 Subject: [PATCH 51/70] adjusting test --- .../dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java | 1 - src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java index ab42a1f49..7e01da300 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -1,6 +1,5 @@ package com.mageddo.dnsproxyserver.sandbox; -import com.google.common.collect.Maps; import com.mageddo.commons.exec.CommandLines; import com.mageddo.commons.exec.NopResultHandler; import com.mageddo.dnsproxyserver.config.dataprovider.vo.ConfigEnv; diff --git a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java index 2676a6d89..2dd6751a0 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java @@ -94,7 +94,6 @@ private static App buildClientAppAndWait(ExecutorService executor, Integer serve private static Result buildAndStartServerApp(String hostToQuery) { final var configFile = ConfigJsonFileTemplates.withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(hostToQuery); final var instance = Sandbox.runFromGradleTests(configFile); - instance.watchOutputInDaemonThread(); return Result.of(configFile, instance); } From 04c42141c845f90e887f9a32f80a7a0999069dac Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 20:27:58 -0300 Subject: [PATCH 52/70] fixing test --- .../mageddo/commons/exec/CommandLines.java | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/mageddo/commons/exec/CommandLines.java b/src/main/java/com/mageddo/commons/exec/CommandLines.java index 35b9eae63..9fbdee5b6 100644 --- a/src/main/java/com/mageddo/commons/exec/CommandLines.java +++ b/src/main/java/com/mageddo/commons/exec/CommandLines.java @@ -72,29 +72,18 @@ public static Result exec(CommandLine commandLine, long timeout) { } private static void registerProcessWatch(ProcessAccessibleDaemonExecutor executor) { - ProcessesWatchDog.instance().watch(executor::getProcess); + ProcessesWatchDog.instance() + .watch(executor::getProcess) + ; } public static Result exec(CommandLine commandLine, ExecuteResultHandler handler) { - final var bout = new ByteArrayOutputStream(); - final var stream = new PipedStream(bout); - final var executor = createExecutor(); - executor.setStreamHandler(new PumpStreamHandler(stream)); - try { - executor.setWatchdog(new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT)); - executor.execute(commandLine, handler); - registerProcessWatch(executor); - } catch (ExecuteException e) { - handler.onProcessFailed(e); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - return Result + return exec(Request .builder() - .executor(executor) - .processSupplier(executor::getProcess) - .out(bout) - .build(); + .commandLine(commandLine) + .handler(handler) + .build() + ); } public static Result exec(Request request) { From 98390e3d941b0c573cfe86c72e064f6ede2f7579 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 20:36:06 -0300 Subject: [PATCH 53/70] fixing bugs and creating tests --- .../mageddo/commons/exec/CommandLines.java | 44 +++++++++---------- .../ExecutionValidationFailedException.java | 4 ++ .../commons/exec/CommandLinesTest.java | 26 +++++++++++ 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/mageddo/commons/exec/CommandLines.java b/src/main/java/com/mageddo/commons/exec/CommandLines.java index 9fbdee5b6..b6769bd8f 100644 --- a/src/main/java/com/mageddo/commons/exec/CommandLines.java +++ b/src/main/java/com/mageddo/commons/exec/CommandLines.java @@ -26,6 +26,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.UncheckedIOException; +import java.time.Duration; import java.util.Map; import java.util.function.Supplier; @@ -47,28 +48,12 @@ public static Result exec(CommandLine commandLine) { } public static Result exec(CommandLine commandLine, long timeout) { - - final var bout = new ByteArrayOutputStream(); - final var stream = new PipedStream(bout); - final var executor = createExecutor(); - executor.setStreamHandler(new PumpStreamHandler(stream)); - int exitCode; - try { - executor.setWatchdog(new ExecuteWatchdog(timeout)); - exitCode = executor.execute(commandLine); - registerProcessWatch(executor); - } catch (ExecuteException e) { - exitCode = e.getExitValue(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - return Result - .builder() - .executor(executor) - .out(bout) - .exitCode(exitCode) - .processSupplier(executor::getProcess) - .build(); + return exec( + Request.builder() + .commandLine(commandLine) + .timeout(Duration.ofMillis(timeout)) + .build() + ); } private static void registerProcessWatch(ProcessAccessibleDaemonExecutor executor) { @@ -91,7 +76,7 @@ public static Result exec(Request request) { executor.setStreamHandler(request.getStreamHandler()); Integer exitCode = null; try { - executor.setWatchdog(new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT)); + executor.setWatchdog(new ExecuteWatchdog(request.getTimeoutInMillis())); if (request.getHandler() != null) { executor.execute(request.getCommandLine(), request.getEnv(), request.getHandler()); registerProcessWatch(executor); @@ -136,7 +121,11 @@ protected Process launch(CommandLine command, Map env, File dir) @Builder(toBuilder = true, builderClassName = "RequestBuilder", buildMethodName = "build0") public static class Request { + @NonNull private final CommandLine commandLine; + + private final Duration timeout; + private final ExecuteResultHandler handler; private Map env; @@ -165,6 +154,13 @@ public OutputStream getBestOut() { return this.streams.getBestOriginalOutput(); } + public long getTimeoutInMillis() { + if (this.timeout == null) { + return ExecuteWatchdog.INFINITE_TIMEOUT; + } + return this.timeout.toMillis(); + } + public static class RequestBuilder { private boolean printLogsInBackground = false; @@ -201,7 +197,7 @@ public PipedStream getBestOut() { } public OutputStream getBestOriginalOutput() { - return this.getBestOut(); + return this.getBestOut().getOriginalOut(); } public static class StreamsBuilder { diff --git a/src/main/java/com/mageddo/commons/exec/ExecutionValidationFailedException.java b/src/main/java/com/mageddo/commons/exec/ExecutionValidationFailedException.java index 618d8ae0e..562b9b0a1 100644 --- a/src/main/java/com/mageddo/commons/exec/ExecutionValidationFailedException.java +++ b/src/main/java/com/mageddo/commons/exec/ExecutionValidationFailedException.java @@ -11,4 +11,8 @@ public ExecutionValidationFailedException(CommandLines.Result result) { public CommandLines.Result result() { return this.result; } + + public int getExitCode() { + return this.result.getExitCode(); + } } diff --git a/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java b/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java index ac31d0c5a..bebd08efa 100644 --- a/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java +++ b/src/test/java/com/mageddo/commons/exec/CommandLinesTest.java @@ -4,9 +4,35 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; class CommandLinesTest { + + @Test + void mustValidateWhenExitsWithErrorCode(){ + + final var result = CommandLines.exec( + new CommandLine("sh") + .addArgument("-c") + .addArgument("exit 3", false) + ); + + final var ex = assertThrows(ExecutionValidationFailedException.class, result::checkExecution); + + assertEquals(3, ex.getExitCode()); + + } + + @Test + void mustExecuteCommand(){ + + final var result = CommandLines.exec("echo %s", "hey"); + + assertEquals(0, result.getExitCode()); + assertEquals("hey\n", result.getOutAsString()); + } + @Test void mustExecuteAndPrintOutputConcurrently() { From d6367a67f2d1c5f85c652c1a68794fec6f097ce7 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 20:40:23 -0300 Subject: [PATCH 54/70] refactoring inner class to upper --- .../mageddo/commons/exec/CommandLines.java | 208 ------------------ .../ExecutionValidationFailedException.java | 6 +- .../exec/ProcessAccessibleDaemonExecutor.java | 20 ++ .../com/mageddo/commons/exec/Request.java | 117 ++++++++++ .../java/com/mageddo/commons/exec/Result.java | 93 ++++++++ .../sandbox/BinaryFromGradleTestsSandbox.java | 3 +- .../dnsproxyserver/sandbox/Instance.java | 6 +- 7 files changed, 238 insertions(+), 215 deletions(-) create mode 100644 src/main/java/com/mageddo/commons/exec/ProcessAccessibleDaemonExecutor.java create mode 100644 src/main/java/com/mageddo/commons/exec/Request.java create mode 100644 src/main/java/com/mageddo/commons/exec/Result.java diff --git a/src/main/java/com/mageddo/commons/exec/CommandLines.java b/src/main/java/com/mageddo/commons/exec/CommandLines.java index b6769bd8f..a372a483f 100644 --- a/src/main/java/com/mageddo/commons/exec/CommandLines.java +++ b/src/main/java/com/mageddo/commons/exec/CommandLines.java @@ -1,34 +1,14 @@ package com.mageddo.commons.exec; -import com.mageddo.io.LogPrinter; -import com.mageddo.wait.Wait; -import lombok.Builder; -import lombok.Getter; -import lombok.NonNull; -import lombok.SneakyThrows; -import lombok.ToString; -import lombok.Value; -import lombok.experimental.NonFinal; import lombok.extern.slf4j.Slf4j; import org.apache.commons.exec.CommandLine; -import org.apache.commons.exec.DaemonExecutor; import org.apache.commons.exec.ExecuteException; import org.apache.commons.exec.ExecuteResultHandler; -import org.apache.commons.exec.ExecuteStreamHandler; import org.apache.commons.exec.ExecuteWatchdog; -import org.apache.commons.exec.Executor; -import org.apache.commons.exec.PumpStreamHandler; -import org.apache.commons.lang3.Validate; -import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.io.UncheckedIOException; import java.time.Duration; -import java.util.Map; -import java.util.function.Supplier; @Slf4j public class CommandLines { @@ -106,192 +86,4 @@ private static ProcessAccessibleDaemonExecutor createExecutor() { return new ProcessAccessibleDaemonExecutor(); } - @Getter - static class ProcessAccessibleDaemonExecutor extends DaemonExecutor { - - private Process process = null; - - @Override - protected Process launch(CommandLine command, Map env, File dir) throws IOException { - return this.process = super.launch(command, env, dir); - } - } - - @Value - @Builder(toBuilder = true, builderClassName = "RequestBuilder", buildMethodName = "build0") - public static class Request { - - @NonNull - private final CommandLine commandLine; - - private final Duration timeout; - - private final ExecuteResultHandler handler; - private Map env; - - @NonFinal - private boolean watchingOutput; - - @Builder.Default - private final Streams streams = Streams.builder() - .outAndErr(new ByteArrayOutputStream()) - .build(); - - public ExecuteStreamHandler getStreamHandler() { - return this.streams.toStreamHandler(); - } - - private Request printOutToLogsInBackground() { - if (this.watchingOutput) { - throw new IllegalStateException("Already watching output"); - } - this.watchingOutput = true; - LogPrinter.printInBackground(this.streams.outAndErr.getPipedIn()); - return this; - } - - public OutputStream getBestOut() { - return this.streams.getBestOriginalOutput(); - } - - public long getTimeoutInMillis() { - if (this.timeout == null) { - return ExecuteWatchdog.INFINITE_TIMEOUT; - } - return this.timeout.toMillis(); - } - - public static class RequestBuilder { - - private boolean printLogsInBackground = false; - - public Request build() { - final var request = this.build0(); - if (this.printLogsInBackground) { - request.printOutToLogsInBackground(); - } - return request; - } - - public RequestBuilder printLogsInBackground() { - this.printLogsInBackground = true; - return this; - } - } - - - @Value - @Builder(toBuilder = true, builderClassName = "StreamsBuilder") - public static class Streams { - - private final PipedStream outAndErr; - private final OutputStream out; - private final OutputStream err; - private final InputStream input; - - public PipedStream getBestOut() { - if (this.outAndErr != null) { - return this.outAndErr; - } - throw new UnsupportedOperationException(); - } - - public OutputStream getBestOriginalOutput() { - return this.getBestOut().getOriginalOut(); - } - - public static class StreamsBuilder { - public StreamsBuilder outAndErr(OutputStream outAndErr) { - this.outAndErr = new PipedStream(outAndErr); - return this; - } - } - - public ExecuteStreamHandler toStreamHandler() { - if (this.outAndErr != null) { - return new PumpStreamHandler(this.outAndErr); - } - return new PumpStreamHandler(this.out, this.err, this.input); - } - } - } - - @Getter - @Builder - @ToString(of = {"exitCode"}) - public static class Result { - - @NonNull - private Request request; - - @NonNull - private Executor executor; - - @NonNull - private OutputStream out; - - @NonNull - private Supplier processSupplier; - - private Integer exitCode; - - public Result printOutToLogsInBackground() { - this.request.printOutToLogsInBackground(); - return this; - } - - public String getOutAsString() { - Validate.isTrue(this.out instanceof ByteArrayOutputStream, "Only ByteArrayOutputStream is supported"); - return this.out.toString(); - } - - public Result checkExecution() { - if (this.executor.isFailure(this.getExitCode())) { - throw new ExecutionValidationFailedException(this); - } - return this; - } - - public String toString(boolean printOut) { - return String.format( - "code=%d, out=%s", - this.exitCode, printOut ? this.getOutAsString() : null - ); - } - - @SneakyThrows - public Process getProcess() { - return this.processSupplier.get(); - } - - public Long getProcessId() { - final var process = this.getProcess(); - if (process == null) { - return null; - } - return process.pid(); - } - - public void waitProcessToFinish() { - new Wait<>() - .infinityTimeout() - .ignoreException(IllegalArgumentException.class) - .until(() -> { - Validate.isTrue(this.isProcessFinished(), "Process not finished yet"); - return true; - }); - } - - private boolean isProcessFinished() { - return getProcess() != null && !getProcess().isAlive(); - } - - public Integer getProcessExitCodeWhenAvailable() { - try { - return getProcess().exitValue(); - } catch (IllegalThreadStateException e) { - return null; - } - } - } } diff --git a/src/main/java/com/mageddo/commons/exec/ExecutionValidationFailedException.java b/src/main/java/com/mageddo/commons/exec/ExecutionValidationFailedException.java index 562b9b0a1..482ded0ac 100644 --- a/src/main/java/com/mageddo/commons/exec/ExecutionValidationFailedException.java +++ b/src/main/java/com/mageddo/commons/exec/ExecutionValidationFailedException.java @@ -1,14 +1,14 @@ package com.mageddo.commons.exec; public class ExecutionValidationFailedException extends RuntimeException { - private final CommandLines.Result result; + private final Result result; - public ExecutionValidationFailedException(CommandLines.Result result) { + public ExecutionValidationFailedException(Result result) { super(String.format("error, code=%d, error=%s", result.getExitCode(), result.getOutAsString())); this.result = result; } - public CommandLines.Result result() { + public Result result() { return this.result; } diff --git a/src/main/java/com/mageddo/commons/exec/ProcessAccessibleDaemonExecutor.java b/src/main/java/com/mageddo/commons/exec/ProcessAccessibleDaemonExecutor.java new file mode 100644 index 000000000..16cf233bd --- /dev/null +++ b/src/main/java/com/mageddo/commons/exec/ProcessAccessibleDaemonExecutor.java @@ -0,0 +1,20 @@ +package com.mageddo.commons.exec; + +import lombok.Getter; +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DaemonExecutor; + +import java.io.File; +import java.io.IOException; +import java.util.Map; + +@Getter +class ProcessAccessibleDaemonExecutor extends DaemonExecutor { + + private Process process = null; + + @Override + protected Process launch(CommandLine command, Map env, File dir) throws IOException { + return this.process = super.launch(command, env, dir); + } +} diff --git a/src/main/java/com/mageddo/commons/exec/Request.java b/src/main/java/com/mageddo/commons/exec/Request.java new file mode 100644 index 000000000..987e2fca9 --- /dev/null +++ b/src/main/java/com/mageddo/commons/exec/Request.java @@ -0,0 +1,117 @@ +package com.mageddo.commons.exec; + +import com.mageddo.io.LogPrinter; +import lombok.Builder; +import lombok.NonNull; +import lombok.Value; +import lombok.experimental.NonFinal; +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.ExecuteResultHandler; +import org.apache.commons.exec.ExecuteStreamHandler; +import org.apache.commons.exec.ExecuteWatchdog; +import org.apache.commons.exec.PumpStreamHandler; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.time.Duration; +import java.util.Map; + +@Value +@Builder(toBuilder = true, builderClassName = "RequestBuilder", buildMethodName = "build0") +public class Request { + + @NonNull + private final CommandLine commandLine; + + private final Duration timeout; + + private final ExecuteResultHandler handler; + private Map env; + + @NonFinal + private boolean watchingOutput; + + @Builder.Default + private final Streams streams = Streams.builder() + .outAndErr(new ByteArrayOutputStream()) + .build(); + + public ExecuteStreamHandler getStreamHandler() { + return this.streams.toStreamHandler(); + } + + public Request printOutToLogsInBackground() { + if (this.watchingOutput) { + throw new IllegalStateException("Already watching output"); + } + this.watchingOutput = true; + LogPrinter.printInBackground(this.streams.outAndErr.getPipedIn()); + return this; + } + + public OutputStream getBestOut() { + return this.streams.getBestOriginalOutput(); + } + + public long getTimeoutInMillis() { + if (this.timeout == null) { + return ExecuteWatchdog.INFINITE_TIMEOUT; + } + return this.timeout.toMillis(); + } + + public static class RequestBuilder { + + private boolean printLogsInBackground = false; + + public Request build() { + final var request = this.build0(); + if (this.printLogsInBackground) { + request.printOutToLogsInBackground(); + } + return request; + } + + public RequestBuilder printLogsInBackground() { + this.printLogsInBackground = true; + return this; + } + } + + + @Value + @Builder(toBuilder = true, builderClassName = "StreamsBuilder") + public static class Streams { + + private final PipedStream outAndErr; + private final OutputStream out; + private final OutputStream err; + private final InputStream input; + + public PipedStream getBestOut() { + if (this.outAndErr != null) { + return this.outAndErr; + } + throw new UnsupportedOperationException(); + } + + public OutputStream getBestOriginalOutput() { + return this.getBestOut().getOriginalOut(); + } + + public static class StreamsBuilder { + public Streams.StreamsBuilder outAndErr(OutputStream outAndErr) { + this.outAndErr = new PipedStream(outAndErr); + return this; + } + } + + public ExecuteStreamHandler toStreamHandler() { + if (this.outAndErr != null) { + return new PumpStreamHandler(this.outAndErr); + } + return new PumpStreamHandler(this.out, this.err, this.input); + } + } +} diff --git a/src/main/java/com/mageddo/commons/exec/Result.java b/src/main/java/com/mageddo/commons/exec/Result.java new file mode 100644 index 000000000..62ea79063 --- /dev/null +++ b/src/main/java/com/mageddo/commons/exec/Result.java @@ -0,0 +1,93 @@ +package com.mageddo.commons.exec; + +import com.mageddo.wait.Wait; +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; +import lombok.SneakyThrows; +import lombok.ToString; +import org.apache.commons.exec.Executor; +import org.apache.commons.lang3.Validate; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.util.function.Supplier; + +@Getter +@Builder +@ToString(of = {"exitCode"}) +public class Result { + + @NonNull + private Request request; + + @NonNull + private Executor executor; + + @NonNull + private OutputStream out; + + @NonNull + private Supplier processSupplier; + + private Integer exitCode; + + public Result printOutToLogsInBackground() { + this.request.printOutToLogsInBackground(); + return this; + } + + public String getOutAsString() { + Validate.isTrue(this.out instanceof ByteArrayOutputStream, "Only ByteArrayOutputStream is supported"); + return this.out.toString(); + } + + public Result checkExecution() { + if (this.executor.isFailure(this.getExitCode())) { + throw new ExecutionValidationFailedException(this); + } + return this; + } + + public String toString(boolean printOut) { + return String.format( + "code=%d, out=%s", + this.exitCode, printOut ? this.getOutAsString() : null + ); + } + + @SneakyThrows + public Process getProcess() { + return this.processSupplier.get(); + } + + public Long getProcessId() { + final var process = this.getProcess(); + if (process == null) { + return null; + } + return process.pid(); + } + + public void waitProcessToFinish() { + new Wait<>() + .infinityTimeout() + .ignoreException(IllegalArgumentException.class) + .until(() -> { + Validate.isTrue(this.isProcessFinished(), "Process not finished yet"); + return true; + }); + } + + private boolean isProcessFinished() { + return getProcess() != null && !getProcess().isAlive(); + } + + public Integer getProcessExitCodeWhenAvailable() { + try { + return getProcess().exitValue(); + } catch (IllegalThreadStateException e) { + return null; + } + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java index 7e01da300..6816a43ad 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -2,6 +2,7 @@ import com.mageddo.commons.exec.CommandLines; import com.mageddo.commons.exec.NopResultHandler; +import com.mageddo.commons.exec.Request; import com.mageddo.dnsproxyserver.config.dataprovider.vo.ConfigEnv; import lombok.extern.slf4j.Slf4j; @@ -12,7 +13,7 @@ public class BinaryFromGradleTestsSandbox { public Instance run(Path configFile) { final var commandLine = DpsBinaryExecutableFinder.buildCommandLine(); - final var request = CommandLines.Request.builder() + final var request = Request.builder() .commandLine(commandLine) .handler(new NopResultHandler()) .env(Map.of(ConfigEnv.MG_CONFIG_FILE_PATH, configFile.toString())) diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java index ceaed4b72..731e5e140 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java @@ -1,6 +1,6 @@ package com.mageddo.dnsproxyserver.sandbox; -import com.mageddo.commons.exec.CommandLines; +import com.mageddo.commons.exec.Result; import com.mageddo.os.linux.kill.Kill; import lombok.Builder; import lombok.NonNull; @@ -14,9 +14,9 @@ public class Instance { @NonNull - CommandLines.Result result; + Result result; - public static Instance of(CommandLines.Result result) { + public static Instance of(Result result) { return Instance.builder() .result(result) .build() From 8660a11712f2ffbb2383a0dd38827d377189cedb Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 22:10:04 -0300 Subject: [PATCH 55/70] reduce native image optimization for int test to reduce build time --- build.gradle | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/build.gradle b/build.gradle index bd4269307..4e1cbb030 100644 --- a/build.gradle +++ b/build.gradle @@ -206,6 +206,7 @@ graalvmNative { mergeWithExisting = true } } + binaries { main { javaLauncher = javaToolchains.launcherFor { @@ -218,10 +219,21 @@ graalvmNative { verbose = true fallback = false buildArgs.add('-J-Xmx5G') + buildArgs.add("-O3") + + } + configureEach { + if(it.name == "intTest"){ + println "> configuring for: ${it.getName()}" + buildArgs.add("-Ob") + } } + test {} // nao funciona como está sendo usado o inttest + } + registerTestBinary("intTest") { usingSourceSet(sourceSets.test) forTestTask(intTest) From 74523857d2513797348633a3653f5a883d1b589b Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 22:16:03 -0300 Subject: [PATCH 56/70] fixing test --- .../templates/ConfigJsonFileTemplates.java | 33 ++++++++++++++++--- src/test/resources/configs-test/009.json | 22 ------------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/test/java/testing/templates/ConfigJsonFileTemplates.java b/src/test/java/testing/templates/ConfigJsonFileTemplates.java index af9c33c74..cc1963735 100644 --- a/src/test/java/testing/templates/ConfigJsonFileTemplates.java +++ b/src/test/java/testing/templates/ConfigJsonFileTemplates.java @@ -1,7 +1,6 @@ package testing.templates; import com.mageddo.net.SocketUtils; -import com.mageddo.utils.TestUtils; import lombok.SneakyThrows; import java.nio.file.Files; @@ -9,14 +8,40 @@ public class ConfigJsonFileTemplates { + public static final String RANDOM_PORTS_NO_DEFAULT_CUSTOM_LOCAL_DB_ENTRY = """ + { + "version": 2, + "webServerPort" : %d, + "dnsServerPort" : %d, + "defaultDns" : false, + "logLevel" : "TRACE", + "remoteDnsServers": [], + "envs": [ + { + "name": "", + "hostnames": [ + { + "id" : 1, + "type": "A", + "hostname": "%s", + "ip": "192.168.0.1", + "ttl": 255 + } + ] + } + ] + } + """; + public static Path withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(String host) { final var webServerPort = SocketUtils.findRandomFreePort(); final var dnsServerPort = SocketUtils.findRandomFreePort(); - return writeToTempPathReplacing("/configs-test/009.json", webServerPort, dnsServerPort, host); + return writeToTempPathReplacing( + RANDOM_PORTS_NO_DEFAULT_CUSTOM_LOCAL_DB_ENTRY, webServerPort, dnsServerPort, host + ); } - private static Path writeToTempPathReplacing(final String resourceTemplatePath, Object ... args) { - final var jsonTemplate = TestUtils.readString(resourceTemplatePath); + private static Path writeToTempPathReplacing(final String jsonTemplate, Object... args) { return writeToTempPath(jsonTemplate.formatted(args)); } diff --git a/src/test/resources/configs-test/009.json b/src/test/resources/configs-test/009.json index 04bb04488..e69de29bb 100644 --- a/src/test/resources/configs-test/009.json +++ b/src/test/resources/configs-test/009.json @@ -1,22 +0,0 @@ -{ - "version": 2, - "webServerPort" : %d, - "dnsServerPort" : %d, - "defaultDns" : false, - "logLevel" : "TRACE", - "remoteDnsServers": [], - "envs": [ - { - "name": "", - "hostnames": [ - { - "id" : 1, - "type": "A", - "hostname": "%s", - "ip": "192.168.0.1", - "ttl": 255 - } - ] - } - ] -} From 217af38ec952511fa8ddc3c54fe845e65b6cf3c4 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 22:16:40 -0300 Subject: [PATCH 57/70] unnecessary --- build.gradle | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 4e1cbb030..c4511c9e2 100644 --- a/build.gradle +++ b/build.gradle @@ -226,12 +226,10 @@ graalvmNative { configureEach { if(it.name == "intTest"){ println "> configuring for: ${it.getName()}" - buildArgs.add("-Ob") + buildArgs.add("-O3") } } - test {} // nao funciona como está sendo usado o inttest - } registerTestBinary("intTest") { From c430ab1ad7844389134a99c64c72d44030939c3e Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 22:19:03 -0300 Subject: [PATCH 58/70] clean code --- .../java/com/mageddo/dnsproxyserver/App.java | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/App.java b/src/main/java/com/mageddo/dnsproxyserver/App.java index 2f5469000..e372c8261 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/App.java +++ b/src/main/java/com/mageddo/dnsproxyserver/App.java @@ -82,15 +82,9 @@ void setupLogs() { } void startContext() { - this.createContext(); - - // start webserver - // start dns server - this.context.start(); - } - - private void createContext() { - this.context = Context.create(); + Context.create() + .start() + ; } void checkExitCommands() { @@ -122,10 +116,6 @@ int getDnsServerPort() { return getConfig().getDnsServerPort(); } - Context getContext() { - return context; - } - static class SystemExitException extends RuntimeException { public SystemExitException(String reason) { super(reason); From 253c6bb18cfeaa8e261c03668dbebd63651b9721 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 22:36:50 -0300 Subject: [PATCH 59/70] deleteing unnecessary file --- src/test/resources/configs-test/009.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/test/resources/configs-test/009.json diff --git a/src/test/resources/configs-test/009.json b/src/test/resources/configs-test/009.json deleted file mode 100644 index e69de29bb..000000000 From 01e616e00b30da552f8a2187daadc60f9fc2e975 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 22:45:34 -0300 Subject: [PATCH 60/70] release notes --- RELEASE-NOTES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index cfc674b97..51d4b9d28 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,3 +1,7 @@ +## 3.29.0 +* Implementing an IntTest which can validate the happy path of all DPS solvers, + being able to detect bugs like the fixed at 3.25.14 (6db82f50d54bd3f3aed15d7120c1963c0386abf4). + ## 3.28.0 * Specify from which source the config is coming to facilitate troubleshooting. #533 From bc0a01dc8c18df6c03f703e6e320ea57c5fe32ad Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 22:45:57 -0300 Subject: [PATCH 61/70] [Gradle Release Plugin] - new version commit: '3.29.0-snapshot'. --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 25497eff6..795042e99 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=3.27.0-snapshot +version=3.29.0-snapshot From 9ac2c148871aeef5e67cf51faf4bc0d404389f6c Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 22:48:31 -0300 Subject: [PATCH 62/70] Creating support for testing DPS really like a integration test, crating int test for solver remote happy pah --- .../sandbox/BinaryFromGradleTestsSandbox.java | 28 +++++++ .../sandbox/DpsBinaryExecutableFinder.java | 84 +++++++++++++++++++ .../dnsproxyserver/sandbox/Instance.java | 52 ++++++++++++ .../dnsproxyserver/sandbox/Sandbox.java | 9 ++ .../mageddo/dnsproxyserver/AppIntTest.java | 71 +++++++++++++++- .../DpsBinaryExecutableFinderIntTest.java | 31 +++++++ .../dnsproxyserver/sandbox/SandboxTest.java | 5 ++ 7 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java create mode 100644 src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java create mode 100644 src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java new file mode 100644 index 000000000..6816a43ad --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/BinaryFromGradleTestsSandbox.java @@ -0,0 +1,28 @@ +package com.mageddo.dnsproxyserver.sandbox; + +import com.mageddo.commons.exec.CommandLines; +import com.mageddo.commons.exec.NopResultHandler; +import com.mageddo.commons.exec.Request; +import com.mageddo.dnsproxyserver.config.dataprovider.vo.ConfigEnv; +import lombok.extern.slf4j.Slf4j; + +import java.nio.file.Path; +import java.util.Map; + +@Slf4j +public class BinaryFromGradleTestsSandbox { + public Instance run(Path configFile) { + final var commandLine = DpsBinaryExecutableFinder.buildCommandLine(); + final var request = Request.builder() + .commandLine(commandLine) + .handler(new NopResultHandler()) + .env(Map.of(ConfigEnv.MG_CONFIG_FILE_PATH, configFile.toString())) + .build(); + + final var result = CommandLines.exec(request) + .printOutToLogsInBackground(); + + return Instance.of(result); + } + +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java new file mode 100644 index 000000000..a446bfc8e --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinder.java @@ -0,0 +1,84 @@ +package com.mageddo.dnsproxyserver.sandbox; + +import com.mageddo.utils.Runtime; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.exec.CommandLine; +import org.apache.commons.lang3.Validate; +import org.graalvm.nativeimage.ImageInfo; + +import java.nio.file.Files; +import java.nio.file.Path; + +@Slf4j +public class DpsBinaryExecutableFinder { + + public static CommandLine buildCommandLine() { + return new DpsBinaryExecutableFinder().buildCommandLineForBestExecutable(); + } + + private CommandLine buildCommandLineForBestExecutable() { + final var executablePath = this.findBestExecutablePath(); + if (ImageInfo.inImageRuntimeCode()) { + return new CommandLine(executablePath.toString()); + } + final var javaCommandPath = this.findJavaCommand(); + return new CommandLine(javaCommandPath) + .addArgument("-jar") + .addArgument(executablePath.toFile().toString()); + } + + private String findJavaCommand() { + return ProcessHandle.current() + .info() + .command() + .orElseThrow(() -> new IllegalStateException("Couldn't find current java process command")) + ; + } + + public static Path findPath() { + return new DpsBinaryExecutableFinder().findBestExecutablePath(); + } + + Path findBestExecutablePath() { + if (ImageInfo.inImageRuntimeCode()) { + return findBuiltNativeExecutablePath(); + } + return findBuiltJarPath(); + } + + Path findBuiltNativeExecutablePath() { + final var buildPath = this.findBuildPath(); + final var path = buildPath.resolve("native/nativeIntTestCompile/dns-proxy-server-tests"); + Validate.isTrue(Files.exists(path), "Native executable not found at: " + path); + return path; + } + + Path findBuiltJarPath() { + final var buildPath = this.findBuildPath(); + final var libsPath = buildPath.resolve("libs"); + return findFirstMatchInPath(libsPath); + } + + @SneakyThrows + private Path findFirstMatchInPath(Path libsPath) { + try (var stream = Files.list(libsPath)) { + return stream + .filter(path -> path.toString().endsWith("-all.jar")) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Unable to find fat jar at libs path")); + } + } + + private Path findBuildPath() { + var path = Runtime.getRunningDir(); + while (path != null) { + if (path.endsWith("build")) { + log.trace("buildPath={}", path); + return path; + } + path = path.getParent(); + } + return null; + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java new file mode 100644 index 000000000..731e5e140 --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java @@ -0,0 +1,52 @@ +package com.mageddo.dnsproxyserver.sandbox; + +import com.mageddo.commons.exec.Result; +import com.mageddo.os.linux.kill.Kill; +import lombok.Builder; +import lombok.NonNull; +import lombok.Value; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.Validate; + +@Slf4j +@Value +@Builder +public class Instance { + + @NonNull + Result result; + + public static Instance of(Result result) { + return Instance.builder() + .result(result) + .build() + ; + } + + + public void sendHealthCheckSignal() { + this.sendHealthCheckSignalValidatingResult(); + this.validateIsHealth(); + } + + private void validateIsHealth() { + final var out = this.getResult().getOutAsString(); + final var isHealth = out.contains("dps.healthCheck.health=true"); + Validate.isTrue(isHealth, "App not health yet, content=%s", out); + } + + private void sendHealthCheckSignalValidatingResult() { + final var processId = this.getProcessId(); + Validate.isTrue(processId != null, "Process not started yet"); + log.trace("is alive: {}, exitcode={}", this.result.getProcess().isAlive(), this.result.getProcessExitCodeWhenAvailable()); + Kill.sendSignal(10, processId); + } + + private Long getProcessId() { + return this.result.getProcessId(); + } + + public void watchOutputInDaemonThread() { + getResult().printOutToLogsInBackground(); + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java new file mode 100644 index 000000000..4196377a9 --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Sandbox.java @@ -0,0 +1,9 @@ +package com.mageddo.dnsproxyserver.sandbox; + +import java.nio.file.Path; + +public class Sandbox { + public static Instance runFromGradleTests(Path configFile) { + return new BinaryFromGradleTestsSandbox().run(configFile); + } +} diff --git a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java index d9c1db6e6..2dd6751a0 100644 --- a/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java +++ b/src/test/java/com/mageddo/dnsproxyserver/AppIntTest.java @@ -1,22 +1,34 @@ package com.mageddo.dnsproxyserver; import com.mageddo.commons.concurrent.Threads; +import com.mageddo.commons.exec.ProcessesWatchDog; import com.mageddo.dns.utils.Messages; import com.mageddo.dnsproxyserver.config.application.Configs; +import com.mageddo.dnsproxyserver.config.dataprovider.JsonConfigs; +import com.mageddo.dnsproxyserver.config.dataprovider.vo.ConfigJson; +import com.mageddo.dnsproxyserver.sandbox.Instance; +import com.mageddo.dnsproxyserver.sandbox.Sandbox; import com.mageddo.dnsproxyserver.server.Starter; import com.mageddo.dnsproxyserver.solver.SimpleResolver; import com.mageddo.dnsproxyserver.utils.Ips; +import com.mageddo.net.IpAddr; import com.mageddo.utils.Executors; import lombok.SneakyThrows; +import lombok.Value; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.xbill.DNS.Message; import testing.templates.ConfigFlagArgsTemplates; +import testing.templates.ConfigJsonFileTemplates; +import java.nio.file.Path; import java.time.Duration; +import java.util.Arrays; +import java.util.concurrent.ExecutorService; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @Slf4j @@ -29,12 +41,13 @@ void beforeEach() { } @AfterAll - static void afterAll(){ + static void afterAll() { Starter.setMustStartFlagActive(false); + ProcessesWatchDog.instance().killAllProcesses(); } @Test - void appMustStartAndQuerySampleWithSuccess() { + void appMustStartAndQuerySampleWithSuccessFromLocalDbSolver() { final var hostToQuery = "dps-sample.dev"; final var args = ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDns(); @@ -51,13 +64,67 @@ void appMustStartAndQuerySampleWithSuccess() { assertTrue(Messages.isSuccess(res)); } + } + + @Test + void mustQueryRemoteSolverPassingThroughAllModulesAndGetSuccess() { + + final var hostToQuery = "dps-int-test.dev"; + + try (final var executor = Executors.newThreadExecutor()) { + + final var serverAppConfig = buildAndStartServerApp(hostToQuery); + final var clientApp = buildClientAppAndWait(executor, serverAppConfig.getDnsServerPort()); + + final var port = clientApp.getDnsServerPort(); + final var res = queryStartedServer(port, hostToQuery); + + assertTrue(Messages.isSuccess(res)); + assertEquals("192.168.0.1", Messages.findAnswerRawIP(res)); + + } } + private static App buildClientAppAndWait(ExecutorService executor, Integer serverPort) { + final var remoteAddr = IpAddr.of("127.0.0.1", serverPort); + return buildAppAndWait(executor, ConfigFlagArgsTemplates.withRandomPortsAndNotAsDefaultDnsUsingRemote(remoteAddr)); + } + + private static Result buildAndStartServerApp(String hostToQuery) { + final var configFile = ConfigJsonFileTemplates.withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(hostToQuery); + final var instance = Sandbox.runFromGradleTests(configFile); + return Result.of(configFile, instance); + } + + private static App buildAppAndWait(ExecutorService executor, final String[] params) { + log.debug("app={}", Arrays.toString(params)); + final var app = new App(params); + executor.submit(app::start); + Threads.sleep(Duration.ofSeconds(2)); + return app; + } + @SneakyThrows static Message queryStartedServer(Integer port, String host) { final var dnsServerAddress = Ips.getAnyLocalAddress(port); final var dnsClient = new SimpleResolver(dnsServerAddress); return dnsClient.send(Messages.aQuestion(host)); } + + @Value + static class Result { + + private final ConfigJson config; + private final Instance instance; + + public static Result of(Path configFile, Instance instance) { + return new Result(JsonConfigs.loadConfig(configFile), instance); + } + + public Integer getDnsServerPort() { + return this.config.getDnsServerPort(); + } + + } } diff --git a/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java b/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java new file mode 100644 index 000000000..b6e8a6ec0 --- /dev/null +++ b/src/test/java/com/mageddo/dnsproxyserver/sandbox/DpsBinaryExecutableFinderIntTest.java @@ -0,0 +1,31 @@ +package com.mageddo.dnsproxyserver.sandbox; + +import org.graalvm.nativeimage.ImageInfo; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeFalse; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +class DpsBinaryExecutableFinderIntTest { + + @Test + void mustFindDpsNativeExecutablePath(){ + assumeTrue(ImageInfo.inImageRuntimeCode()); + + final var found = DpsBinaryExecutableFinder.findPath(); + + assertTrue(found.toString().endsWith("-tests")); + } + + @Test + void mustFindDpsJarPath(){ + assumeFalse(ImageInfo.inImageRuntimeCode()); + + final var found = DpsBinaryExecutableFinder.findPath(); + + assertTrue(found.toString().endsWith(".jar")); + } + + +} diff --git a/src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java b/src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java new file mode 100644 index 000000000..a1ddfc758 --- /dev/null +++ b/src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java @@ -0,0 +1,5 @@ +package com.mageddo.dnsproxyserver.sandbox; + +class SandboxTest { + +} From 9816e333d12fed978f9a065b984b5a10c8cf2ffb Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 22:50:06 -0300 Subject: [PATCH 63/70] clean code --- .../dnsproxyserver/sandbox/Instance.java | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java index 731e5e140..45648fe65 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java +++ b/src/main/java/com/mageddo/dnsproxyserver/sandbox/Instance.java @@ -1,12 +1,10 @@ package com.mageddo.dnsproxyserver.sandbox; import com.mageddo.commons.exec.Result; -import com.mageddo.os.linux.kill.Kill; import lombok.Builder; import lombok.NonNull; import lombok.Value; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.Validate; @Slf4j @Value @@ -22,31 +20,4 @@ public static Instance of(Result result) { .build() ; } - - - public void sendHealthCheckSignal() { - this.sendHealthCheckSignalValidatingResult(); - this.validateIsHealth(); - } - - private void validateIsHealth() { - final var out = this.getResult().getOutAsString(); - final var isHealth = out.contains("dps.healthCheck.health=true"); - Validate.isTrue(isHealth, "App not health yet, content=%s", out); - } - - private void sendHealthCheckSignalValidatingResult() { - final var processId = this.getProcessId(); - Validate.isTrue(processId != null, "Process not started yet"); - log.trace("is alive: {}, exitcode={}", this.result.getProcess().isAlive(), this.result.getProcessExitCodeWhenAvailable()); - Kill.sendSignal(10, processId); - } - - private Long getProcessId() { - return this.result.getProcessId(); - } - - public void watchOutputInDaemonThread() { - getResult().printOutToLogsInBackground(); - } } From 7df2fc008c712d00c67eb12b3a7a541e962f95d8 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 22:50:44 -0300 Subject: [PATCH 64/70] clean code --- .../java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java diff --git a/src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java b/src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java deleted file mode 100644 index a1ddfc758..000000000 --- a/src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.mageddo.dnsproxyserver.sandbox; - -class SandboxTest { - -} From 54f77da4a99348b3c23443dc310f1d2eaa992034 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 22:52:40 -0300 Subject: [PATCH 65/70] configuring templates --- .../templates/ConfigJsonFileTemplates.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/test/java/testing/templates/ConfigJsonFileTemplates.java diff --git a/src/test/java/testing/templates/ConfigJsonFileTemplates.java b/src/test/java/testing/templates/ConfigJsonFileTemplates.java new file mode 100644 index 000000000..cc1963735 --- /dev/null +++ b/src/test/java/testing/templates/ConfigJsonFileTemplates.java @@ -0,0 +1,53 @@ +package testing.templates; + +import com.mageddo.net.SocketUtils; +import lombok.SneakyThrows; + +import java.nio.file.Files; +import java.nio.file.Path; + +public class ConfigJsonFileTemplates { + + public static final String RANDOM_PORTS_NO_DEFAULT_CUSTOM_LOCAL_DB_ENTRY = """ + { + "version": 2, + "webServerPort" : %d, + "dnsServerPort" : %d, + "defaultDns" : false, + "logLevel" : "TRACE", + "remoteDnsServers": [], + "envs": [ + { + "name": "", + "hostnames": [ + { + "id" : 1, + "type": "A", + "hostname": "%s", + "ip": "192.168.0.1", + "ttl": 255 + } + ] + } + ] + } + """; + + public static Path withRandomPortsAndNotAsDefaultDnsAndCustomLocalDBEntry(String host) { + final var webServerPort = SocketUtils.findRandomFreePort(); + final var dnsServerPort = SocketUtils.findRandomFreePort(); + return writeToTempPathReplacing( + RANDOM_PORTS_NO_DEFAULT_CUSTOM_LOCAL_DB_ENTRY, webServerPort, dnsServerPort, host + ); + } + + private static Path writeToTempPathReplacing(final String jsonTemplate, Object... args) { + return writeToTempPath(jsonTemplate.formatted(args)); + } + + @SneakyThrows + private static Path writeToTempPath(String content) { + final var config = Files.createTempFile("config", ".json"); + return Files.writeString(config, content); + } +} From 66f4b3793c1bf488cd878f07f1059cad3373668f Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 22:53:16 -0300 Subject: [PATCH 66/70] configuring templates --- .../templates/ConfigFlagArgsTemplates.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/test/java/testing/templates/ConfigFlagArgsTemplates.java b/src/test/java/testing/templates/ConfigFlagArgsTemplates.java index 60e62c651..674b2f75a 100644 --- a/src/test/java/testing/templates/ConfigFlagArgsTemplates.java +++ b/src/test/java/testing/templates/ConfigFlagArgsTemplates.java @@ -1,8 +1,27 @@ package testing.templates; +import com.mageddo.dnsproxyserver.config.dataprovider.vo.ConfigJson; +import com.mageddo.net.IpAddr; import com.mageddo.net.SocketUtils; +import lombok.Builder; +import lombok.SneakyThrows; +import lombok.Value; +import lombok.experimental.Accessors; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; public class ConfigFlagArgsTemplates { + + public static String[] withRandomPortsAndNotAsDefaultDnsUsingRemote(IpAddr addr) { + final var configPath = makeConfigFileRandomPortAndCustomRemote(addr); + return new String[]{ + "--conf-path=" + configPath.toString() + }; + } + public static String[] withRandomPortsAndNotAsDefaultDns() { final var webServerPort = SocketUtils.findRandomFreePort(); final var dnsServerPort = SocketUtils.findRandomFreePort(); @@ -15,6 +34,29 @@ public static String[] withRandomPortsAndNotAsDefaultDns() { }; } + @SneakyThrows + private static Path makeConfigFileRandomPortAndCustomRemote(IpAddr remoteAddr) { + final var webServerPort = SocketUtils.findRandomFreePort(); + final var dnsServerPort = SocketUtils.findRandomFreePort(); + final var configJsonContent = """ + { + "version": 2, + "webServerPort" : %d, + "dnsServerPort" : %d, + "defaultDns" : false, + "logLevel" : "TRACE", + "remoteDnsServers": ["%s"], + "envs": [] + } + """.formatted(webServerPort, dnsServerPort, remoteAddr.toString()); + return writeToTempPath(configJsonContent); + } + + private static Path writeToTempPath(String content) throws IOException { + final var config = Files.createTempFile("config", ".json"); + return Files.writeString(config, content); + } + public static String[] withConfigFilePath() { return new String[]{ "--conf-path=flag-relative-path/flag-config.json" @@ -24,4 +66,18 @@ public static String[] withConfigFilePath() { public static String[] empty() { return new String[]{}; } + + @Value + @Builder + @Accessors(fluent = true) + public static class Config { + + private String[] args; + private ConfigJson config; + private Map envs; + + public Integer getDnsServerPort() { + return config().getDnsServerPort(); + } + } } From 14fc70386cc36e59e3ba506f647910e7808e9cce Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 22:54:01 -0300 Subject: [PATCH 67/70] option to get answer ip --- src/main/java/com/mageddo/dns/utils/Messages.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/mageddo/dns/utils/Messages.java b/src/main/java/com/mageddo/dns/utils/Messages.java index 8780eef15..e4827453d 100644 --- a/src/main/java/com/mageddo/dns/utils/Messages.java +++ b/src/main/java/com/mageddo/dns/utils/Messages.java @@ -301,4 +301,8 @@ public static HostnameQuery toHostnameQuery(Message query) { public static boolean isSuccess(Message res) { return res.getRcode() == Rcode.NOERROR; } + + public static String findAnswerRawIP(Message res) { + return findFirstAnswerRecord(res).rdataToString(); + } } From 998e302d148d27bfdfb40299e7a0d722dbc1fac6 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 23:21:43 -0300 Subject: [PATCH 68/70] clean code --- .../java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java diff --git a/src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java b/src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java deleted file mode 100644 index a1ddfc758..000000000 --- a/src/test/java/com/mageddo/dnsproxyserver/sandbox/SandboxTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.mageddo.dnsproxyserver.sandbox; - -class SandboxTest { - -} From 9b9e102a502facbbce5d5b75c0f6cf2e7d170507 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 23:24:01 -0300 Subject: [PATCH 69/70] deleting healthcheck feature --- .../dnsproxyserver/di/module/ModuleEager.java | 10 +--- .../healthcheck/HealthCheck.java | 16 ----- .../HealthCheckSignalEntrypoint.java | 36 ------------ .../HealthCheckStreamEntrypoint.java | 18 ------ .../in/entrypoint/InputStreamEntrypoint.java | 58 ------------------- .../HealthCheckSignalEntrypointTest.java | 39 ------------- 6 files changed, 2 insertions(+), 175 deletions(-) delete mode 100644 src/main/java/com/mageddo/dnsproxyserver/healthcheck/HealthCheck.java delete mode 100644 src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java delete mode 100644 src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckStreamEntrypoint.java delete mode 100644 src/main/java/com/mageddo/dnsproxyserver/in/entrypoint/InputStreamEntrypoint.java delete mode 100644 src/test/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypointTest.java diff --git a/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java b/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java index ec268d7d7..b7326a34f 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java +++ b/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java @@ -1,8 +1,6 @@ package com.mageddo.dnsproxyserver.di.module; import com.mageddo.di.Eager; -import com.mageddo.dnsproxyserver.healthcheck.entrypoint.HealthCheckSignalEntrypoint; -import com.mageddo.dnsproxyserver.in.entrypoint.InputStreamEntrypoint; import dagger.Module; import dagger.Provides; import dagger.multibindings.ElementsIntoSet; @@ -15,11 +13,7 @@ public class ModuleEager { @Provides @Singleton @ElementsIntoSet - Set beans( - HealthCheckSignalEntrypoint b1, InputStreamEntrypoint b2 - ) { - return Set.of( - b1, b2 - ); + Set beans() { + return Set.of(); } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/HealthCheck.java b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/HealthCheck.java deleted file mode 100644 index 93f352c5c..000000000 --- a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/HealthCheck.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.mageddo.dnsproxyserver.healthcheck; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import javax.inject.Inject; -import javax.inject.Singleton; - -@Slf4j -@Singleton -@RequiredArgsConstructor(onConstructor = @__({@Inject})) -public class HealthCheck { - public boolean isHealth(){ - return true; - } -} diff --git a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java deleted file mode 100644 index aa55fe52a..000000000 --- a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.mageddo.dnsproxyserver.healthcheck.entrypoint; - -import com.mageddo.di.Eager; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import sun.misc.Signal; - -import javax.inject.Inject; -import javax.inject.Singleton; - -@Slf4j -@Singleton -@RequiredArgsConstructor(onConstructor = @__({@Inject})) -public class HealthCheckSignalEntrypoint implements Eager { - - private static final String USER_DEFINED_SIGNAL = "USR1"; - private final HealthCheckStreamEntrypoint streamEntrypoint; - - @Override - public void run() { - this.safeRegisterHandler(); - } - - void safeRegisterHandler() { - try { - this.registerHandler(); - } catch (Throwable t){ - log.warn("status=couldntRegisterHandler, msg={}", t.getMessage(), t); - } - } - - void registerHandler() { - Signal.handle(new Signal(USER_DEFINED_SIGNAL), sig -> this.streamEntrypoint.printHealthCheck()); - log.debug("status=healthCheckSignalRegistered, signal={}", USER_DEFINED_SIGNAL); - } -} diff --git a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckStreamEntrypoint.java b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckStreamEntrypoint.java deleted file mode 100644 index c482959a4..000000000 --- a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckStreamEntrypoint.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.mageddo.dnsproxyserver.healthcheck.entrypoint; - -import com.mageddo.dnsproxyserver.healthcheck.HealthCheck; -import lombok.RequiredArgsConstructor; - -import javax.inject.Inject; -import javax.inject.Singleton; - -@Singleton -@RequiredArgsConstructor(onConstructor = @__({@Inject})) -public class HealthCheckStreamEntrypoint { - - private final HealthCheck healthCheck; - - public void printHealthCheck() { - System.out.printf("dps.healthCheck.health=%b%n", this.healthCheck.isHealth()); - } -} diff --git a/src/main/java/com/mageddo/dnsproxyserver/in/entrypoint/InputStreamEntrypoint.java b/src/main/java/com/mageddo/dnsproxyserver/in/entrypoint/InputStreamEntrypoint.java deleted file mode 100644 index 8e7338b90..000000000 --- a/src/main/java/com/mageddo/dnsproxyserver/in/entrypoint/InputStreamEntrypoint.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.mageddo.dnsproxyserver.in.entrypoint; - -import com.mageddo.commons.concurrent.Threads; -import com.mageddo.di.Eager; -import com.mageddo.dnsproxyserver.healthcheck.entrypoint.HealthCheckStreamEntrypoint; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import javax.inject.Inject; -import javax.inject.Singleton; -import java.util.NoSuchElementException; -import java.util.Scanner; - -@Slf4j -@Singleton -@RequiredArgsConstructor(onConstructor = @__({@Inject})) -public class InputStreamEntrypoint implements Eager { - - private final HealthCheckStreamEntrypoint healthCheckStreamEntrypoint; - private boolean inShell; - - @Override - public void run() { - Thread.ofVirtual() - .start(this::readInputStream) - ; - } - - private void readInputStream() { - log.debug("status=scanningInputStream"); - final var scanner = new Scanner(System.in); - while (true) { - final var line = safeReadLine(scanner); - if (line == null) { - break; - } - this.checkHealthCheck(line); - Threads.sleep(1000 / 15); - } - } - - private static String safeReadLine(Scanner scanner) { - try { - return scanner.nextLine(); - } catch (NoSuchElementException e) { - return null; - } - } - - private void checkHealthCheck(String line) { - if (line.equals("shell")) { - this.inShell = true; - } - if (this.inShell && line.equals("dps.healthCheck.health")) { - this.healthCheckStreamEntrypoint.printHealthCheck(); - } - } -} diff --git a/src/test/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypointTest.java b/src/test/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypointTest.java deleted file mode 100644 index 106fc9983..000000000 --- a/src/test/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypointTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.mageddo.dnsproxyserver.healthcheck.entrypoint; - -import com.mageddo.dnsproxyserver.healthcheck.HealthCheck; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; - -import static org.mockito.Mockito.doThrow; - -@ExtendWith(MockitoExtension.class) -class HealthCheckSignalEntrypointTest { - - @Mock - HealthCheck healthCheck; - - @Spy - @InjectMocks - HealthCheckSignalEntrypoint entrypoint; - - @Test - void mustRegisterHandler() { - this.entrypoint.registerHandler(); - } - - @Test - void mustCatchFatalErrorsWhenRegisteringHandler() { - - doThrow(new AssertionError("mocked error")) - .when(this.entrypoint) - .registerHandler(); - - this.entrypoint.safeRegisterHandler(); - - } - -} From d8ae984d86f6ba8caacbbbfadc3192e9bfcf2d63 Mon Sep 17 00:00:00 2001 From: Elvis de Freitas Date: Wed, 4 Sep 2024 23:24:44 -0300 Subject: [PATCH 70/70] Revert "deleting healthcheck feature" This reverts commit 9b9e102a502facbbce5d5b75c0f6cf2e7d170507. --- .../dnsproxyserver/di/module/ModuleEager.java | 10 +++- .../healthcheck/HealthCheck.java | 16 +++++ .../HealthCheckSignalEntrypoint.java | 36 ++++++++++++ .../HealthCheckStreamEntrypoint.java | 18 ++++++ .../in/entrypoint/InputStreamEntrypoint.java | 58 +++++++++++++++++++ .../HealthCheckSignalEntrypointTest.java | 39 +++++++++++++ 6 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/mageddo/dnsproxyserver/healthcheck/HealthCheck.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckStreamEntrypoint.java create mode 100644 src/main/java/com/mageddo/dnsproxyserver/in/entrypoint/InputStreamEntrypoint.java create mode 100644 src/test/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypointTest.java diff --git a/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java b/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java index b7326a34f..ec268d7d7 100644 --- a/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java +++ b/src/main/java/com/mageddo/dnsproxyserver/di/module/ModuleEager.java @@ -1,6 +1,8 @@ package com.mageddo.dnsproxyserver.di.module; import com.mageddo.di.Eager; +import com.mageddo.dnsproxyserver.healthcheck.entrypoint.HealthCheckSignalEntrypoint; +import com.mageddo.dnsproxyserver.in.entrypoint.InputStreamEntrypoint; import dagger.Module; import dagger.Provides; import dagger.multibindings.ElementsIntoSet; @@ -13,7 +15,11 @@ public class ModuleEager { @Provides @Singleton @ElementsIntoSet - Set beans() { - return Set.of(); + Set beans( + HealthCheckSignalEntrypoint b1, InputStreamEntrypoint b2 + ) { + return Set.of( + b1, b2 + ); } } diff --git a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/HealthCheck.java b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/HealthCheck.java new file mode 100644 index 000000000..93f352c5c --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/HealthCheck.java @@ -0,0 +1,16 @@ +package com.mageddo.dnsproxyserver.healthcheck; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Slf4j +@Singleton +@RequiredArgsConstructor(onConstructor = @__({@Inject})) +public class HealthCheck { + public boolean isHealth(){ + return true; + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java new file mode 100644 index 000000000..aa55fe52a --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypoint.java @@ -0,0 +1,36 @@ +package com.mageddo.dnsproxyserver.healthcheck.entrypoint; + +import com.mageddo.di.Eager; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import sun.misc.Signal; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Slf4j +@Singleton +@RequiredArgsConstructor(onConstructor = @__({@Inject})) +public class HealthCheckSignalEntrypoint implements Eager { + + private static final String USER_DEFINED_SIGNAL = "USR1"; + private final HealthCheckStreamEntrypoint streamEntrypoint; + + @Override + public void run() { + this.safeRegisterHandler(); + } + + void safeRegisterHandler() { + try { + this.registerHandler(); + } catch (Throwable t){ + log.warn("status=couldntRegisterHandler, msg={}", t.getMessage(), t); + } + } + + void registerHandler() { + Signal.handle(new Signal(USER_DEFINED_SIGNAL), sig -> this.streamEntrypoint.printHealthCheck()); + log.debug("status=healthCheckSignalRegistered, signal={}", USER_DEFINED_SIGNAL); + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckStreamEntrypoint.java b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckStreamEntrypoint.java new file mode 100644 index 000000000..c482959a4 --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckStreamEntrypoint.java @@ -0,0 +1,18 @@ +package com.mageddo.dnsproxyserver.healthcheck.entrypoint; + +import com.mageddo.dnsproxyserver.healthcheck.HealthCheck; +import lombok.RequiredArgsConstructor; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +@RequiredArgsConstructor(onConstructor = @__({@Inject})) +public class HealthCheckStreamEntrypoint { + + private final HealthCheck healthCheck; + + public void printHealthCheck() { + System.out.printf("dps.healthCheck.health=%b%n", this.healthCheck.isHealth()); + } +} diff --git a/src/main/java/com/mageddo/dnsproxyserver/in/entrypoint/InputStreamEntrypoint.java b/src/main/java/com/mageddo/dnsproxyserver/in/entrypoint/InputStreamEntrypoint.java new file mode 100644 index 000000000..8e7338b90 --- /dev/null +++ b/src/main/java/com/mageddo/dnsproxyserver/in/entrypoint/InputStreamEntrypoint.java @@ -0,0 +1,58 @@ +package com.mageddo.dnsproxyserver.in.entrypoint; + +import com.mageddo.commons.concurrent.Threads; +import com.mageddo.di.Eager; +import com.mageddo.dnsproxyserver.healthcheck.entrypoint.HealthCheckStreamEntrypoint; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.NoSuchElementException; +import java.util.Scanner; + +@Slf4j +@Singleton +@RequiredArgsConstructor(onConstructor = @__({@Inject})) +public class InputStreamEntrypoint implements Eager { + + private final HealthCheckStreamEntrypoint healthCheckStreamEntrypoint; + private boolean inShell; + + @Override + public void run() { + Thread.ofVirtual() + .start(this::readInputStream) + ; + } + + private void readInputStream() { + log.debug("status=scanningInputStream"); + final var scanner = new Scanner(System.in); + while (true) { + final var line = safeReadLine(scanner); + if (line == null) { + break; + } + this.checkHealthCheck(line); + Threads.sleep(1000 / 15); + } + } + + private static String safeReadLine(Scanner scanner) { + try { + return scanner.nextLine(); + } catch (NoSuchElementException e) { + return null; + } + } + + private void checkHealthCheck(String line) { + if (line.equals("shell")) { + this.inShell = true; + } + if (this.inShell && line.equals("dps.healthCheck.health")) { + this.healthCheckStreamEntrypoint.printHealthCheck(); + } + } +} diff --git a/src/test/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypointTest.java b/src/test/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypointTest.java new file mode 100644 index 000000000..106fc9983 --- /dev/null +++ b/src/test/java/com/mageddo/dnsproxyserver/healthcheck/entrypoint/HealthCheckSignalEntrypointTest.java @@ -0,0 +1,39 @@ +package com.mageddo.dnsproxyserver.healthcheck.entrypoint; + +import com.mageddo.dnsproxyserver.healthcheck.HealthCheck; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.Mockito.doThrow; + +@ExtendWith(MockitoExtension.class) +class HealthCheckSignalEntrypointTest { + + @Mock + HealthCheck healthCheck; + + @Spy + @InjectMocks + HealthCheckSignalEntrypoint entrypoint; + + @Test + void mustRegisterHandler() { + this.entrypoint.registerHandler(); + } + + @Test + void mustCatchFatalErrorsWhenRegisteringHandler() { + + doThrow(new AssertionError("mocked error")) + .when(this.entrypoint) + .registerHandler(); + + this.entrypoint.safeRegisterHandler(); + + } + +}