Skip to content

Commit

Permalink
Modified PNReconnectionPolicy (#297)
Browse files Browse the repository at this point in the history
* Modified PNReconnectionPolicy
Added random value 0,001-0,999s to delay between retry both for Linear and Exponential reconnection policies.

* PubNub SDK v6.4.5 release.
---------
Co-authored-by: PubNub Release Bot <120067856+pubnub-release-bot@users.noreply.github.com>
  • Loading branch information
marcin-cebo authored Dec 18, 2023
1 parent 94ae18e commit e4ec49a
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 36 deletions.
15 changes: 11 additions & 4 deletions .pubnub.yml
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ You will need the publish and subscribe keys to authenticate your app. Get your
<dependency>
<groupId>com.pubnub</groupId>
<artifactId>pubnub-gson</artifactId>
<version>6.4.4</version>
<version>6.4.5</version>
</dependency>
```

* 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:
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ plugins {
}
group = 'com.pubnub'

version = '6.4.4'
version = '6.4.5'

description = """"""

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/pubnub/api/PNConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -284,7 +286,7 @@ public PNConfiguration(@NotNull UserId userId) throws PubNubException {

startSubscriberThread = true;

maximumReconnectionRetries = -1;
maximumReconnectionRetries = MAXIMUM_RECONNECTION_RETRIES_DEFAULT;

dedupOnSubscribe = false;
suppressLeaveEvents = false;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/pubnub/api/PubNub.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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) {
Expand All @@ -61,6 +64,10 @@ private boolean isReconnectionPolicyUndefined() {
return false;
}

private int getRandomDelayInMilliSeconds() {
return random.nextInt(BOUND);
}

private void callTime() {
stop();
callback.onReconnection();
Expand Down
40 changes: 26 additions & 14 deletions src/main/java/com/pubnub/api/managers/ReconnectionManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,21 @@
import org.jetbrains.annotations.NotNull;

import java.util.Calendar;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;


@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;
Expand All @@ -31,6 +34,7 @@ public class ReconnectionManager {

private PNReconnectionPolicy pnReconnectionPolicy;
private int maxConnectionRetries;
private final Random random = new Random();

/**
* Timer for heartbeat operations.
Expand All @@ -55,18 +59,18 @@ 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();

if (isReconnectionPolicyUndefined()) {
return;
}

if (maxConnectionRetries != -1 && failedCalls >= maxConnectionRetries) { // _what's -1?
if (!maxConnectionIsSetToInfinite() && failedCalls >= maxConnectionRetries) {
callback.onMaxReconnectionExhaustion();
return;
}
Expand All @@ -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) {
Expand All @@ -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();
Expand All @@ -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();
}
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/com/pubnub/api/PubNubTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

import java.util.UUID;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class ReconnectionManagerTest {
Expand All @@ -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
Expand All @@ -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);
Expand Down

0 comments on commit e4ec49a

Please sign in to comment.