diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/PollingBase.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/PollingBase.java index 5cd1325..01d3f3d 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/PollingBase.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/PollingBase.java @@ -138,7 +138,9 @@ protected CompletableFuture poll(Selector selector, boolean on return oneShot ? FDv2SourceResult.terminalError(info, fdv1Fallback) : FDv2SourceResult.interrupted(info, fdv1Fallback); } case GOODBYE: - return FDv2SourceResult.goodbye(((FDv2ProtocolHandler.FDv2ActionGoodbye) res).getReason(), fdv1Fallback); + String reason = ((FDv2ProtocolHandler.FDv2ActionGoodbye) res).getReason(); + logger.info("Goodbye was received from the LaunchDarkly connection with reason: '{}'.", reason); + return FDv2SourceResult.goodbye(reason, fdv1Fallback); case NONE: break; case INTERNAL_ERROR: { diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/StreamingSynchronizerImpl.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/StreamingSynchronizerImpl.java index e0d8773..b902bea 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/StreamingSynchronizerImpl.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/StreamingSynchronizerImpl.java @@ -279,8 +279,9 @@ private void handleMessage(MessageEvent event) { break; case GOODBYE: - FDv2ProtocolHandler.FDv2ActionGoodbye goodbye = (FDv2ProtocolHandler.FDv2ActionGoodbye) action; - result = FDv2SourceResult.goodbye(goodbye.getReason(), getFallback(event)); + String reason = ((FDv2ProtocolHandler.FDv2ActionGoodbye) action).getReason(); + logger.info("Goodbye was received from the LaunchDarkly connection with reason: '{}'.", reason); + result = FDv2SourceResult.goodbye(reason, getFallback(event)); // We drop this current connection and attempt to restart the stream. restartStream(); break; diff --git a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/datasources/FDv2SourceResult.java b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/datasources/FDv2SourceResult.java index acd5e12..6b24109 100644 --- a/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/datasources/FDv2SourceResult.java +++ b/lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/datasources/FDv2SourceResult.java @@ -54,6 +54,8 @@ public static class Status { private final State state; private final DataSourceStatusProvider.ErrorInfo errorInfo; + private final String reason; + public State getState() { return state; } @@ -62,9 +64,34 @@ public DataSourceStatusProvider.ErrorInfo getErrorInfo() { return errorInfo; } - public Status(State state, DataSourceStatusProvider.ErrorInfo errorInfo) { + Status(State state, DataSourceStatusProvider.ErrorInfo errorInfo, String reason) { this.state = state; this.errorInfo = errorInfo; + this.reason = reason; + } + + public static Status goodbye(String reason) { + return new Status(State.GOODBYE, null, reason); + } + + public static Status interrupted(DataSourceStatusProvider.ErrorInfo errorInfo) { + return new Status(State.INTERRUPTED, errorInfo, null); + } + + public static Status terminalError(DataSourceStatusProvider.ErrorInfo errorInfo) { + return new Status(State.TERMINAL_ERROR, errorInfo, null); + } + + public static Status shutdown() { + return new Status(State.SHUTDOWN, null, null); + } + + /** + * If the state is GOODBYE, then this will be the reason. Otherwise, it will be null. + * @return the reason, or null + */ + public String getReason() { + return reason; } } @@ -97,7 +124,7 @@ public static FDv2SourceResult interrupted(DataSourceStatusProvider.ErrorInfo er public static FDv2SourceResult interrupted(DataSourceStatusProvider.ErrorInfo errorInfo, boolean fdv1Fallback, Function completionCallback) { return new FDv2SourceResult( null, - new Status(State.INTERRUPTED, errorInfo), + Status.interrupted(errorInfo), ResultType.STATUS, fdv1Fallback, completionCallback); @@ -109,7 +136,7 @@ public static FDv2SourceResult shutdown() { public static FDv2SourceResult shutdown(Function completionCallback) { return new FDv2SourceResult(null, - new Status(State.SHUTDOWN, null), + Status.shutdown(), ResultType.STATUS, false, completionCallback); @@ -121,7 +148,7 @@ public static FDv2SourceResult terminalError(DataSourceStatusProvider.ErrorInfo public static FDv2SourceResult terminalError(DataSourceStatusProvider.ErrorInfo errorInfo, boolean fdv1Fallback, Function completionCallback) { return new FDv2SourceResult(null, - new Status(State.TERMINAL_ERROR, errorInfo), + Status.terminalError(errorInfo), ResultType.STATUS, fdv1Fallback, completionCallback); @@ -145,10 +172,9 @@ public static FDv2SourceResult goodbye(String reason, boolean fdv1Fallback) { } public static FDv2SourceResult goodbye(String reason, boolean fdv1Fallback, Function completionCallback) { - // TODO: Goodbye reason. return new FDv2SourceResult( null, - new Status(State.GOODBYE, null), + Status.goodbye(reason), ResultType.STATUS, fdv1Fallback, completionCallback); diff --git a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/StreamingSynchronizerImplTest.java b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/StreamingSynchronizerImplTest.java index d7c2ae7..e7c0629 100644 --- a/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/StreamingSynchronizerImplTest.java +++ b/lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/StreamingSynchronizerImplTest.java @@ -141,6 +141,7 @@ public void httpRecoverableError() throws Exception { assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); assertEquals(FDv2SourceResult.State.INTERRUPTED, result.getStatus().getState()); assertEquals(DataSourceStatusProvider.ErrorKind.ERROR_RESPONSE, result.getStatus().getErrorInfo().getKind()); + assertNull(result.getStatus().getReason()); synchronizer.close(); } @@ -238,6 +239,7 @@ public void shutdownBeforeEventReceived() throws Exception { assertEquals(FDv2SourceResult.ResultType.STATUS, result.getResultType()); assertEquals(FDv2SourceResult.State.SHUTDOWN, result.getStatus().getState()); assertNull(result.getStatus().getErrorInfo()); + assertNull(result.getStatus().getReason()); } } @@ -314,6 +316,7 @@ public void goodbyeEventInResponse() throws Exception { assertNotNull(result1); assertEquals(FDv2SourceResult.ResultType.STATUS, result1.getResultType()); assertEquals(FDv2SourceResult.State.GOODBYE, result1.getStatus().getState()); + assertEquals("service-unavailable", result1.getStatus().getReason()); // Second result should be a changeset from the restarted stream CompletableFuture result2Future = synchronizer.next();