Skip to content

Commit 7284937

Browse files
Making Optimizely Autocloseable (#296)
1 parent 0adddb0 commit 7284937

File tree

2 files changed

+94
-6
lines changed

2 files changed

+94
-6
lines changed

core-api/src/main/java/com/optimizely/ab/Optimizely.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import javax.annotation.Nonnull;
3838
import javax.annotation.Nullable;
3939
import javax.annotation.concurrent.ThreadSafe;
40+
import java.io.Closeable;
4041
import java.util.ArrayList;
4142
import java.util.Collections;
4243
import java.util.HashMap;
@@ -69,7 +70,7 @@
6970
* to be logged, and for the "control" variation to be returned.
7071
*/
7172
@ThreadSafe
72-
public class Optimizely {
73+
public class Optimizely implements AutoCloseable {
7374

7475
private static final Logger logger = LoggerFactory.getLogger(Optimizely.class);
7576

@@ -115,6 +116,33 @@ public boolean isValid() {
115116
return getProjectConfig() != null;
116117
}
117118

119+
/**
120+
* Helper method which checks if Object is an instance of Closeable and calls close() on it.
121+
*/
122+
private void tryClose(Object obj) {
123+
if (!(obj instanceof Closeable)) {
124+
return;
125+
}
126+
127+
try {
128+
((Closeable) obj).close();
129+
} catch (Exception e) {
130+
logger.warn("Unexpected exception on trying to close {}.", obj);
131+
}
132+
}
133+
134+
/**
135+
* Checks if eventHandler {@link EventHandler} and projectConfigManager {@link ProjectConfigManager}
136+
* are Closeable {@link Closeable} and calls close on them.
137+
*
138+
* <b>NOTE:</b> There is a chance that this could be long running if the implementations of close are long running.
139+
*/
140+
@Override
141+
public void close() {
142+
tryClose(eventHandler);
143+
tryClose(projectConfigManager);
144+
}
145+
118146
//======== activate calls ========//
119147

120148
@Nullable

core-api/src/test/java/com/optimizely/ab/OptimizelyTest.java

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.mockito.junit.MockitoRule;
4646

4747
import javax.annotation.Nonnull;
48+
import java.io.Closeable;
4849
import java.io.IOException;
4950
import java.util.ArrayList;
5051
import java.util.Arrays;
@@ -53,18 +54,13 @@
5354
import java.util.HashMap;
5455
import java.util.List;
5556
import java.util.Map;
56-
import java.util.concurrent.CountDownLatch;
57-
import java.util.concurrent.TimeUnit;
58-
import java.util.concurrent.TimeoutException;
5957

6058
import static com.optimizely.ab.config.DatafileProjectConfigTestUtils.*;
6159
import static com.optimizely.ab.config.ValidProjectConfigV4.*;
6260
import static com.optimizely.ab.event.LogEvent.RequestMethod;
6361
import static com.optimizely.ab.notification.DecisionNotification.ExperimentDecisionNotificationBuilder.EXPERIMENT_KEY;
6462
import static com.optimizely.ab.notification.DecisionNotification.ExperimentDecisionNotificationBuilder.VARIATION_KEY;
6563
import static com.optimizely.ab.notification.DecisionNotification.FeatureVariableDecisionNotificationBuilder.*;
66-
import static com.optimizely.ab.notification.DecisionNotification.ExperimentDecisionNotificationBuilder.EXPERIMENT_KEY;
67-
import static com.optimizely.ab.notification.DecisionNotification.ExperimentDecisionNotificationBuilder.VARIATION_KEY;
6864
import static java.util.Arrays.asList;
6965
import static junit.framework.TestCase.assertTrue;
7066
import static org.hamcrest.CoreMatchers.is;
@@ -148,6 +144,70 @@ public OptimizelyTest(String validDatafile, String noAudienceDatafile) throws Co
148144
this.datafileVersion = Integer.parseInt(validProjectConfig.getVersion());
149145
}
150146

147+
@Test
148+
public void testClose() throws IOException {
149+
EventHandler mockCloseableEventHandler = mock(
150+
EventHandler.class,
151+
withSettings().extraInterfaces(Closeable.class)
152+
);
153+
ProjectConfigManager mockCloseableProjectConfigManager = mock(
154+
ProjectConfigManager.class,
155+
withSettings().extraInterfaces(Closeable.class)
156+
);
157+
158+
Optimizely optimizely = Optimizely.builder()
159+
.withEventHandler(mockCloseableEventHandler)
160+
.withConfigManager(mockCloseableProjectConfigManager)
161+
.build();
162+
163+
optimizely.close();
164+
165+
verify((Closeable) mockCloseableEventHandler).close();
166+
verify((Closeable) mockCloseableProjectConfigManager).close();
167+
}
168+
169+
@Test
170+
public void testCloseConfigManagerThrowsException() throws IOException {
171+
EventHandler mockCloseableEventHandler = mock(
172+
EventHandler.class,
173+
withSettings().extraInterfaces(Closeable.class)
174+
);
175+
ProjectConfigManager mockCloseableProjectConfigManager = mock(
176+
ProjectConfigManager.class,
177+
withSettings().extraInterfaces(Closeable.class)
178+
);
179+
180+
Optimizely optimizely = Optimizely.builder()
181+
.withEventHandler(mockCloseableEventHandler)
182+
.withConfigManager(mockCloseableProjectConfigManager)
183+
.build();
184+
185+
doThrow(new IOException()).when((Closeable) mockCloseableProjectConfigManager).close();
186+
logbackVerifier.expectMessage(Level.WARN, "Unexpected exception on trying to close " + mockCloseableProjectConfigManager + ".");
187+
optimizely.close();
188+
}
189+
190+
@Test
191+
public void testCloseEventHandlerThrowsException() throws IOException {
192+
EventHandler mockCloseableEventHandler = mock(
193+
EventHandler.class,
194+
withSettings().extraInterfaces(Closeable.class)
195+
);
196+
ProjectConfigManager mockCloseableProjectConfigManager = mock(
197+
ProjectConfigManager.class,
198+
withSettings().extraInterfaces(Closeable.class)
199+
);
200+
201+
Optimizely optimizely = Optimizely.builder()
202+
.withEventHandler(mockCloseableEventHandler)
203+
.withConfigManager(mockCloseableProjectConfigManager)
204+
.build();
205+
206+
doThrow(new IOException()).when((Closeable) mockCloseableEventHandler).close();
207+
logbackVerifier.expectMessage(Level.WARN, "Unexpected exception on trying to close " + mockCloseableEventHandler + ".");
208+
optimizely.close();
209+
}
210+
151211
//======== activate tests ========//
152212

153213
/**

0 commit comments

Comments
 (0)