Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit e1855d1

Browse files
committed
Merge pull request #42 from launchdarkly/dr/bounded
Implement Bounded Resource Consumption
2 parents d2c451d + c7c7e3b commit e1855d1

File tree

14 files changed

+564
-140
lines changed

14 files changed

+564
-140
lines changed

build.gradle

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,21 @@ apply plugin: 'signing'
55
apply plugin: 'idea'
66
apply plugin: 'com.github.johnrengelman.shadow'
77

8+
configurations.all {
9+
// check for updates every build for dependencies with: 'changing: true'
10+
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
11+
}
12+
813
repositories {
9-
mavenCentral()
1014
mavenLocal()
15+
// Before LaunchDarkly release artifacts get synced to Maven Central they are here along with snapshots:
16+
maven { url "https://oss.sonatype.org/content/groups/public/" }
17+
mavenCentral()
1118
}
1219

1320
allprojects {
1421
group = 'com.launchdarkly'
15-
version = "0.20.0"
22+
version = "1.0.0-SNAPSHOT"
1623
sourceCompatibility = 1.7
1724
targetCompatibility = 1.7
1825
}
@@ -24,11 +31,11 @@ dependencies {
2431
compile "com.google.code.gson:gson:2.2.4"
2532
compile "com.google.guava:guava:19.0"
2633
compile "org.slf4j:slf4j-api:1.7.7"
27-
compile "com.launchdarkly:okhttp-eventsource:0.1.0"
34+
compile group: "com.launchdarkly", name: "okhttp-eventsource", version: "0.1.3-SNAPSHOT", changing: true
2835
compile "redis.clients:jedis:2.8.0"
29-
testCompile "org.easymock:easymock:3.3"
36+
testCompile "org.easymock:easymock:3.4"
3037
testCompile 'junit:junit:[4.10,)'
31-
testRuntime "org.slf4j:slf4j-simple:1.7.7"
38+
testRuntime "ch.qos.logback:logback-classic:1.1.3"
3239
}
3340

3441
jar {
@@ -50,7 +57,7 @@ buildscript {
5057
}
5158
dependencies {
5259
classpath 'org.ajoberstar:gradle-git:0.12.0'
53-
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.2'
60+
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3'
5461
}
5562
}
5663

