Update to Pushy v0.14.1.

This commit is contained in:
Jon Chambers 2020-06-05 10:19:47 -04:00 committed by Jon Chambers
parent 228ffcbfce
commit ba6ac778fc
4 changed files with 35 additions and 61 deletions

View File

@ -114,7 +114,7 @@
<dependency> <dependency>
<groupId>com.eatthepath</groupId> <groupId>com.eatthepath</groupId>
<artifactId>pushy</artifactId> <artifactId>pushy</artifactId>
<version>0.13.11</version> <version>0.14.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.eatthepath</groupId> <groupId>com.eatthepath</groupId>

View File

@ -37,7 +37,7 @@ import javax.annotation.Nullable;
import java.io.IOException; import java.io.IOException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Date; import java.time.Instant;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@ -92,7 +92,7 @@ public class APNSender implements Managed {
ListenableFuture<ApnResult> future = apnsClient.send(message.getApnId(), topic, ListenableFuture<ApnResult> future = apnsClient.send(message.getApnId(), topic,
message.getMessage(), message.getMessage(),
new Date(message.getExpirationTime())); Instant.ofEpochMilli(message.getExpirationTime()));
Futures.addCallback(future, new FutureCallback<ApnResult>() { Futures.addCallback(future, new FutureCallback<ApnResult>() {
@Override @Override

View File

@ -13,7 +13,6 @@ import com.eatthepath.pushy.apns.util.SimpleApnsPushNotification;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture; import com.google.common.util.concurrent.SettableFuture;
import io.netty.util.concurrent.GenericFutureListener;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.util.Constants; import org.whispersystems.textsecuregcm.util.Constants;
@ -22,9 +21,9 @@ import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Date; import java.time.Instant;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException; import java.util.function.BiConsumer;
import static com.codahale.metrics.MetricRegistry.name; import static com.codahale.metrics.MetricRegistry.name;
@ -55,11 +54,11 @@ public class RetryingApnsClient {
this.apnsClient = apnsClient; this.apnsClient = apnsClient;
} }
ListenableFuture<ApnResult> send(final String apnId, final String topic, final String payload, final Date expiration) { ListenableFuture<ApnResult> send(final String apnId, final String topic, final String payload, final Instant expiration) {
SettableFuture<ApnResult> result = SettableFuture.create(); SettableFuture<ApnResult> result = SettableFuture.create();
SimpleApnsPushNotification notification = new SimpleApnsPushNotification(apnId, topic, payload, expiration, DeliveryPriority.IMMEDIATE); SimpleApnsPushNotification notification = new SimpleApnsPushNotification(apnId, topic, payload, expiration, DeliveryPriority.IMMEDIATE);
apnsClient.sendNotification(notification).addListener(new ResponseHandler(result)); apnsClient.sendNotification(notification).whenComplete(new ResponseHandler(result));
return result; return result;
} }
@ -68,7 +67,7 @@ public class RetryingApnsClient {
apnsClient.close(); apnsClient.close();
} }
private static final class ResponseHandler implements GenericFutureListener<io.netty.util.concurrent.Future<PushNotificationResponse<SimpleApnsPushNotification>>> { private static final class ResponseHandler implements BiConsumer<PushNotificationResponse<SimpleApnsPushNotification>, Throwable> {
private final SettableFuture<ApnResult> future; private final SettableFuture<ApnResult> future;
@ -77,27 +76,20 @@ public class RetryingApnsClient {
} }
@Override @Override
public void operationComplete(io.netty.util.concurrent.Future<PushNotificationResponse<SimpleApnsPushNotification>> result) { public void accept(final PushNotificationResponse<SimpleApnsPushNotification> response, final Throwable cause) {
try { if (response != null) {
PushNotificationResponse<SimpleApnsPushNotification> response = result.get();
if (response.isAccepted()) { if (response.isAccepted()) {
future.set(new ApnResult(ApnResult.Status.SUCCESS, null)); future.set(new ApnResult(ApnResult.Status.SUCCESS, null));
} else if ("Unregistered".equals(response.getRejectionReason()) || } else if ("Unregistered".equals(response.getRejectionReason()) ||
"BadDeviceToken".equals(response.getRejectionReason())) "BadDeviceToken".equals(response.getRejectionReason())) {
{
future.set(new ApnResult(ApnResult.Status.NO_SUCH_USER, response.getRejectionReason())); future.set(new ApnResult(ApnResult.Status.NO_SUCH_USER, response.getRejectionReason()));
} else { } else {
logger.warn("Got APN failure: " + response.getRejectionReason()); logger.warn("Got APN failure: " + response.getRejectionReason());
future.set(new ApnResult(ApnResult.Status.GENERIC_FAILURE, response.getRejectionReason())); future.set(new ApnResult(ApnResult.Status.GENERIC_FAILURE, response.getRejectionReason()));
} }
} else {
} catch (InterruptedException e) { logger.warn("Execution exception", cause);
logger.warn("Interrupted exception", e); future.setException(cause);
future.setException(e);
} catch (ExecutionException e) {
logger.warn("Execution exception", e);
future.setException(e.getCause());
} }
} }
} }

View File

@ -21,14 +21,13 @@ import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.Device; import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.tests.util.SynchronousExecutorService; import org.whispersystems.textsecuregcm.tests.util.SynchronousExecutorService;
import java.util.Date; import java.time.Instant;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import io.netty.util.concurrent.DefaultEventExecutor; import io.netty.util.concurrent.DefaultEventExecutor;
import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.EventExecutor;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
@ -43,8 +42,6 @@ public class APNSenderTest {
private final Device destinationDevice = mock(Device.class); private final Device destinationDevice = mock(Device.class);
private final ApnFallbackManager fallbackManager = mock(ApnFallbackManager.class); private final ApnFallbackManager fallbackManager = mock(ApnFallbackManager.class);
private final DefaultEventExecutor executor = new DefaultEventExecutor();
@Before @Before
public void setup() { public void setup() {
when(destinationAccount.getDevice(1)).thenReturn(Optional.of(destinationDevice)); when(destinationAccount.getDevice(1)).thenReturn(Optional.of(destinationDevice));
@ -60,7 +57,7 @@ public class APNSenderTest {
when(response.isAccepted()).thenReturn(true); when(response.isAccepted()).thenReturn(true);
when(apnsClient.sendNotification(any(SimpleApnsPushNotification.class))) when(apnsClient.sendNotification(any(SimpleApnsPushNotification.class)))
.thenAnswer((Answer) invocationOnMock -> new MockPushNotificationFuture<>(executor, invocationOnMock.getArgument(0), response)); .thenAnswer((Answer) invocationOnMock -> new MockPushNotificationFuture<>(invocationOnMock.getArgument(0), response));
RetryingApnsClient retryingApnsClient = new RetryingApnsClient(apnsClient); RetryingApnsClient retryingApnsClient = new RetryingApnsClient(apnsClient);
ApnMessage message = new ApnMessage(DESTINATION_APN_ID, DESTINATION_NUMBER, 1, true, Optional.empty()); ApnMessage message = new ApnMessage(DESTINATION_APN_ID, DESTINATION_NUMBER, 1, true, Optional.empty());
@ -74,7 +71,7 @@ public class APNSenderTest {
verify(apnsClient, times(1)).sendNotification(notification.capture()); verify(apnsClient, times(1)).sendNotification(notification.capture());
assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_APN_ID); assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_APN_ID);
assertThat(notification.getValue().getExpiration()).isEqualTo(new Date(ApnMessage.MAX_EXPIRATION)); assertThat(notification.getValue().getExpiration()).isEqualTo(Instant.ofEpochMilli(ApnMessage.MAX_EXPIRATION));
assertThat(notification.getValue().getPayload()).isEqualTo(ApnMessage.APN_NOTIFICATION_PAYLOAD); assertThat(notification.getValue().getPayload()).isEqualTo(ApnMessage.APN_NOTIFICATION_PAYLOAD);
assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE); assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE);
assertThat(notification.getValue().getTopic()).isEqualTo("foo.voip"); assertThat(notification.getValue().getTopic()).isEqualTo("foo.voip");
@ -94,7 +91,7 @@ public class APNSenderTest {
when(response.isAccepted()).thenReturn(true); when(response.isAccepted()).thenReturn(true);
when(apnsClient.sendNotification(any(SimpleApnsPushNotification.class))) when(apnsClient.sendNotification(any(SimpleApnsPushNotification.class)))
.thenAnswer((Answer) invocationOnMock -> new MockPushNotificationFuture<>(executor, invocationOnMock.getArgument(0), response)); .thenAnswer((Answer) invocationOnMock -> new MockPushNotificationFuture<>(invocationOnMock.getArgument(0), response));
RetryingApnsClient retryingApnsClient = new RetryingApnsClient(apnsClient); RetryingApnsClient retryingApnsClient = new RetryingApnsClient(apnsClient);
ApnMessage message = new ApnMessage(DESTINATION_APN_ID, DESTINATION_NUMBER, 1, false, Optional.empty()); ApnMessage message = new ApnMessage(DESTINATION_APN_ID, DESTINATION_NUMBER, 1, false, Optional.empty());
@ -108,7 +105,7 @@ public class APNSenderTest {
verify(apnsClient, times(1)).sendNotification(notification.capture()); verify(apnsClient, times(1)).sendNotification(notification.capture());
assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_APN_ID); assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_APN_ID);
assertThat(notification.getValue().getExpiration()).isEqualTo(new Date(ApnMessage.MAX_EXPIRATION)); assertThat(notification.getValue().getExpiration()).isEqualTo(Instant.ofEpochMilli(ApnMessage.MAX_EXPIRATION));
assertThat(notification.getValue().getPayload()).isEqualTo(ApnMessage.APN_NOTIFICATION_PAYLOAD); assertThat(notification.getValue().getPayload()).isEqualTo(ApnMessage.APN_NOTIFICATION_PAYLOAD);
assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE); assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE);
assertThat(notification.getValue().getTopic()).isEqualTo("foo"); assertThat(notification.getValue().getTopic()).isEqualTo("foo");
@ -129,7 +126,7 @@ public class APNSenderTest {
when(response.getRejectionReason()).thenReturn("Unregistered"); when(response.getRejectionReason()).thenReturn("Unregistered");
when(apnsClient.sendNotification(any(SimpleApnsPushNotification.class))) when(apnsClient.sendNotification(any(SimpleApnsPushNotification.class)))
.thenAnswer((Answer) invocationOnMock -> new MockPushNotificationFuture<>(executor, invocationOnMock.getArgument(0), response)); .thenAnswer((Answer) invocationOnMock -> new MockPushNotificationFuture<>(invocationOnMock.getArgument(0), response));
RetryingApnsClient retryingApnsClient = new RetryingApnsClient(apnsClient); RetryingApnsClient retryingApnsClient = new RetryingApnsClient(apnsClient);
@ -149,7 +146,7 @@ public class APNSenderTest {
verify(apnsClient, times(1)).sendNotification(notification.capture()); verify(apnsClient, times(1)).sendNotification(notification.capture());
assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_APN_ID); assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_APN_ID);
assertThat(notification.getValue().getExpiration()).isEqualTo(new Date(ApnMessage.MAX_EXPIRATION)); assertThat(notification.getValue().getExpiration()).isEqualTo(Instant.ofEpochMilli(ApnMessage.MAX_EXPIRATION));
assertThat(notification.getValue().getPayload()).isEqualTo(ApnMessage.APN_NOTIFICATION_PAYLOAD); assertThat(notification.getValue().getPayload()).isEqualTo(ApnMessage.APN_NOTIFICATION_PAYLOAD);
assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE); assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE);
@ -233,7 +230,7 @@ public class APNSenderTest {
when(response.getRejectionReason()).thenReturn("Unregistered"); when(response.getRejectionReason()).thenReturn("Unregistered");
when(apnsClient.sendNotification(any(SimpleApnsPushNotification.class))) when(apnsClient.sendNotification(any(SimpleApnsPushNotification.class)))
.thenAnswer((Answer) invocationOnMock -> new MockPushNotificationFuture<>(executor, invocationOnMock.getArgument(0), response)); .thenAnswer((Answer) invocationOnMock -> new MockPushNotificationFuture<>(invocationOnMock.getArgument(0), response));
RetryingApnsClient retryingApnsClient = new RetryingApnsClient(apnsClient); RetryingApnsClient retryingApnsClient = new RetryingApnsClient(apnsClient);
ApnMessage message = new ApnMessage(DESTINATION_APN_ID, DESTINATION_NUMBER, 1, true, Optional.empty()); ApnMessage message = new ApnMessage(DESTINATION_APN_ID, DESTINATION_NUMBER, 1, true, Optional.empty());
@ -252,7 +249,7 @@ public class APNSenderTest {
verify(apnsClient, times(1)).sendNotification(notification.capture()); verify(apnsClient, times(1)).sendNotification(notification.capture());
assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_APN_ID); assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_APN_ID);
assertThat(notification.getValue().getExpiration()).isEqualTo(new Date(ApnMessage.MAX_EXPIRATION)); assertThat(notification.getValue().getExpiration()).isEqualTo(Instant.ofEpochMilli(ApnMessage.MAX_EXPIRATION));
assertThat(notification.getValue().getPayload()).isEqualTo(ApnMessage.APN_NOTIFICATION_PAYLOAD); assertThat(notification.getValue().getPayload()).isEqualTo(ApnMessage.APN_NOTIFICATION_PAYLOAD);
assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE); assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE);
@ -328,7 +325,7 @@ public class APNSenderTest {
when(response.getRejectionReason()).thenReturn("BadTopic"); when(response.getRejectionReason()).thenReturn("BadTopic");
when(apnsClient.sendNotification(any(SimpleApnsPushNotification.class))) when(apnsClient.sendNotification(any(SimpleApnsPushNotification.class)))
.thenAnswer((Answer) invocationOnMock -> new MockPushNotificationFuture<>(executor, invocationOnMock.getArgument(0), response)); .thenAnswer((Answer) invocationOnMock -> new MockPushNotificationFuture<>(invocationOnMock.getArgument(0), response));
RetryingApnsClient retryingApnsClient = new RetryingApnsClient(apnsClient); RetryingApnsClient retryingApnsClient = new RetryingApnsClient(apnsClient);
ApnMessage message = new ApnMessage(DESTINATION_APN_ID, DESTINATION_NUMBER, 1, true, Optional.empty()); ApnMessage message = new ApnMessage(DESTINATION_APN_ID, DESTINATION_NUMBER, 1, true, Optional.empty());
@ -342,7 +339,7 @@ public class APNSenderTest {
verify(apnsClient, times(1)).sendNotification(notification.capture()); verify(apnsClient, times(1)).sendNotification(notification.capture());
assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_APN_ID); assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_APN_ID);
assertThat(notification.getValue().getExpiration()).isEqualTo(new Date(ApnMessage.MAX_EXPIRATION)); assertThat(notification.getValue().getExpiration()).isEqualTo(Instant.ofEpochMilli(ApnMessage.MAX_EXPIRATION));
assertThat(notification.getValue().getPayload()).isEqualTo(ApnMessage.APN_NOTIFICATION_PAYLOAD); assertThat(notification.getValue().getPayload()).isEqualTo(ApnMessage.APN_NOTIFICATION_PAYLOAD);
assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE); assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE);
@ -361,7 +358,7 @@ public class APNSenderTest {
when(response.isAccepted()).thenReturn(true); when(response.isAccepted()).thenReturn(true);
when(apnsClient.sendNotification(any(SimpleApnsPushNotification.class))) when(apnsClient.sendNotification(any(SimpleApnsPushNotification.class)))
.thenAnswer((Answer) invocationOnMock -> new MockPushNotificationFuture<>(executor, invocationOnMock.getArgument(0), new Exception("lost connection"))); .thenAnswer((Answer) invocationOnMock -> new MockPushNotificationFuture<>(invocationOnMock.getArgument(0), new Exception("lost connection")));
RetryingApnsClient retryingApnsClient = new RetryingApnsClient(apnsClient); RetryingApnsClient retryingApnsClient = new RetryingApnsClient(apnsClient);
ApnMessage message = new ApnMessage(DESTINATION_APN_ID, DESTINATION_NUMBER, 1, true, Optional.empty()); ApnMessage message = new ApnMessage(DESTINATION_APN_ID, DESTINATION_NUMBER, 1, true, Optional.empty());
@ -383,7 +380,7 @@ public class APNSenderTest {
verify(apnsClient, times(1)).sendNotification(notification.capture()); verify(apnsClient, times(1)).sendNotification(notification.capture());
assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_APN_ID); assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_APN_ID);
assertThat(notification.getValue().getExpiration()).isEqualTo(new Date(ApnMessage.MAX_EXPIRATION)); assertThat(notification.getValue().getExpiration()).isEqualTo(Instant.ofEpochMilli(ApnMessage.MAX_EXPIRATION));
assertThat(notification.getValue().getPayload()).isEqualTo(ApnMessage.APN_NOTIFICATION_PAYLOAD); assertThat(notification.getValue().getPayload()).isEqualTo(ApnMessage.APN_NOTIFICATION_PAYLOAD);
assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE); assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE);
@ -392,31 +389,16 @@ public class APNSenderTest {
verifyNoMoreInteractions(fallbackManager); verifyNoMoreInteractions(fallbackManager);
} }
private static class MockPushNotificationFuture <P extends ApnsPushNotification, V> extends DefaultPromise<V> implements PushNotificationFuture<P, V> { private static class MockPushNotificationFuture <P extends ApnsPushNotification, V> extends PushNotificationFuture<P, V> {
private final P pushNotification; MockPushNotificationFuture(final P pushNotification, final V response) {
super(pushNotification);
MockPushNotificationFuture(final EventExecutor eventExecutor, final P pushNotification) { complete(response);
super(eventExecutor);
this.pushNotification = pushNotification;
} }
MockPushNotificationFuture(final EventExecutor eventExecutor, final P pushNotification, final V response) { MockPushNotificationFuture(final P pushNotification, final Exception exception) {
super(eventExecutor); super(pushNotification);
this.pushNotification = pushNotification; completeExceptionally(exception);
setSuccess(response);
}
MockPushNotificationFuture(final EventExecutor eventExecutor, final P pushNotification, final Exception exception) {
super(eventExecutor);
this.pushNotification = pushNotification;
setFailure(exception);
}
@Override
public P getPushNotification() {
return pushNotification;
} }
} }