Skip to content

Commit 0adddb0

Browse files
Introducing builder pattern on AsyncEventHandler (#293)
1 parent 7f72b0a commit 0adddb0

File tree

3 files changed

+87
-7
lines changed

3 files changed

+87
-7
lines changed

core-httpclient-impl/src/main/java/com/optimizely/ab/event/AsyncEventHandler.java

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,24 @@
4747
* {@link EventHandler} implementation that queues events and has a separate pool of threads responsible
4848
* for the dispatch.
4949
*/
50-
public class AsyncEventHandler implements EventHandler {
50+
public class AsyncEventHandler implements EventHandler, AutoCloseable {
5151

5252
private static final Logger logger = LoggerFactory.getLogger(AsyncEventHandler.class);
5353
private static final ProjectConfigResponseHandler EVENT_RESPONSE_HANDLER = new ProjectConfigResponseHandler();
5454

5555
private final OptimizelyHttpClient httpClient;
5656
private final ExecutorService workerExecutor;
5757

58-
public AsyncEventHandler(int queueCapacity, int numWorkers) {
59-
this(queueCapacity, numWorkers, 200, 20, 5000);
60-
}
58+
private final long closeTimeout;
59+
private final TimeUnit closeTimeoutUnit;
6160

62-
public AsyncEventHandler(int queueCapacity, int numWorkers, int maxConnections, int connectionsPerRoute, int validateAfter) {
61+
public AsyncEventHandler(int queueCapacity,
62+
int numWorkers,
63+
int maxConnections,
64+
int connectionsPerRoute,
65+
int validateAfter,
66+
long closeTimeout,
67+
TimeUnit closeTimeoutUnit) {
6368
if (queueCapacity <= 0) {
6469
throw new IllegalArgumentException("queue capacity must be > 0");
6570
}
@@ -74,12 +79,17 @@ public AsyncEventHandler(int queueCapacity, int numWorkers, int maxConnections,
7479
0L, TimeUnit.MILLISECONDS,
7580
new ArrayBlockingQueue<Runnable>(queueCapacity),
7681
new NamedThreadFactory("optimizely-event-dispatcher-thread-%s", true));
82+
83+
this.closeTimeout = closeTimeout;
84+
this.closeTimeoutUnit = closeTimeoutUnit;
7785
}
7886

7987
@VisibleForTesting
8088
public AsyncEventHandler(OptimizelyHttpClient httpClient, ExecutorService workerExecutor) {
8189
this.httpClient = httpClient;
8290
this.workerExecutor = workerExecutor;
91+
this.closeTimeout = Long.MAX_VALUE;
92+
this.closeTimeoutUnit = TimeUnit.MILLISECONDS;
8393
}
8494

8595
@Override
@@ -136,6 +146,11 @@ public void shutdownAndAwaitTermination(long timeout, TimeUnit unit) {
136146
logger.info("event handler shutdown complete");
137147
}
138148

149+
@Override
150+
public void close() {
151+
shutdownAndAwaitTermination(closeTimeout, closeTimeoutUnit);
152+
}
153+
139154
//======== Helper classes ========//
140155

141156
/**
@@ -205,4 +220,62 @@ public Void handleResponse(HttpResponse response) throws IOException {
205220
}
206221
}
207222
}
223+
224+
//======== Builder ========//
225+
226+
public static Builder builder() { return new Builder(); }
227+
228+
public static class Builder {
229+
230+
private int queueCapacity;
231+
private int numWorkers;
232+
private int maxTotalConnections = 200;
233+
private int maxPerRoute = 20;
234+
private int validateAfterInactivity = 5000;
235+
private long closeTimeout = Long.MAX_VALUE;
236+
private TimeUnit closeTimeoutUnit = TimeUnit.MILLISECONDS;
237+
238+
public Builder withQueueCapacity(int queueCapacity) {
239+
this.queueCapacity = queueCapacity;
240+
return this;
241+
}
242+
243+
public Builder withNumWorkers(int numWorkers) {
244+
this.numWorkers = numWorkers;
245+
return this;
246+
}
247+
248+
public Builder withMaxTotalConnections(int maxTotalConnections) {
249+
this.maxTotalConnections = maxTotalConnections;
250+
return this;
251+
}
252+
253+
public Builder withMaxPerRoute(int maxPerRoute) {
254+
this.maxPerRoute = maxPerRoute;
255+
return this;
256+
}
257+
258+
public Builder withValidateAfterInactivity(int validateAfterInactivity) {
259+
this.validateAfterInactivity = validateAfterInactivity;
260+
return this;
261+
}
262+
263+
public Builder withCloseTimeout(long closeTimeout, TimeUnit unit) {
264+
this.closeTimeout = closeTimeout;
265+
this.closeTimeoutUnit = unit;
266+
return this;
267+
}
268+
269+
public AsyncEventHandler build() {
270+
return new AsyncEventHandler(
271+
queueCapacity,
272+
numWorkers,
273+
maxTotalConnections,
274+
maxPerRoute,
275+
validateAfterInactivity,
276+
closeTimeout,
277+
closeTimeoutUnit
278+
);
279+
}
280+
}
208281
}

core-httpclient-impl/src/test/java/com/optimizely/ab/event/AsyncEventHandlerTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ public class AsyncEventHandlerTest {
6565
@Test
6666
public void testQueueCapacityPreconditionCheck() throws Exception {
6767
thrown.expect(IllegalArgumentException.class);
68-
new AsyncEventHandler(-1, 1);
68+
AsyncEventHandler.builder()
69+
.withQueueCapacity(-1)
70+
.withNumWorkers(-1)
71+
.build();
6972
}
7073

7174
@Test

java-quickstart/src/main/java/com/optimizely/Example.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ private void processVisitor(String userId, Map<String, String> attributes) {
5353
}
5454

5555
public static void main(String[] args) throws InterruptedException {
56-
EventHandler eventHandler = new AsyncEventHandler(100,2);
56+
EventHandler eventHandler = AsyncEventHandler.builder()
57+
.withQueueCapacity(100)
58+
.withNumWorkers(2)
59+
.build();
60+
5761
HttpProjectConfigManager projectConfigManager = HttpProjectConfigManager.builder()
5862
.withSdkKey("BX9Y3bTa4YErpHZEMpAwHm")
5963
.withPollingInterval(1, TimeUnit.SECONDS)

0 commit comments

Comments
 (0)