Skip to content

Commit

Permalink
prepare 2.1.0 release (#45)
Browse files Browse the repository at this point in the history
  • Loading branch information
LaunchDarklyCI authored Apr 29, 2020
1 parent 330d30b commit fbfae6a
Show file tree
Hide file tree
Showing 13 changed files with 1,024 additions and 534 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@ All notable changes to the LaunchDarkly EventSource implementation for Java will
### Removed:
- In `EventSource`: `setHttpUrl`, `setLastEventId`, `setMaxReconnectTime`, `setReconnectionTime`, `setUri` (these can only be set in the builder).

## [1.11.0] - 2020-03-30
### Added:
- New `EventSource` method `restart()` allows the caller to force a stream connection retry even if no I/O error has happened, using the same backoff behavior that would be used for errors.

## [1.10.2] - 2020-03-20
### Changed:
- Updated OkHttp version to 3.12.10 (the latest version that still supports Java 7).

## [1.10.1] - 2019-10-17
### Fixed:
- Fixed trailing period in logger name. ([#34](https://github.com/launchdarkly/okhttp-eventsource/issues/34))
- If you provide your own value for the `Accept` header using `EventSource.Builder.headers()`, it should not _also_ send the default `Accept: text/event-stream`, but replace it. ([#38](https://github.com/launchdarkly/okhttp-eventsource/issues/38))


## [1.10.0] - 2019-08-01
### Added:
- `EventSource.Builder.clientBuilderActions()` allows you to modify the OkHttp client options in any way, such as customizing TLS behavior or any other methods supported by `OkHttpClient.Builder`.
Expand Down
41 changes: 27 additions & 14 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ plugins {
id "java-library"
id "signing"
id "maven-publish"
id "de.marcphilipp.nexus-publish" version "0.3.0"
id "de.marcphilipp.nexus-publish" version "0.4.0"
id "io.codearte.nexus-staging" version "0.21.2"
id "org.ajoberstar.git-publish" version "2.1.3"
id "idea"
Expand All @@ -27,27 +27,29 @@ repositories {
allprojects {
group = 'com.launchdarkly'
version = "${version}"
archivesBaseName = 'okhttp-eventsource'
sourceCompatibility = 1.8
targetCompatibility = 1.8
}

dependencies {
compile "com.squareup.okhttp3:okhttp:4.3.1"
compile "org.slf4j:slf4j-api:1.7.22"
testRuntime "ch.qos.logback:logback-classic:1.1.9"
testCompile "org.mockito:mockito-core:1.10.19"
testCompile "com.squareup.okhttp3:mockwebserver:4.3.1"
testCompile "junit:junit:4.11"
}
ext.versions = [
"okhttp": "4.5.0",
"slf4j": "1.7.22"
]

task wrapper(type: Wrapper) {
gradleVersion = '4.10.2'
dependencies {
api "com.squareup.okhttp3:okhttp:${versions.okhttp}"
api "org.slf4j:slf4j-api:${versions.slf4j}"
testImplementation "ch.qos.logback:logback-classic:1.1.9"
testImplementation "org.mockito:mockito-core:1.10.19"
testImplementation "org.eclipse.jetty:jetty-server:9.4.27.v20200227"
testImplementation "junit:junit:4.12"
testImplementation "org.hamcrest:hamcrest-all:1.3"
}

jar {
baseName = 'okhttp-eventsource'
manifest {
attributes("Implementation-Version": version)
attributes("Implementation-Version": project.version)
}
}

Expand All @@ -61,6 +63,17 @@ task javadocJar(type: Jar, dependsOn: javadoc) {
from javadoc.destinationDir
}

javadoc {
// Force the Javadoc build to fail if there are any Javadoc warnings. See: https://discuss.gradle.org/t/javadoc-fail-on-warning/18141/3
// The '-quiet' as second argument is actually a hack,
// since the one parameter addStringOption doesn't seem to
// work, we extra add '-quiet', which is added anyway by
// gradle. See https://github.com/gradle/gradle/issues/2354
// See JDK-8200363 (https://bugs.openjdk.java.net/browse/JDK-8200363)
// for information about the -Xwerror option.
options.addStringOption('Xwerror', '-quiet')
}

test {
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
Expand Down Expand Up @@ -111,7 +124,7 @@ publishing {
scm {
connection = 'scm:git:git://github.com/launchdarkly/okhttp-eventsource.git'
developerConnection = 'scm:git:ssh:git@github.com:launchdarkly/okhttp-eventsource.git'
url = 'http://example.com/my-library/'
url = 'https://github.com/launchdarkly/okhttp-eventsource'
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
version=2.0.1
ossrhUsername=
ossrhPassword=

# See https://github.com/gradle/gradle/issues/11308 regarding the following property
systemProp.org.gradle.internal.publish.checksums.insecure=true
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
10 changes: 10 additions & 0 deletions src/main/java/com/launchdarkly/eventsource/EventHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ public interface EventHandler {

/**
* EventSource calls this method when the stream connection has been closed.
* <p>
* This method is <i>not</i> called if the connection was closed due to a {@link ConnectionErrorHandler}
* returning {@link ConnectionErrorHandler.Action#SHUTDOWN}; EventSource assumes that if you registered
* such a handler and made it return that value, then you already know that the connection is being closed.
*
* @throws Exception throwing an exception here will cause it to be logged and also sent to {@link #onError(Throwable)}
*/
void onClosed() throws Exception;
Expand All @@ -36,6 +41,11 @@ public interface EventHandler {
* an {@link UnsuccessfulResponseException} if the server returns an unexpected HTTP status),
* but only after the {@link ConnectionErrorHandler} (if any) has processed it. If you need to
* do anything that affects the state of the connection, use {@link ConnectionErrorHandler}.
* <p>
* This method is <i>not</i> called if the error was already passed to a {@link ConnectionErrorHandler}
* which returned {@link ConnectionErrorHandler.Action#SHUTDOWN}; EventSource assumes that if you registered
* such a handler and made it return that value, then you do not want to handle the same error twice.
*
* @param t a {@code Throwable} object
*/
void onError(Throwable t);
Expand Down
70 changes: 51 additions & 19 deletions src/main/java/com/launchdarkly/eventsource/EventSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,27 @@ public void start() {
logger.info("Starting EventSource client using URI: " + url);
streamExecutor.execute(this::connect);
}


/**
* Drops the current stream connection (if any) and attempts to reconnect.
* <p>
* This method returns immediately after dropping the current connection; the reconnection happens on
* a worker thread.
* <p>
* If a connection attempt is already in progress but has not yet connected, or if {@link #close()} has
* previously been called, this method has no effect. If {@link #start()} has never been called, it is
* the same as calling {@link #start()}.
*/
public void restart() {
ReadyState previousState = readyState.getAndUpdate(t -> t == ReadyState.OPEN ? ReadyState.CLOSED : t);
if (previousState == OPEN) {
closeCurrentStream(previousState);
} else if (previousState == RAW || previousState == CONNECTING) {
start();
}
// if already shutdown or in the process of closing, do nothing
}

/**
* Returns an enum indicating the current status of the connection.
* @return a {@link ReadyState} value
Expand All @@ -161,28 +181,18 @@ public ReadyState getState() {
return readyState.get();
}

/**
* Drops the current stream connection (if any) and permanently shuts down the EventSource.
*/
@Override
public void close() {
ReadyState currentState = readyState.getAndSet(SHUTDOWN);
logger.debug("readyState change: " + currentState + " -> " + SHUTDOWN);
if (currentState == SHUTDOWN) {
return;
}
if (currentState == ReadyState.OPEN) {
try {
handler.onClosed();
} catch (Exception e) {
handler.onError(e);
}
}

if (call != null) {
// The call.cancel() must precede the bufferedSource.close().
// Otherwise, an IllegalArgumentException "Unbalanced enter/exit" error is thrown by okhttp.
// https://github.com/google/ExoPlayer/issues/1348
call.cancel();
logger.debug("call cancelled");
}

closeCurrentStream(currentState);

eventExecutor.shutdownNow();
streamExecutor.shutdownNow();
Expand All @@ -200,6 +210,24 @@ public void close() {
}
}

private void closeCurrentStream(ReadyState previousState) {
if (previousState == ReadyState.OPEN) {
try {
handler.onClosed();
} catch (Exception e) {
handler.onError(e);
}
}

if (call != null) {
// The call.cancel() must precede the bufferedSource.close().
// Otherwise, an IllegalArgumentException "Unbalanced enter/exit" error is thrown by okhttp.
// https://github.com/google/ExoPlayer/issues/1348
call.cancel();
logger.debug("call cancelled");
}
}

Request buildRequest() {
Request.Builder builder = new Request.Builder()
.headers(headers)
Expand Down Expand Up @@ -271,11 +299,14 @@ public void setLastEventId(String lastEventId) {
} catch (EOFException eofe) {
logger.warn("Connection unexpectedly closed.");
} catch (IOException ioe) {
if (readyState.get() != SHUTDOWN) {
ReadyState state = readyState.get();
if (state == SHUTDOWN) {
errorHandlerAction = ConnectionErrorHandler.Action.SHUTDOWN;
} else if (state == CLOSED) { // this happens if it's being restarted
errorHandlerAction = ConnectionErrorHandler.Action.PROCEED;
} else {
logger.debug("Connection problem.", ioe);
errorHandlerAction = dispatchError(ioe);
} else {
errorHandlerAction = ConnectionErrorHandler.Action.SHUTDOWN;
}
} finally {
ReadyState nextState = CLOSED;
Expand Down Expand Up @@ -307,6 +338,7 @@ public void setLastEventId(String lastEventId) {
handler.onError(e);
}
}

// Reset the backoff if we had a successful connection that stayed good for at least
// backoffResetThresholdMs milliseconds.
if (connectedTime >= 0 && (System.currentTimeMillis() - connectedTime) >= backoffResetThreshold.toMillis()) {
Expand Down
Loading

0 comments on commit fbfae6a

Please sign in to comment.