From 7a613da3cc19507f181c6019a8630eec211ed2b3 Mon Sep 17 00:00:00 2001 From: petruki <31597636+petruki@users.noreply.github.com> Date: Tue, 14 Oct 2025 19:44:44 -0700 Subject: [PATCH] feat: improved async performance with thread-safe type --- .../client/model/AsyncSwitcher.java | 2 +- .../client/model/SwitcherBuilder.java | 9 +----- .../client/model/SwitcherRequest.java | 30 ++++++++++++++----- .../service/local/ClientLocalService.java | 20 ++++++++----- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/switcherapi/client/model/AsyncSwitcher.java b/src/main/java/com/switcherapi/client/model/AsyncSwitcher.java index 60ea93e..b3b9752 100644 --- a/src/main/java/com/switcherapi/client/model/AsyncSwitcher.java +++ b/src/main/java/com/switcherapi/client/model/AsyncSwitcher.java @@ -46,7 +46,7 @@ public AsyncSwitcher(final Switcher switcher, long delay) { * Validate if next run is ready to be performed, otherwise it will skip and delegate the * Switcher result for the Switcher history execution. */ - public synchronized void execute() { + public void execute() { SwitcherUtils.debug(logger, "nextRun: {} - currentTimeMillis: {}", nextRun, System.currentTimeMillis()); if (nextRun < System.currentTimeMillis()) { diff --git a/src/main/java/com/switcherapi/client/model/SwitcherBuilder.java b/src/main/java/com/switcherapi/client/model/SwitcherBuilder.java index 70d325f..46242fb 100644 --- a/src/main/java/com/switcherapi/client/model/SwitcherBuilder.java +++ b/src/main/java/com/switcherapi/client/model/SwitcherBuilder.java @@ -15,8 +15,6 @@ public abstract class SwitcherBuilder implements Switcher { protected final SwitcherProperties properties; - - protected final Map, SwitcherResult> historyExecution; protected long delay; @@ -32,7 +30,6 @@ public abstract class SwitcherBuilder implements Switcher { protected SwitcherBuilder(final SwitcherProperties properties) { this.properties = properties; - this.historyExecution = new HashMap<>(); this.entry = new ArrayList<>(); this.delay = 0; } @@ -42,11 +39,7 @@ protected SwitcherBuilder(final SwitcherProperties properties) { * * @return {@link SwitcherBuilder} */ - public SwitcherBuilder flush() { - this.historyExecution.clear(); - this.entry.clear(); - return this; - } + public abstract SwitcherBuilder flush(); /** * Skip API calls given a delay time diff --git a/src/main/java/com/switcherapi/client/model/SwitcherRequest.java b/src/main/java/com/switcherapi/client/model/SwitcherRequest.java index b698970..ab8591f 100644 --- a/src/main/java/com/switcherapi/client/model/SwitcherRequest.java +++ b/src/main/java/com/switcherapi/client/model/SwitcherRequest.java @@ -6,7 +6,11 @@ import com.switcherapi.client.exception.SwitcherException; import com.switcherapi.client.test.SwitcherBypass; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; /** * SwitcherRequest is the entry point to evaluate criteria and return the result. @@ -20,6 +24,8 @@ */ public final class SwitcherRequest extends SwitcherBuilder { + private final ConcurrentHashMap, SwitcherResult> historyExecution; + private final SwitcherExecutor switcherExecutor; private final String switcherKey; @@ -39,6 +45,7 @@ public SwitcherRequest(final String switcherKey, super(switcherProperties); this.switcherExecutor = switcherExecutor; this.switcherKey = switcherKey; + this.historyExecution = new ConcurrentHashMap<>(); } @Override @@ -61,7 +68,14 @@ public SwitcherRequest prepareEntry(final Entry entry, final boolean add) { public SwitcherRequest prepareEntry(final Entry entry) { return this.prepareEntry(entry, false); } - + + @Override + public SwitcherBuilder flush() { + this.entry.clear(); + this.historyExecution.clear(); + return this; + } + @Override public boolean isItOn() throws SwitcherException { final SwitcherResult response = submit(); @@ -80,9 +94,9 @@ public SwitcherResult submit() throws SwitcherException { } asyncSwitcher.execute(); - final Optional response = getFromHistory(); - if (response.isPresent()) { - return response.get(); + final SwitcherResult response = getFromHistory(); + if (Objects.nonNull(response)) { + return response; } } @@ -117,7 +131,7 @@ public List getEntry() { @Override public SwitcherResult getLastExecutionResult() { - return getFromHistory().orElse(null); + return getFromHistory(); } public boolean isBypassMetrics() { @@ -128,8 +142,8 @@ private boolean canUseAsync() { return super.delay > 0 && !this.historyExecution.isEmpty(); } - private Optional getFromHistory() { - return Optional.ofNullable(historyExecution.get(entry)); + private SwitcherResult getFromHistory() { + return historyExecution.get(entry); } @Override diff --git a/src/main/java/com/switcherapi/client/service/local/ClientLocalService.java b/src/main/java/com/switcherapi/client/service/local/ClientLocalService.java index 8f23149..607eeb0 100644 --- a/src/main/java/com/switcherapi/client/service/local/ClientLocalService.java +++ b/src/main/java/com/switcherapi/client/service/local/ClientLocalService.java @@ -4,11 +4,11 @@ import com.switcherapi.client.exception.SwitcherKeyNotFoundException; import com.switcherapi.client.model.Entry; import com.switcherapi.client.model.SwitcherRequest; +import com.switcherapi.client.model.SwitcherResult; import com.switcherapi.client.model.criteria.Config; import com.switcherapi.client.model.criteria.Domain; import com.switcherapi.client.model.criteria.Group; import com.switcherapi.client.model.criteria.StrategyConfig; -import com.switcherapi.client.model.SwitcherResult; import com.switcherapi.client.service.SwitcherFactory; import com.switcherapi.client.service.SwitcherValidator; import com.switcherapi.client.utils.SwitcherUtils; @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.Set; /** @@ -72,7 +73,7 @@ public SwitcherResult executeCriteria(final SwitcherRequest switcher, final Doma for (final Group group : domain.getGroup()) { config = findConfigInGroup(group, switcher.getSwitcherKey()); - if (config != null) { + if (Objects.nonNull(config)) { return getSwitcherResult(switcher, group, config); } } @@ -101,10 +102,13 @@ private SwitcherResult getSwitcherResult(SwitcherRequest switcher, Group group, } private Config findConfigInGroup(final Group group, final String switcherKey) { - return Arrays.stream(group.getConfig()) - .filter(c -> c.getKey().equals(switcherKey)) - .findFirst() - .orElse(null); + for (Config config : group.getConfig()) { + if (config.getKey().equals(switcherKey)) { + return config; + } + } + + return null; } /** @@ -126,7 +130,7 @@ private SwitcherResult processOperation(final StrategyConfig[] configStrategies, final Entry switcherInput = tryGetSwitcherInput(input, strategyConfig); - if (switcherInput == null) { + if (Objects.isNull(switcherInput)) { return strategyFailed(switcher, strategyConfig, STRATEGY_FAIL_NO_INPUT_PATTERN); } @@ -143,7 +147,7 @@ private SwitcherResult strategyFailed(SwitcherRequest switcher, StrategyConfig s } private Entry tryGetSwitcherInput(final List input, StrategyConfig strategyConfig) { - if (input == null) { + if (Objects.isNull(input)) { return null; }