Skip to content

Commit

Permalink
Steel thread client + example app works
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Richelson committed Aug 19, 2016
0 parents commit ed62877
Show file tree
Hide file tree
Showing 49 changed files with 4,807 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
/.gradle
23 changes: 23 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.3'

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}
1 change: 1 addition & 0 deletions client/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
29 changes: 29 additions & 0 deletions client/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
apply plugin: 'com.android.library'

android {
compileSdkVersion 24
buildToolsVersion "24.0.1"

defaultConfig {
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.noveogroup.android:android-logger:1.3.1'
compile 'com.google.code.gson:gson:2.6.2'
compile 'com.launchdarkly:okhttp-eventsource:0.2.1'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
}
17 changes: 17 additions & 0 deletions client/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/dan/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
13 changes: 13 additions & 0 deletions client/src/android-logger.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Android Logger configuration example

# By default logger will print only ERROR (and higher) messages
# with "MyApplication" tag
#root=ERROR:MyApplication

# DEBUG (and higher) messages from classes of com.example.database
# will be logged with "MyApplication-Database" tag
#logger.com.example.database=DEBUG:MyApplication-Database

# All messages from classes of com.example.ui will be logged with
# "MyApplication-UI" tag
#logger.com.example.ui=MyApplication-UI
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.launchdarkly.android;

import android.app.Application;
import android.test.ApplicationTestCase;

/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}
14 changes: 14 additions & 0 deletions client/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.launchdarkly.android">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">
<activity android:name=".LaunchDarklyActivity" android:theme="@android:style/Theme.NoDisplay"/>
</application>

</manifest>
47 changes: 47 additions & 0 deletions client/src/main/java/com/launchdarkly/android/Event.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.launchdarkly.android;

import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName;

class Event {
Long creationDate;
String key;
String kind;
LDUser user;

Event(String kind, String key, LDUser user) {
this.creationDate = System.currentTimeMillis();
this.key = key;
this.kind = kind;
this.user = user;
}
}

class IdentifyEvent extends Event {

IdentifyEvent(LDUser user) {
super("identify", user.getKeyAsString(), user);
}
}

class CustomEvent extends Event {
private final JsonElement data;

CustomEvent(String key, LDUser user, JsonElement data) {
super("custom", key, user);
this.data = data;
}
}

class FeatureRequestEvent extends Event {
JsonElement value;
@SerializedName("default")
JsonElement defaultVal;


FeatureRequestEvent(String key, LDUser user, JsonElement value, JsonElement defaultVal) {
super("feature", key, user);
this.value = value;
this.defaultVal = defaultVal;
}
}
122 changes: 122 additions & 0 deletions client/src/main/java/com/launchdarkly/android/EventProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package com.launchdarkly.android;


import android.util.Log;

import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

import static com.launchdarkly.android.LDConfig.JSON;

class EventProcessor implements Closeable {
private static final String TAG = "LDEventProcessor";
private final ScheduledExecutorService scheduler;
private final Random random = new Random();
private final BlockingQueue<Event> queue;
private final LDConfig config;
private final Consumer consumer;
private final OkHttpClient client;

EventProcessor(LDConfig config) {
this.queue = new ArrayBlockingQueue<>(config.getEventsCapacity());
this.consumer = new Consumer(config);
this.config = config;
// ThreadFactory threadFactory = new ThreadFactoryBuilder()
// .setDaemon(true)
// .setNameFormat("LaunchDarkly-EventProcessor-%d")
// .build();

//TODO: maybe use daemon thread here
this.scheduler = Executors.newSingleThreadScheduledExecutor(Executors.defaultThreadFactory());
this.scheduler.scheduleAtFixedRate(consumer, 0, config.getEventsFlushIntervalMillis(), TimeUnit.MILLISECONDS);
client = new OkHttpClient.Builder()
.connectTimeout(this.config.getConnectionTimeoutMillis(), TimeUnit.MILLISECONDS)

// .cache() //TODO

This comment has been minimized.

Copy link
@jkodumal

jkodumal Aug 19, 2016

Contributor

I don't think we'll need to cache anything here.

.build();
}

boolean sendEvent(Event e) {
return queue.offer(e);
}

@Override
public void close() throws IOException {
scheduler.shutdown();
this.flush();
}

public void flush() {
this.consumer.flush();
}

class Consumer implements Runnable {
private LDConfig config;

Consumer(LDConfig config) {
this.config = config;
}

@Override
public void run() {
flush();
}

public void flush() {
List<Event> events = new ArrayList<>(queue.size());
queue.drainTo(events);

if (!events.isEmpty()) {
postEvents(events);
}
}

private void postEvents(List<Event> events) {

String content = LDConfig.GSON.toJson(events);
Request request = config.getRequestBuilder()
.url(config.getEventsUri().toString())
.post(RequestBody.create(JSON, content))
.addHeader("Content-Type", "application/json")

This comment has been minimized.

Copy link
@jkodumal

jkodumal Aug 19, 2016

Contributor

User agent header?

This comment has been minimized.

.build();


Log.d(TAG, "Posting " + events.size() + " event(s) to " + request.url());

// CloseableHttpResponse response = null;
// Gson gson = new Gson();
// String json = gson.toJson(events);
//
// HttpPost request = config.postEventsRequest(key, "/bulk");
// StringEntity entity = new StringEntity(json, "UTF-8");
// entity.setContentType("application/json");
// request.setEntity(entity);
Response response = null;
try {
response = client.newCall(request).execute();
Log.i(TAG, "Events Response: " + response.code());
// response = client.execute(request);
// if (Util.handleResponse(logger, request, response)) {
// logger.debug("Successfully posted " + events.size() + " event(s).");
// }
} catch (IOException e) {
Log.e(TAG, "Unhandled exception in LaunchDarkly client attempting to connect to URI: " + request.url(), e);
} finally {
if (response != null) response.close();
}
}
}
}
Loading

0 comments on commit ed62877

Please sign in to comment.