Skip to content

Commit 2091826

Browse files
committed
move to tool - draft
Signed-off-by: liran2000 <[email protected]>
1 parent d201b1f commit 2091826

File tree

8 files changed

+1531
-1
lines changed

8 files changed

+1531
-1
lines changed

providers/flagd/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,12 @@ If the `in-process` mode is not used, and before the provider is ready, the `get
5858
HttpConnector is responsible for polling data from a specified URL at regular intervals.
5959
It is leveraging Http cache mechanism with 'ETag' header, then when receiving 304 Not Modified response,
6060
reducing traffic, reducing rate limits effects and changes updates. Can be enabled via useHttpCache option.
61-
One of its benefits is to reduce infrastructure/devops work, without additional containers needed.
6261
The implementation is using Java HttpClient.
6362

63+
##### Use cases and benefits
64+
* Reduce infrastructure/devops work, without additional containers needed.
65+
* Use as an additional provider for fallback / internal backup service via multi-provider.
66+
6467
##### What happens if the Http source is down when application is starting ?
6568

6669
It supports optional fail-safe initialization via cache, such that on initial fetch error following by
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package dev.openfeature.contrib.tools.flagd.resolver.process.storage.connector.sync.http.util;
2+
3+
import lombok.AccessLevel;
4+
import lombok.NoArgsConstructor;
5+
import lombok.extern.slf4j.Slf4j;
6+
import java.util.concurrent.ExecutorService;
7+
import java.util.concurrent.TimeUnit;
8+
9+
/**
10+
* Concurrent / Concurrency utilities.
11+
*
12+
* @author Liran Mendelovich
13+
*/
14+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
15+
@Slf4j
16+
public class ConcurrentUtils {
17+
18+
/**
19+
* Graceful shutdown a thread pool. <br>
20+
* See <a
21+
* href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html">
22+
* https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html</a>
23+
*
24+
* @param pool thread pool
25+
* @param timeoutSeconds grace period timeout in seconds - timeout can be twice than this value,
26+
* as first it waits for existing tasks to terminate, then waits for cancelled tasks to
27+
* terminate.
28+
*/
29+
public static void shutdownAndAwaitTermination(ExecutorService pool, int timeoutSeconds) {
30+
if (pool == null) {
31+
return;
32+
}
33+
34+
// Disable new tasks from being submitted
35+
pool.shutdown();
36+
try {
37+
38+
// Wait a while for existing tasks to terminate
39+
if (!pool.awaitTermination(timeoutSeconds, TimeUnit.SECONDS)) {
40+
41+
// Cancel currently executing tasks - best effort, based on interrupt handling
42+
// implementation.
43+
pool.shutdownNow();
44+
45+
// Wait a while for tasks to respond to being cancelled
46+
if (!pool.awaitTermination(timeoutSeconds, TimeUnit.SECONDS)) {
47+
log.error("Thread pool did not shutdown all tasks after the timeout: {} seconds.", timeoutSeconds);
48+
}
49+
}
50+
} catch (InterruptedException e) {
51+
52+
log.info("Current thread interrupted during shutdownAndAwaitTermination, calling shutdownNow.");
53+
54+
// (Re-)Cancel if current thread also interrupted
55+
pool.shutdownNow();
56+
57+
// Preserve interrupt status
58+
Thread.currentThread().interrupt();
59+
}
60+
}
61+
}

tools/flagd-http-connector/src/test/java/dev/openfeature/contrib/tools/flagd/resolver/process/storage/connector/sync/http/HttpCacheFetcherTest.java

Lines changed: 309 additions & 0 deletions
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package dev.openfeature.contrib.tools.flagd.resolver.process.storage.connector.sync.http;
2+
3+
import static dev.openfeature.contrib.providers.flagd.resolver.process.storage.connector.sync.http.HttpConnectorTest.delay;
4+
import static org.junit.jupiter.api.Assertions.assertEquals;
5+
import static org.junit.jupiter.api.Assumptions.assumeTrue;
6+
7+
import dev.openfeature.contrib.providers.flagd.resolver.process.storage.connector.QueuePayload;
8+
import dev.openfeature.contrib.providers.flagd.resolver.process.storage.connector.sync.http.HttpConnector;
9+
import dev.openfeature.contrib.providers.flagd.resolver.process.storage.connector.sync.http.HttpConnectorOptions;
10+
import java.util.concurrent.BlockingQueue;
11+
import lombok.SneakyThrows;
12+
import lombok.extern.slf4j.Slf4j;
13+
import org.junit.jupiter.api.Test;
14+
15+
/**
16+
* Integration test for the HttpConnector class, specifically testing the ability to fetch
17+
* raw content from a GitHub URL. This test assumes that integration tests are enabled
18+
* and verifies that the HttpConnector can successfully enqueue data from the specified URL.
19+
* The test initializes the HttpConnector with specific configurations, waits for data
20+
* to be enqueued, and asserts the expected queue size. The connector is shut down
21+
* gracefully after the test execution.
22+
* As this integration test using external request, it is disabled by default, and not part of the CI build.
23+
*/
24+
@Slf4j
25+
class HttpConnectorIntegrationTest {
26+
27+
@SneakyThrows
28+
@Test
29+
void testGithubRawContent() {
30+
assumeTrue(parseBoolean("integrationTestsEnabled"));
31+
dev.openfeature.contrib.providers.flagd.resolver.process.storage.connector.sync.http.HttpConnector connector = null;
32+
try {
33+
String testUrl = "https://raw.githubusercontent.com/open-feature/java-sdk-contrib/58fe5da7d4e2f6f4ae2c1caf3411a01e84a1dc1a/providers/flagd/version.txt";
34+
35+
dev.openfeature.contrib.providers.flagd.resolver.process.storage.connector.sync.http.HttpConnectorOptions httpConnectorOptions = HttpConnectorOptions.builder()
36+
.url(testUrl)
37+
.connectTimeoutSeconds(10)
38+
.requestTimeoutSeconds(10)
39+
.useHttpCache(true)
40+
.pollIntervalSeconds(5)
41+
.build();
42+
connector = HttpConnector.builder()
43+
.httpConnectorOptions(httpConnectorOptions)
44+
.build();
45+
BlockingQueue<QueuePayload> queue = connector.getStreamQueue();
46+
delay(20000);
47+
assertEquals(1, queue.size());
48+
} finally {
49+
if (connector != null) {
50+
connector.shutdown();
51+
}
52+
}
53+
}
54+
55+
public static boolean parseBoolean(String key) {
56+
return Boolean.parseBoolean(System.getProperty(key, System.getenv(key)));
57+
}
58+
59+
}

0 commit comments

Comments
 (0)