Skip to content

Commit

Permalink
Return in callback PNReconnectedCategory status for reconnect method (#…
Browse files Browse the repository at this point in the history
…227)

Return in callback PNReconnectedCategory status for reconnect method
  • Loading branch information
kleewho authored Dec 10, 2021
1 parent dd37701 commit cc10618
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 17 deletions.
17 changes: 11 additions & 6 deletions .pubnub.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: java
version: v5.2.3
version: v5.2.4
schema: 1
scm: github.com/pubnub/java
files:
- build/libs/pubnub-gson-5.2.3-all.jar
- build/libs/pubnub-gson-5.2.4-all.jar
sdks:
-
type: library
Expand All @@ -23,8 +23,8 @@ sdks:
-
distribution-type: library
distribution-repository: git release
package-name: pubnub-gson-5.2.3
location: https://github.com/pubnub/java/releases/download/v5.2.3/pubnub-gson-5.2.3-all.jar
package-name: pubnub-gson-5.2.4
location: https://github.com/pubnub/java/releases/download/v5.2.4/pubnub-gson-5.2.4-all.jar
supported-platforms:
supported-operating-systems:
Android:
Expand Down Expand Up @@ -135,8 +135,8 @@ sdks:
-
distribution-type: library
distribution-repository: maven
package-name: pubnub-gson-5.2.3
location: https://repo.maven.apache.org/maven2/com/pubnub/pubnub-gson/5.2.3/pubnub-gson-5.2.3.jar
package-name: pubnub-gson-5.2.4
location: https://repo.maven.apache.org/maven2/com/pubnub/pubnub-gson/5.2.4/pubnub-gson-5.2.4.jar
supported-platforms:
supported-operating-systems:
Android:
Expand Down Expand Up @@ -234,6 +234,11 @@ sdks:
is-required: Required

changelog:
- date: 2021-12-09
version: v5.2.4
changes:
- type: bug
text: "Emit PNReconnectedCategory in case of successful manual reconnection."
- date: 2021-11-17
version: v5.2.3
changes:
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## v5.2.4
December 09 2021

#### Fixed
- Emit PNReconnectedCategory in case of successful manual reconnection.

