Skip to content

Commit 2e115cd

Browse files
matthewelwellkhvn26
andcommitted
fix: FlagsmithClient.close() doesn't kill polling manager properly (#133)
* Convert to daemon thread and ensure that closing works correctly * Remove unnecessary call to getEnvironmentFlags * Add comment * typo Co-authored-by: Kim Gustyr <kim.gustyr@flagsmith.com> --------- Co-authored-by: Kim Gustyr <kim.gustyr@flagsmith.com>
1 parent 30a6c1f commit 2e115cd

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

src/main/java/com/flagsmith/threads/PollingManager.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public PollingManager(FlagsmithClient client, Integer interval) {
3232
* @return
3333
*/
3434
private Thread initializeThread() {
35-
return new Thread() {
35+
Thread thread = new Thread() {
3636
@Override
3737
public void run() {
3838
try {
@@ -45,6 +45,8 @@ public void run() {
4545
}
4646
}
4747
};
48+
thread.setDaemon(true);
49+
return thread;
4850
}
4951

5052
/**
@@ -61,5 +63,10 @@ public void stopPolling() {
6163
internalThread.interrupt();
6264
}
6365

64-
66+
/**
67+
* Get thread status
68+
*/
69+
public Boolean getIsThreadAlive() {
70+
return internalThread.isAlive();
71+
}
6572
}

src/test/java/com/flagsmith/FlagsmithClientTest.java

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import com.fasterxml.jackson.core.JsonProcessingException;
88
import com.fasterxml.jackson.core.type.TypeReference;
99
import com.fasterxml.jackson.databind.JsonNode;
10-
import com.flagsmith.responses.FlagsAndTraitsResponse;
1110
import com.flagsmith.config.FlagsmithCacheConfig;
1211
import com.flagsmith.config.FlagsmithConfig;
1312
import com.flagsmith.exceptions.FlagsmithApiError;
@@ -20,6 +19,7 @@
2019
import com.flagsmith.models.DefaultFlag;
2120
import com.flagsmith.models.Flags;
2221
import com.flagsmith.models.Segment;
22+
import com.flagsmith.responses.FlagsAndTraitsResponse;
2323
import com.flagsmith.threads.PollingManager;
2424
import com.flagsmith.threads.RequestProcessor;
2525

@@ -591,4 +591,36 @@ public void testLocalEvaluation_ReturnsConsistentResults() throws FlagsmithClien
591591
Assert.assertEquals(flags.getFeatureValue("some_feature"), expectedValue);
592592
}
593593
}
594+
595+
@Test(groups = "unit")
596+
public void testClose() throws FlagsmithApiError, InterruptedException {
597+
// Given
598+
int pollingInterval = 1;
599+
600+
FlagsmithConfig config = FlagsmithConfig
601+
.newBuilder()
602+
.withLocalEvaluation(true)
603+
.withEnvironmentRefreshIntervalSeconds(pollingInterval)
604+
.build();
605+
606+
FlagsmithApiWrapper mockedApiWrapper = mock(FlagsmithApiWrapper.class);
607+
when(mockedApiWrapper.getEnvironment()).thenReturn(FlagsmithTestHelper.environmentModel());
608+
when(mockedApiWrapper.getConfig()).thenReturn(config);
609+
610+
FlagsmithClient client = FlagsmithClient.newBuilder()
611+
.withFlagsmithApiWrapper(mockedApiWrapper)
612+
.withConfiguration(config)
613+
.setApiKey("ser.dummy-key")
614+
.build();
615+
616+
// When
617+
client.close();
618+
619+
// Then
620+
// Since the thread will only stop once it reads the interrupt signal correctly
621+
// on its next polling interval, we need to wait for the polling interval
622+
// to complete before checking the thread has been killed correctly.
623+
Thread.sleep(pollingInterval);
624+
Assert.assertFalse(client.getPollingManager().getIsThreadAlive());
625+
}
594626
}

0 commit comments

Comments
 (0)