Skip to content

Commit faa0140

Browse files
authored
Improved Switcher interface, decoupled concrete requester (#332)
1 parent 65ea85d commit faa0140

31 files changed

Lines changed: 369 additions & 371 deletions

src/main/java/com/github/switcherapi/client/SwitcherContext.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import com.github.switcherapi.client.exception.SwitcherKeyNotFoundException;
44
import com.github.switcherapi.client.exception.SwitchersValidationException;
55
import com.github.switcherapi.client.model.ContextKey;
6-
import com.github.switcherapi.client.model.Switcher;
6+
import com.github.switcherapi.client.model.SwitcherRequest;
77

88
/**
99
* <b>Switcher Context</b>
@@ -54,7 +54,7 @@ public static void initializeClient() {
5454
* @return a ready to use Switcher
5555
* @throws SwitcherKeyNotFoundException in case the key was not properly loaded
5656
*/
57-
public static Switcher getSwitcher(String key, boolean keepEntries) {
57+
public static SwitcherRequest getSwitcher(String key, boolean keepEntries) {
5858
return SwitcherContextBase.getSwitcher(key, keepEntries);
5959
}
6060

@@ -64,7 +64,7 @@ public static Switcher getSwitcher(String key, boolean keepEntries) {
6464
* @param key name
6565
* @return a ready to use Switcher
6666
*/
67-
public static Switcher getSwitcher(String key) {
67+
public static SwitcherRequest getSwitcher(String key) {
6868
return SwitcherContextBase.getSwitcher(key);
6969
}
7070

src/main/java/com/github/switcherapi/client/SwitcherContextBase.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import com.github.switcherapi.client.exception.SwitcherKeyNotFoundException;
66
import com.github.switcherapi.client.exception.SwitchersValidationException;
77
import com.github.switcherapi.client.model.ContextKey;
8-
import com.github.switcherapi.client.model.Switcher;
8+
import com.github.switcherapi.client.model.SwitcherRequest;
99
import com.github.switcherapi.client.remote.ClientWS;
1010
import com.github.switcherapi.client.remote.ClientWSImpl;
1111
import com.github.switcherapi.client.service.SwitcherValidator;
@@ -85,7 +85,7 @@ public abstract class SwitcherContextBase extends SwitcherConfig {
8585

8686
protected static SwitcherProperties switcherProperties;
8787
protected static Set<String> switcherKeys;
88-
protected static Map<String, Switcher> switchers;
88+
protected static Map<String, SwitcherRequest> switchers;
8989
protected static SwitcherExecutor instance;
9090
private static ScheduledExecutorService scheduledExecutorService;
9191
private static ExecutorService watcherExecutorService;
@@ -257,7 +257,7 @@ private static void loadSwitchers() {
257257

258258
switchers.clear();
259259
for (String key : switcherKeys) {
260-
switchers.put(key, new Switcher(key, instance));
260+
switchers.put(key, new SwitcherRequest(key, instance));
261261
}
262262
}
263263

@@ -353,14 +353,14 @@ private static ClientWS initRemotePoolExecutorService() {
353353
* @return a ready to use Switcher
354354
* @throws SwitcherKeyNotFoundException in case the key was not properly loaded
355355
*/
356-
public static Switcher getSwitcher(String key, boolean keepEntries) {
356+
public static SwitcherRequest getSwitcher(String key, boolean keepEntries) {
357357
SwitcherUtils.debug(logger, "key: {} - keepEntries: {}", key, keepEntries);
358358

359359
if (!switchers.containsKey(key)) {
360360
throw new SwitcherKeyNotFoundException(key);
361361
}
362362

363-
final Switcher switcher = switchers.get(key);
363+
final SwitcherRequest switcher = switchers.get(key);
364364
if (!keepEntries) {
365365
switcher.resetEntry();
366366
}
@@ -374,7 +374,7 @@ public static Switcher getSwitcher(String key, boolean keepEntries) {
374374
* @param key name
375375
* @return a ready to use Switcher
376376
*/
377-
public static Switcher getSwitcher(String key) {
377+
public static SwitcherRequest getSwitcher(String key) {
378378
return getSwitcher(key, false);
379379
}
380380

src/main/java/com/github/switcherapi/client/SwitcherExecutor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import com.github.switcherapi.client.exception.SwitcherRemoteException;
44
import com.github.switcherapi.client.exception.SwitcherSnapshotWriteException;
55
import com.github.switcherapi.client.model.ContextKey;
6-
import com.github.switcherapi.client.model.Switcher;
6+
import com.github.switcherapi.client.model.SwitcherRequest;
77
import com.github.switcherapi.client.model.criteria.Domain;
88
import com.github.switcherapi.client.model.criteria.Snapshot;
99
import com.github.switcherapi.client.model.SwitcherResult;
@@ -47,7 +47,7 @@ protected SwitcherExecutor(final SwitcherProperties switcherProperties) {
4747
* @param switcher to be evaluated
4848
* @return Criteria response containing the evaluation details
4949
*/
50-
public abstract SwitcherResult executeCriteria(final Switcher switcher);
50+
public abstract SwitcherResult executeCriteria(final SwitcherRequest switcher);
5151

5252
/**
5353
* Check the snapshot versions against the Remote configuration.

src/main/java/com/github/switcherapi/client/model/AsyncSwitcher.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,27 @@
1818
* @since 2021-11-27
1919
*
2020
*/
21-
public class AsyncSwitcher<T> {
21+
public class AsyncSwitcher {
2222

2323
private static final Logger logger = LoggerFactory.getLogger(AsyncSwitcher.class);
2424

2525
private final ExecutorService executorService;
2626

27-
private final SwitcherInterface<T> switcherInterface;
27+
private final Switcher switcher;
2828

2929
private final long delay;
3030

3131
private long nextRun = 0;
3232

33-
public AsyncSwitcher(final SwitcherInterface<T> switcherInterface, long delay) {
33+
public AsyncSwitcher(final Switcher switcher, long delay) {
3434
this.executorService = Executors.newCachedThreadPool(r -> {
3535
Thread thread = new Thread(r);
3636
thread.setName(SWITCHER_ASYNC_WORKER.toString());
3737
thread.setDaemon(true);
3838
return thread;
3939
});
4040

41-
this.switcherInterface = switcherInterface;
41+
this.switcher = switcher;
4242
this.delay = delay;
4343
}
4444

@@ -59,8 +59,8 @@ public synchronized void execute() {
5959

6060
public void run() {
6161
try {
62-
final SwitcherResult response = switcherInterface.executeCriteria();
63-
switcherInterface.updateHistoryExecution(response);
62+
final SwitcherResult response = switcher.executeCriteria();
63+
switcher.updateHistoryExecution(response);
6464
} catch (SwitcherException e) {
6565
logger.error(e.getMessage(), e);
6666
}
Lines changed: 88 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -1,157 +1,110 @@
11
package com.github.switcherapi.client.model;
22

33
import com.github.switcherapi.client.SwitcherContext;
4-
import com.github.switcherapi.client.SwitcherExecutor;
54
import com.github.switcherapi.client.exception.SwitcherException;
65

7-
import java.util.*;
6+
import java.util.List;
87

98
/**
10-
* Switchers are the entry point to evaluate criteria and return the result.
11-
* <br>To execute a criteria evaluation, use one of the available methods: {@link #isItOn()}.
12-
*
13-
* @author Roger Floriano (petruki)
14-
* @since 2019-12-24
15-
*
16-
* @see #isItOn()
17-
* @see #submit()
9+
* The API that handles the switcher operations.
10+
*
11+
* <ul>
12+
* <li>Switcher creation</li>
13+
* <li>Switcher execution</li>
14+
* <li>Switcher get input/output</li>
15+
* </ul>
1816
*/
19-
public final class Switcher extends SwitcherBuilder {
20-
21-
public static final String KEY = "key";
22-
23-
public static final String SHOW_REASON = "showReason";
24-
25-
public static final String BYPASS_METRIC = "bypassMetric";
17+
public interface Switcher {
2618

27-
private final SwitcherExecutor context;
28-
29-
private final String switcherKey;
30-
31-
private final Set<SwitcherResult> historyExecution;
32-
33-
private AsyncSwitcher<Switcher> asyncSwitcher;
34-
3519
/**
36-
* Use {@link SwitcherContext#getSwitcher(String)} to create this object.
37-
*
38-
* @param switcherKey name of the key created
39-
* @param context client context in which the switcher will be executed (local/remote)
20+
* This method builds the Switcher object.<br>
21+
* Uses to isolate Switcher creation from the execution.<br>
22+
*
23+
* For example:
24+
* <pre>
25+
* Switcher switcher = SwitcherContext
26+
* .getSwitcher(MY_SWITCHER)
27+
* .remote(true)
28+
* .throttle(1000)
29+
* .checkValue("value")
30+
* .build();
31+
* </pre>
32+
*
33+
* @return instance of SwitcherInterface
34+
* @see SwitcherRequest
4035
*/
41-
public Switcher(final String switcherKey, final SwitcherExecutor context) {
42-
super(context.getSwitcherProperties());
43-
this.context = context;
44-
this.switcherKey = switcherKey;
45-
this.historyExecution = new HashSet<>();
46-
this.entry = new ArrayList<>();
47-
}
48-
49-
@Override
50-
public Switcher build() {
51-
return this;
52-
}
53-
54-
@Override
55-
public Switcher prepareEntry(final List<Entry> entry) {
56-
this.entry = Optional.ofNullable(entry).orElse(new ArrayList<>());
57-
return this;
58-
}
59-
60-
@Override
61-
public Switcher prepareEntry(final Entry entry, final boolean add) {
62-
if (!add) {
63-
this.entry.clear();
64-
}
65-
66-
if (!this.entry.contains(entry)) {
67-
this.entry.add(entry);
68-
}
69-
70-
return this;
71-
}
72-
73-
@Override
74-
public Switcher prepareEntry(final Entry entry) {
75-
return this.prepareEntry(entry, false);
76-
}
77-
78-
@Override
79-
public boolean isItOn() throws SwitcherException {
80-
final SwitcherResult response = submit();
81-
return response.isItOn();
82-
}
83-
84-
@Override
85-
public SwitcherResult submit() throws SwitcherException {
86-
if (SwitcherExecutor.getBypass().containsKey(switcherKey)) {
87-
return SwitcherExecutor.getBypass().get(switcherKey).buildFromSwitcher(switcherKey, entry);
88-
}
89-
90-
if (canUseAsync()) {
91-
if (Objects.isNull(asyncSwitcher)) {
92-
asyncSwitcher = new AsyncSwitcher<>(this, super.delay);
93-
}
94-
95-
asyncSwitcher.execute();
96-
final Optional<SwitcherResult> response = getFromHistory();
97-
if (response.isPresent()) {
98-
return response.get();
99-
}
100-
}
101-
102-
final SwitcherResult response = this.context.executeCriteria(this);
103-
this.updateHistoryExecution(response);
104-
return response;
105-
}
36+
Switcher build();
10637

107-
@Override
108-
public SwitcherResult executeCriteria() {
109-
return this.context.executeCriteria(this);
110-
}
38+
/**
39+
* Prepare the Switcher including a list of inputs necessary to run the criteria afterward.
40+
*
41+
* @param entry input object
42+
* @return instance of SwitcherInterface
43+
*/
44+
Switcher prepareEntry(final List<Entry> entry);
11145

112-
@Override
113-
public void updateHistoryExecution(final SwitcherResult response) {
114-
this.historyExecution.removeIf(item ->
115-
this.switcherKey.equals(item.getSwitcherKey()) && this.entry.equals(item.getEntry()));
46+
/**
47+
* Prepare the Switcher including a list of inputs necessary to run the criteria afterward.
48+
*
49+
* @param entry input object
50+
* @param add if false, the list will be cleaned and the entry provided will be the only input for this Switcher.
51+
* @return instance of SwitcherInterface
52+
*/
53+
Switcher prepareEntry(final Entry entry, final boolean add);
11654

117-
this.historyExecution.add(response);
118-
}
55+
/**
56+
* It adds an input to the list of inputs.
57+
* <br>Under the table it calls {@link #prepareEntry(Entry, boolean)} passing true to the second argument.
58+
*
59+
* @param entry input object
60+
* @return instance of SwitcherInterface
61+
*/
62+
Switcher prepareEntry(final Entry entry);
11963

120-
@Override
121-
public String getSwitcherKey() {
122-
return this.switcherKey;
123-
}
64+
/**
65+
* Execute criteria based on a given switcher key provided via {@link SwitcherContext#getSwitcher(String)}.
66+
* <br>The detailed result is available in list of {@link SwitcherResult}.
67+
*
68+
* @return criteria result
69+
* @throws SwitcherException connectivity or criteria errors regarding reading malformed snapshots
70+
*/
71+
boolean isItOn() throws SwitcherException;
12472

125-
@Override
126-
public List<Entry> getEntry() {
127-
return this.entry;
128-
}
73+
/**
74+
* Execute criteria based on a given switcher key provided via {@link SwitcherContext#getSwitcher(String)}.
75+
* <br>The detailed result is available in list of {@link SwitcherResult}.
76+
*
77+
* @return {@link SwitcherResult}
78+
* @throws SwitcherException connectivity or criteria errors regarding reading malformed snapshots
79+
*/
80+
SwitcherResult submit() throws SwitcherException;
12981

130-
public boolean isBypassMetrics() {
131-
return bypassMetrics;
132-
}
133-
134-
public void resetEntry() {
135-
this.entry = new ArrayList<>();
136-
}
82+
/**
83+
* Execute the criteria evaluation.
84+
*
85+
* @return the switcher result
86+
*/
87+
SwitcherResult executeCriteria();
13788

138-
private boolean canUseAsync() {
139-
return super.delay > 0 && !this.historyExecution.isEmpty();
140-
}
89+
/**
90+
* Update the history of executions.
91+
*
92+
* @param response the response to be updated
93+
*/
94+
void updateHistoryExecution(SwitcherResult response);
14195

142-
private Optional<SwitcherResult> getFromHistory() {
143-
for (SwitcherResult switcherResult : historyExecution) {
144-
if (switcherResult.getEntry().equals(getEntry())) {
145-
return Optional.of(switcherResult);
146-
}
147-
}
148-
return Optional.empty();
149-
}
96+
/**
97+
* Get the key of the switcher.
98+
*
99+
* @return the key of the switcher
100+
*/
101+
String getSwitcherKey();
150102

151-
@Override
152-
public String toString() {
153-
return String.format("Switcher [switcherKey= %s, entry= %s, bypassMetrics= %s]",
154-
switcherKey, entry, bypassMetrics);
155-
}
103+
/**
104+
* Get the entry input list for the switcher.
105+
*
106+
* @return the entry of the switcher
107+
*/
108+
List<Entry> getEntry();
156109

157110
}

src/main/java/com/github/switcherapi/client/model/SwitcherBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
* @author Roger Floriano (petruki)
1515
*/
16-
public abstract class SwitcherBuilder implements SwitcherInterface<Switcher> {
16+
public abstract class SwitcherBuilder implements Switcher {
1717

1818
protected final SwitcherProperties properties;
1919

0 commit comments

Comments
 (0)