## v5.2.3
November 17 2021

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ You will need the publish and subscribe keys to authenticate your app. Get your
<dependency>
<groupId>com.pubnub</groupId>
<artifactId>pubnub-gson</artifactId>
<version>5.2.3</version>
<version>5.2.4</version>
</dependency>
```

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ plugins {
}
group = 'com.pubnub'

version = '5.2.3'
version = '5.2.4'

description = """"""

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 @@ -103,7 +103,7 @@ public class PubNub {
private static final int TIMESTAMP_DIVIDER = 1000;
private static final int MAX_SEQUENCE = 65535;

private static final String SDK_VERSION = "5.2.3";
private static final String SDK_VERSION = "5.2.4";
private final ListenerManager listenerManager;
private final StateManager stateManager;

Expand Down
19 changes: 13 additions & 6 deletions src/main/java/com/pubnub/api/managers/StateManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.pubnub.api.builder.dto.SubscribeOperation;
import com.pubnub.api.builder.dto.TimetokenAndRegionOperation;
import com.pubnub.api.builder.dto.UnsubscribeOperation;
import com.pubnub.api.enums.PNStatusCategory;
import com.pubnub.api.models.SubscriptionItem;
import lombok.AllArgsConstructor;
import lombok.Data;
Expand Down Expand Up @@ -67,7 +68,7 @@ private static class TemporaryUnavailableItem {
private String region = null;

private final PNConfiguration configuration;
private boolean shouldAnnounce = false;
private PNStatusCategory announceStatus = null;

public StateManager(final PNConfiguration configuration) {
this.configuration = configuration;
Expand All @@ -79,12 +80,12 @@ public synchronized boolean handleOperation(final PubSubOperation... pubSubOpera
if (pubSubOperation instanceof SubscribeOperation) {
if (adaptSubscribeBuilder((SubscribeOperation) pubSubOperation)) {
stateChanged = true;
shouldAnnounce = true;
announceStatus = PNStatusCategory.PNConnectedCategory;
}
} else if (pubSubOperation instanceof UnsubscribeOperation) {
unsubscribe((UnsubscribeOperation) pubSubOperation);
stateChanged = true;
shouldAnnounce = true;
announceStatus = PNStatusCategory.PNConnectedCategory;
} else if (pubSubOperation instanceof StateOperation) {
adaptStateBuilder((StateOperation) pubSubOperation);
} else if (pubSubOperation instanceof PresenceOperation) {
Expand All @@ -98,9 +99,12 @@ public synchronized boolean handleOperation(final PubSubOperation... pubSubOpera
} else if (pubSubOperation instanceof ChangeTemporaryUnavailableOperation) {
changeTemporary((ChangeTemporaryUnavailableOperation) pubSubOperation);
} else if (pubSubOperation instanceof PubSubOperation.ConnectedStatusAnnouncedOperation) {
shouldAnnounce = false;
announceStatus = null;
} else if (pubSubOperation instanceof PubSubOperation.ReconnectOperation) {
stateChanged = true;
announceStatus = PNStatusCategory.PNReconnectedCategory;
storedTimetoken = timetoken;
timetoken = 0L;
}
}
return stateChanged;
Expand Down Expand Up @@ -129,7 +133,7 @@ public synchronized SubscriptionStateData subscriptionStateData(Boolean includeP
region,
hasAnythingToSubscribe(),
subscribedToOnlyTemporaryUnavailable(),
shouldAnnounce
announceStatus
);
}

Expand Down Expand Up @@ -474,7 +478,10 @@ public static class SubscriptionStateData {
private final String region;
private final boolean anythingToSubscribe;
private final boolean subscribedToOnlyTemporaryUnavailable;
private final boolean shouldAnnounce;
private final PNStatusCategory announceStatus;
public boolean isShouldAnnounce() {
return announceStatus != null;
}
}

@Data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ synchronized void startSubscribeLoop(final PubSubOperation... pubSubOperations)
final PubSubOperation statusAnnouncedOperation;
if (subscriptionStateData.isShouldAnnounce()) {
PNStatus pnStatus = createPublicStatus(status)
.category(PNStatusCategory.PNConnectedCategory)
.category(subscriptionStateData.getAnnounceStatus())
.error(false)
.build();
listenerManager.announce(pnStatus);
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 @@ -99,7 +99,7 @@ public void getVersionAndTimeStamp() {
pubnub = new PubNub(pnConfiguration);
String version = pubnub.getVersion();
int timeStamp = pubnub.getTimestamp();
Assert.assertEquals("5.2.3", version);
Assert.assertEquals("5.2.4", version);
Assert.assertTrue(timeStamp > 0);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,45 @@
import com.pubnub.api.builder.dto.ChangeTemporaryUnavailableOperation;
import com.pubnub.api.builder.dto.PubSubOperation;
import com.pubnub.api.builder.dto.SubscribeOperation;
import com.pubnub.api.enums.PNStatusCategory;
import com.pubnub.api.managers.subscription.utils.RequestDetails;
import com.pubnub.api.managers.subscription.utils.ResponseHolder;
import com.pubnub.api.managers.subscription.utils.ResponseSupplier;
import com.pubnub.api.managers.token_manager.TokenManager;
import com.pubnub.api.models.consumer.PNStatus;
import com.pubnub.api.models.server.SubscribeEnvelope;
import com.pubnub.api.models.server.SubscribeMetadata;
import com.pubnub.api.services.SubscribeService;
import okhttp3.MediaType;
import okhttp3.ResponseBody;
import org.awaitility.core.ThrowingRunnable;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import retrofit2.Response;

import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static com.pubnub.api.managers.subscription.utils.SubscriptionTestUtils.pubnub;
import static com.pubnub.api.managers.subscription.utils.SubscriptionTestUtils.retrofitManagerMock;
import static com.pubnub.api.managers.subscription.utils.SubscriptionTestUtils.telemetryManager;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.awaitility.Awaitility.await;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -253,6 +264,76 @@ public void run() throws Throwable {
});
}

@Test
public void sendReconnectedOnManualReconnect() {
long timeToken = System.currentTimeMillis();
final ResponseSupplier<SubscribeEnvelope> responseSupplier = new ResponseSupplier<SubscribeEnvelope>() {
private boolean first = true;

@Override
public ResponseHolder<SubscribeEnvelope> get(final RequestDetails requestDetails) {
try {
MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
}
if (first) {
first = false;
return new ResponseHolder<>(Response.error(500, ResponseBody.create(MediaType.parse("application/json"), "{}")));
}
final SubscribeEnvelope subscribeEnvelope = new SubscribeEnvelope(emptyList(),
new SubscribeMetadata(timeToken, FAKE_REGION));
return new ResponseHolder<>(Response.success(200, subscribeEnvelope));
}
};
final RetrofitManager retrofitManagerMock = retrofitManagerMock(responseSupplier);
final SubscriptionManager subscriptionManager = subscriptionManagerUnderTest(retrofitManagerMock);

final SubscribeOperation subscribeOperation = SubscribeOperation.builder()
.channels(singletonList("ch2"))
.channelGroups(singletonList("group2"))
.build();

subscriptionManager.adaptSubscribeBuilder(subscribeOperation);
subscriptionManager.reconnect();
ArgumentCaptor<PNStatus> statusArgumentCaptor = ArgumentCaptor.forClass(PNStatus.class);
await().atMost(1, SECONDS).untilAsserted(() -> verify(listenerManagerMock, times(2)).announce(statusArgumentCaptor.capture()));

List<PNStatusCategory> statusCategories = statusArgumentCaptor.getAllValues().stream().map(PNStatus::getCategory).collect(Collectors.toList());
MatcherAssert.assertThat(statusCategories, Matchers.hasItem(PNStatusCategory.PNReconnectedCategory));
}

@Test
public void reconnectUsesTT0ForFastUserNotification() {
final ResponseSupplier<SubscribeEnvelope> responseSupplier = requestDetails -> {
final SubscribeEnvelope subscribeEnvelope = new SubscribeEnvelope(emptyList(),
new SubscribeMetadata(System.currentTimeMillis(), FAKE_REGION));
try {
MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
}
return new ResponseHolder<>(Response.success(200, subscribeEnvelope));
};

final RetrofitManager retrofitManagerMock = retrofitManagerMock(responseSupplier);
final SubscribeService spiedSubscribeService = retrofitManagerMock.getSubscribeService();
final SubscriptionManager subscriptionManager = subscriptionManagerUnderTest(retrofitManagerMock);

final SubscribeOperation subscribeOperation = SubscribeOperation.builder()
.channels(singletonList("ch2"))
.channelGroups(singletonList("group2"))
.timetoken(42L)
.build();

subscriptionManager.adaptSubscribeBuilder(subscribeOperation);
await().atMost(1, SECONDS).untilAsserted(() -> verify(spiedSubscribeService, atLeast(2)).subscribe(any(), any(), any()));
subscriptionManager.reconnect();
ArgumentCaptor<Map<String, String>> queryParamsCaptor = ArgumentCaptor.forClass(Map.class);
await().atMost(1, SECONDS).untilAsserted(() -> verify(spiedSubscribeService, atLeast(1)).subscribe(any(), any(), queryParamsCaptor.capture()));

List<String> statusCategories = queryParamsCaptor.getAllValues().stream().map((map) -> map.get("tt")).collect(Collectors.toList());
MatcherAssert.assertThat(statusCategories, Matchers.hasItem("0"));
}

@NotNull
private SubscriptionManager subscriptionManagerUnderTest(final RetrofitManager retrofitManagerMock) {
final PubNub pubnub = spy(pubnub(retrofitManagerMock));
Expand Down

0 comments on commit cc10618

Please sign in to comment.