@@ -125,12 +132,6 @@ uploadArchives {
125132
description 'Official LaunchDarkly SDK for Java'
126133
url 'https://github.com/launchdarkly/java-client'
127134

128-
scm {
129-
connection 'scm:svn:http://foo.googlecode.com/svn/trunk/'
130-
developerConnection 'scm:svn:https://foo.googlecode.com/svn/trunk/'
131-
url 'http://foo.googlecode.com/svn/trunk/'
132-
}
133-
134135
licenses {
135136
license {
136137
name 'The Apache License, Version 2.0'

src/main/java/com/launchdarkly/client/EventProcessor.java

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.launchdarkly.client;
22

3+
import com.google.common.util.concurrent.ThreadFactoryBuilder;
34
import com.google.gson.Gson;
45
import org.apache.http.HttpStatus;
56
import org.apache.http.client.methods.CloseableHttpResponse;
@@ -14,22 +15,34 @@
1415
import java.io.IOException;
1516
import java.util.ArrayList;
1617
import java.util.List;
18+
import java.util.Random;
1719
import java.util.concurrent.*;
1820

1921
class EventProcessor implements Closeable {
20-
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory());
22+
private final ScheduledExecutorService scheduler;
23+
private final Random random = new Random();
2124
private final BlockingQueue<Event> queue;
2225
private final String apiKey;
26+
private final LDConfig config;
2327
private final Consumer consumer;
2428

2529
EventProcessor(String apiKey, LDConfig config) {
2630
this.apiKey = apiKey;
2731
this.queue = new ArrayBlockingQueue<>(config.capacity);
2832
this.consumer = new Consumer(config);
33+
this.config = config;
34+
ThreadFactory threadFactory = new ThreadFactoryBuilder()
35+
.setDaemon(true)
36+
.setNameFormat("LaunchDarkly-EventProcessor-%d")
37+
.build();
38+
this.scheduler = Executors.newSingleThreadScheduledExecutor(threadFactory);
2939
this.scheduler.scheduleAtFixedRate(consumer, 0, config.flushInterval, TimeUnit.SECONDS);
3040
}
3141

3242
boolean sendEvent(Event e) {
43+
if (config.samplingInterval > 0 && random.nextInt(config.samplingInterval) != 0) {
44+
return true;
45+
}
3346
return queue.offer(e);
3447
}
3548

@@ -43,18 +56,8 @@ public void flush() {
4356
this.consumer.flush();
4457
}
4558

46-
static class DaemonThreadFactory implements ThreadFactory {
47-
public Thread newThread(Runnable r) {
48-
Thread thread = new Thread(r);
49-
thread.setDaemon(true);
50-
return thread;
51-
}
52-
}
53-
5459
class Consumer implements Runnable {
5560
private final Logger logger = LoggerFactory.getLogger(Consumer.class);
56-
57-
5861
private final CloseableHttpClient client;
5962
private final LDConfig config;
6063

@@ -78,6 +81,7 @@ public void flush() {
7881
}
7982

8083
private void postEvents(List<Event> events) {
84+
logger.debug("Posting " + events.size() + " event(s)..");
8185
CloseableHttpResponse response = null;
8286
Gson gson = new Gson();
8387
String json = gson.toJson(events);
@@ -95,24 +99,21 @@ private void postEvents(List<Event> events) {
9599
if (status >= 300) {
96100
if (status == HttpStatus.SC_UNAUTHORIZED) {
97101
logger.error("Invalid API key");
98-
}
99-
else {
102+
} else {
100103
logger.error("Unexpected status code: " + status);
101104
}
102-
}
103-
else {
104-
logger.debug("Successfully processed events");
105+
} else {
106+
logger.debug("Successfully posted " + events.size() + " event(s).");
105107
}
106108
} catch (IOException e) {
107-
logger.error("Unhandled exception in LaunchDarkly client", e);
109+
logger.error("Unhandled exception in LaunchDarkly client attempting to connect to URI: " + config.eventsURI, e);
108110
} finally {
109111
try {
110112
if (response != null) response.close();
111113
} catch (IOException e) {
112114
logger.error("Unhandled exception in LaunchDarkly client", e);
113115
}
114116
}
115-
116117
}
117118
}
118119
}

src/main/java/com/launchdarkly/client/FeatureRequestor.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ Map<String, FeatureRep<?>> makeAllRequest(boolean latest) throws IOException {
6868

6969
CloseableHttpResponse response = null;
7070
try {
71+
logger.debug("Making request: " + request);
7172
response = client.execute(request, context);
7273

7374
logCacheResponse(context.getCacheResponseStatus());
@@ -76,7 +77,10 @@ Map<String, FeatureRep<?>> makeAllRequest(boolean latest) throws IOException {
7677

7778
Type type = new TypeToken<Map<String, FeatureRep<?>>>() {}.getType();
7879

79-
Map<String, FeatureRep<?>> result = gson.fromJson(EntityUtils.toString(response.getEntity()), type);
80+
String json = EntityUtils.toString(response.getEntity());
81+
logger.debug("Got response: " + response.toString());
82+
logger.debug("Got Response body: " + json);
83+
Map<String, FeatureRep<?>> result = gson.fromJson(json, type);
8084
return result;
8185
}
8286
finally {

src/main/java/com/launchdarkly/client/InMemoryFeatureStore.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
*/
1313
public class InMemoryFeatureStore implements FeatureStore {
1414

15-
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
16-
final Map<String, FeatureRep<?>> features = new HashMap<>();
17-
volatile boolean initialized = false;
15+
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
16+
private final Map<String, FeatureRep<?>> features = new HashMap<>();
17+
private volatile boolean initialized = false;
1818

1919

2020
/**

0 commit comments

Comments
 (0)