diff --git a/.pubnub.yml b/.pubnub.yml index d87511a8a..354e13766 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -1,9 +1,9 @@ name: java -version: 6.4.4 +version: 6.4.5 schema: 1 scm: github.com/pubnub/java files: - - build/libs/pubnub-gson-6.4.4-all.jar + - build/libs/pubnub-gson-6.4.5-all.jar sdks: - type: library @@ -23,8 +23,8 @@ sdks: - distribution-type: library distribution-repository: maven - package-name: pubnub-gson-6.4.4 - location: https://repo.maven.apache.org/maven2/com/pubnub/pubnub-gson/6.4.4/pubnub-gson-6.4.4.jar + package-name: pubnub-gson-6.4.5 + location: https://repo.maven.apache.org/maven2/com/pubnub/pubnub-gson/6.4.5/pubnub-gson-6.4.5.jar supported-platforms: supported-operating-systems: Android: @@ -115,6 +115,13 @@ sdks: is-required: Required changelog: + - date: 2023-12-18 + version: v6.4.5 + changes: + - type: bug + text: "Added reading message type from fetch messages response." + - type: bug + text: "Added random value 0.001-0.999s to delay between retries both for Linear and Exponential reconnection policies." - date: 2023-11-30 version: v6.4.4 changes: diff --git a/CHANGELOG.md b/CHANGELOG.md index cba23543a..3ad1b6de8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## v6.4.5 +December 18 2023 + +#### Fixed +- Added reading message type from fetch messages response. +- Added random value 0.001-0.999s to delay between retries both for Linear and Exponential reconnection policies. + ## v6.4.4 November 30 2023 diff --git a/README.md b/README.md index a571cd500..6963ac7cc 100644 --- a/README.md +++ b/README.md @@ -22,13 +22,13 @@ You will need the publish and subscribe keys to authenticate your app. Get your com.pubnub pubnub-gson - 6.4.4 + 6.4.5 ``` * for Gradle, add the following dependency in your `gradle.build`: ```groovy - implementation 'com.pubnub:pubnub-gson:6.4.4' + implementation 'com.pubnub:pubnub-gson:6.4.5' ``` 2. Configure your keys: diff --git a/build.gradle b/build.gradle index 42388c3ee..387f1b4f8 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ plugins { } group = 'com.pubnub' -version = '6.4.4' +version = '6.4.5' description = """""" diff --git a/gradle.properties b/gradle.properties index abe45b364..33684a749 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ SONATYPE_HOST=DEFAULT SONATYPE_AUTOMATIC_RELEASE=true GROUP=com.pubnub POM_ARTIFACT_ID=pubnub-gson -VERSION_NAME=6.4.4 +VERSION_NAME=6.4.5 POM_PACKAGING=jar POM_NAME=PubNub Java SDK diff --git a/src/main/java/com/pubnub/api/PNConfiguration.java b/src/main/java/com/pubnub/api/PNConfiguration.java index e646c07d6..3f509ad5a 100644 --- a/src/main/java/com/pubnub/api/PNConfiguration.java +++ b/src/main/java/com/pubnub/api/PNConfiguration.java @@ -38,6 +38,7 @@ public class PNConfiguration { private static final int SUBSCRIBE_TIMEOUT = 310; private static final int CONNECT_TIMEOUT = 5; private static final int FILE_MESSAGE_PUBLISH_RETRY_LIMIT = 5; + private static final int MAXIMUM_RECONNECTION_RETRIES_DEFAULT = -1; // infinite @Getter private SSLSocketFactory sslSocketFactory; @@ -201,7 +202,8 @@ public void setUserId(@NotNull UserId userId) { private PNReconnectionPolicy reconnectionPolicy; /** - * Set how many times the reconneciton manager will try to connect before giving app + * Set how many times the reconnection manager will try to connect before giving up. + * Default is -1 which means to retry infinitely. */ @Setter private int maximumReconnectionRetries; @@ -284,7 +286,7 @@ public PNConfiguration(@NotNull UserId userId) throws PubNubException { startSubscriberThread = true; - maximumReconnectionRetries = -1; + maximumReconnectionRetries = MAXIMUM_RECONNECTION_RETRIES_DEFAULT; dedupOnSubscribe = false; suppressLeaveEvents = false; diff --git a/src/main/java/com/pubnub/api/PubNub.java b/src/main/java/com/pubnub/api/PubNub.java index 1928b77e0..9c82a08c8 100644 --- a/src/main/java/com/pubnub/api/PubNub.java +++ b/src/main/java/com/pubnub/api/PubNub.java @@ -105,7 +105,7 @@ public class PubNub { private static final int TIMESTAMP_DIVIDER = 1000; private static final int MAX_SEQUENCE = 65535; - private static final String SDK_VERSION = "6.4.4"; + private static final String SDK_VERSION = "6.4.5"; private final ListenerManager listenerManager; private final StateManager stateManager; diff --git a/src/main/java/com/pubnub/api/managers/DelayedReconnectionManager.java b/src/main/java/com/pubnub/api/managers/DelayedReconnectionManager.java index 7a84b8599..afac4d367 100644 --- a/src/main/java/com/pubnub/api/managers/DelayedReconnectionManager.java +++ b/src/main/java/com/pubnub/api/managers/DelayedReconnectionManager.java @@ -5,17 +5,19 @@ import com.pubnub.api.enums.PNReconnectionPolicy; import lombok.extern.slf4j.Slf4j; +import java.util.Random; import java.util.Timer; import java.util.TimerTask; @Slf4j public class DelayedReconnectionManager { - private static final int DELAY_SECONDS = 3; - private static final int MILLISECONDS = 1000; + private static final int BASE_DELAY_MILLISECONDS = 2000; + private static final int BOUND = 1000; private final PNReconnectionPolicy pnReconnectionPolicy; private ReconnectionCallback callback; private PubNub pubnub; + private final Random random = new Random(); /** * Timer for heartbeat operations. @@ -34,12 +36,13 @@ public void scheduleDelayedReconnection() { } timer = new Timer("Delayed Reconnection Manager timer", true); + int effectiveDelayInMilliSeconds = (int) (BASE_DELAY_MILLISECONDS + getRandomDelayInMilliSeconds()); timer.schedule(new TimerTask() { @Override public void run() { callTime(); } - }, DELAY_SECONDS * MILLISECONDS); + }, effectiveDelayInMilliSeconds); } public void setReconnectionListener(ReconnectionCallback reconnectionCallback) { @@ -61,6 +64,10 @@ private boolean isReconnectionPolicyUndefined() { return false; } + private int getRandomDelayInMilliSeconds() { + return random.nextInt(BOUND); + } + private void callTime() { stop(); callback.onReconnection(); diff --git a/src/main/java/com/pubnub/api/managers/ReconnectionManager.java b/src/main/java/com/pubnub/api/managers/ReconnectionManager.java index 7a1cc4858..6631d3dcf 100644 --- a/src/main/java/com/pubnub/api/managers/ReconnectionManager.java +++ b/src/main/java/com/pubnub/api/managers/ReconnectionManager.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Calendar; +import java.util.Random; import java.util.Timer; import java.util.TimerTask; @@ -17,11 +18,13 @@ @Slf4j public class ReconnectionManager { - private static final int LINEAR_INTERVAL = 3; - private static final int MIN_EXPONENTIAL_BACKOFF = 1; + private static final int BASE_LINEAR_INTERVAL_IN_MILLISECONDS = 3000; + private static final int MIN_EXPONENTIAL_BACKOFF = 2; private static final int MAX_EXPONENTIAL_BACKOFF = 32; - private static final int MILLISECONDS = 1000; + private static final int BOUND = 1000; + private static final int MILLISECONDS = BOUND; + private static final int MAXIMUM_RECONNECTION_RETRIES_DEFAULT = 10; private ReconnectionCallback callback; private PubNub pubnub; @@ -31,6 +34,7 @@ public class ReconnectionManager { private PNReconnectionPolicy pnReconnectionPolicy; private int maxConnectionRetries; + private final Random random = new Random(); /** * Timer for heartbeat operations. @@ -55,10 +59,10 @@ public void startPolling() { exponentialMultiplier = 1; failedCalls = 0; - registerHeartbeatTimer(); + registerRetryTimer(); } - private void registerHeartbeatTimer() { + private void registerRetryTimer() { // make sure only one timer is running at a time. stopHeartbeatTimer(); @@ -66,7 +70,7 @@ private void registerHeartbeatTimer() { return; } - if (maxConnectionRetries != -1 && failedCalls >= maxConnectionRetries) { // _what's -1? + if (!maxConnectionIsSetToInfinite() && failedCalls >= maxConnectionRetries) { callback.onMaxReconnectionExhaustion(); return; } @@ -78,11 +82,15 @@ private void registerHeartbeatTimer() { public void run() { callTime(); } - }, getNextInterval() * MILLISECONDS); + }, getNextIntervalInMilliSeconds()); } - int getNextInterval() { - int timerInterval = LINEAR_INTERVAL; + private boolean maxConnectionIsSetToInfinite() { + return maxConnectionRetries == -1; + } + + int getNextIntervalInMilliSeconds() { + int timerInterval = 0; failedCalls++; if (pnReconnectionPolicy == PNReconnectionPolicy.EXPONENTIAL) { @@ -91,20 +99,24 @@ int getNextInterval() { if (timerInterval > MAX_EXPONENTIAL_BACKOFF) { timerInterval = MIN_EXPONENTIAL_BACKOFF; exponentialMultiplier = 1; - log.debug("timerInterval > MAXEXPONENTIALBACKOFF at: " + Calendar.getInstance().getTime().toString()); + log.debug("timerInterval > MAXEXPONENTIALBACKOFF at: " + Calendar.getInstance().getTime()); } else if (timerInterval < 1) { timerInterval = MIN_EXPONENTIAL_BACKOFF; } - log.debug("timerInterval = " + timerInterval + " at: " + Calendar.getInstance().getTime().toString()); + timerInterval = (int) ((timerInterval * MILLISECONDS) + getRandomDelayInMilliSeconds()); + log.debug("timerInterval = " + timerInterval + "ms at: " + Calendar.getInstance().getTime()); } if (pnReconnectionPolicy == PNReconnectionPolicy.LINEAR) { - timerInterval = LINEAR_INTERVAL; + timerInterval = (int) (BASE_LINEAR_INTERVAL_IN_MILLISECONDS + getRandomDelayInMilliSeconds()); } - return timerInterval; } + private int getRandomDelayInMilliSeconds() { + return random.nextInt(BOUND); + } + private void stopHeartbeatTimer() { if (timer != null) { timer.cancel(); @@ -121,7 +133,7 @@ public void onResponse(PNTimeResult result, @NotNull PNStatus status) { callback.onReconnection(); } else { log.debug("callTime() at: " + Calendar.getInstance().getTime().toString()); - registerHeartbeatTimer(); + registerRetryTimer(); } } }); diff --git a/src/test/java/com/pubnub/api/PubNubTest.java b/src/test/java/com/pubnub/api/PubNubTest.java index 8a9350716..c139f68e8 100644 --- a/src/test/java/com/pubnub/api/PubNubTest.java +++ b/src/test/java/com/pubnub/api/PubNubTest.java @@ -100,7 +100,7 @@ public void getVersionAndTimeStamp() { pubnub = new PubNub(pnConfiguration); String version = pubnub.getVersion(); int timeStamp = pubnub.getTimestamp(); - Assert.assertEquals("6.4.4", version); + Assert.assertEquals("6.4.5", version); Assert.assertTrue(timeStamp > 0); } diff --git a/src/test/java/com/pubnub/api/managers/ReconnectionManagerTest.java b/src/test/java/com/pubnub/api/managers/ReconnectionManagerTest.java index 647e14bbf..2738eed96 100644 --- a/src/test/java/com/pubnub/api/managers/ReconnectionManagerTest.java +++ b/src/test/java/com/pubnub/api/managers/ReconnectionManagerTest.java @@ -9,7 +9,6 @@ import java.util.UUID; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class ReconnectionManagerTest { @@ -20,10 +19,11 @@ public void reconnectionIntervalsEqualsForLinear() throws PubNubException { pnConfiguration.setReconnectionPolicy(PNReconnectionPolicy.LINEAR); final ReconnectionManager reconnectionManagerUnderTest = new ReconnectionManager(pubNub); - int firstInterval = reconnectionManagerUnderTest.getNextInterval(); - int secondInterval = reconnectionManagerUnderTest.getNextInterval(); + int firstInterval = reconnectionManagerUnderTest.getNextIntervalInMilliSeconds(); + int secondInterval = reconnectionManagerUnderTest.getNextIntervalInMilliSeconds(); - assertEquals(secondInterval, firstInterval); + assertTrue(firstInterval >= 3000 && firstInterval <= 6000); + assertTrue(secondInterval >= 3000 && secondInterval <= 6000); } @Test @@ -33,9 +33,9 @@ public void reconnectionIntervalsIncreaseForExponential() throws PubNubException PubNub pubNub = new PubNub(pnConfiguration); final ReconnectionManager reconnectionManagerUnderTest = new ReconnectionManager(pubNub); - int firstInterval = reconnectionManagerUnderTest.getNextInterval(); - int secondInterval = reconnectionManagerUnderTest.getNextInterval(); - int thirdInterval = reconnectionManagerUnderTest.getNextInterval(); + int firstInterval = reconnectionManagerUnderTest.getNextIntervalInMilliSeconds(); + int secondInterval = reconnectionManagerUnderTest.getNextIntervalInMilliSeconds(); + int thirdInterval = reconnectionManagerUnderTest.getNextIntervalInMilliSeconds(); assertTrue(firstInterval < secondInterval); assertTrue(secondInterval < thirdInterval);