Include "token invalidation timestamp" in push notification responses

This commit is contained in:
Jon Chambers
2024-06-21 16:56:57 -04:00
committed by Jon Chambers
parent d743454d07
commit 1cf174a613
7 changed files with 36 additions and 29 deletions

View File

@@ -23,6 +23,7 @@ import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import org.whispersystems.textsecuregcm.configuration.ApnConfiguration;
@@ -156,20 +157,21 @@ public class APNSender implements Managed, PushNotificationSender {
})
.thenApplyAsync(response -> {
final boolean accepted;
final String rejectionReason;
final Optional<String> rejectionReason;
final boolean unregistered;
if (response.isAccepted()) {
accepted = true;
rejectionReason = null;
rejectionReason = Optional.empty();
unregistered = false;
} else {
accepted = false;
rejectionReason = response.getRejectionReason().orElse("unknown");
unregistered = ("Unregistered".equals(rejectionReason) || "BadDeviceToken".equals(rejectionReason));
rejectionReason = response.getRejectionReason();
unregistered = response.getRejectionReason().map(reason -> "Unregistered".equals(reason) || "BadDeviceToken".equals(reason))
.orElse(false);
}
return new SendPushNotificationResult(accepted, rejectionReason, unregistered);
return new SendPushNotificationResult(accepted, rejectionReason, unregistered, response.getTokenInvalidationTimestamp());
}, executor);
}

View File

@@ -23,6 +23,7 @@ import io.micrometer.core.instrument.Timer;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;
@@ -96,7 +97,7 @@ public class FcmSender implements PushNotificationSender {
return GoogleApiUtil.toCompletableFuture(firebaseMessagingClient.sendAsync(builder.build()), executor)
.whenComplete((ignored, throwable) -> sample.stop(SEND_NOTIFICATION_TIMER))
.thenApply(ignored -> new SendPushNotificationResult(true, null, false))
.thenApply(ignored -> new SendPushNotificationResult(true, Optional.empty(), false, Optional.empty()))
.exceptionally(throwable -> {
if (ExceptionUtils.unwrap(throwable) instanceof final FirebaseMessagingException firebaseMessagingException) {
final String errorCode;
@@ -111,7 +112,7 @@ public class FcmSender implements PushNotificationSender {
final boolean unregistered =
firebaseMessagingException.getMessagingErrorCode() == MessagingErrorCode.UNREGISTERED;
return new SendPushNotificationResult(false, errorCode, unregistered);
return new SendPushNotificationResult(false, Optional.of(errorCode), unregistered, Optional.empty());
} else {
throw ExceptionUtils.wrap(throwable);
}

View File

@@ -123,8 +123,8 @@ public class PushNotificationManager {
"accepted", String.valueOf(result.accepted()),
"unregistered", String.valueOf(result.unregistered()));
if (StringUtils.isNotBlank(result.errorCode())) {
tags = tags.and("errorCode", result.errorCode());
if (result.errorCode().isPresent()) {
tags = tags.and("errorCode", result.errorCode().get());
}
Metrics.counter(SENT_NOTIFICATION_COUNTER_NAME, tags).increment();

View File

@@ -5,7 +5,11 @@
package org.whispersystems.textsecuregcm.push;
import javax.annotation.Nullable;
import java.time.Instant;
import java.util.Optional;
public record SendPushNotificationResult(boolean accepted, @Nullable String errorCode, boolean unregistered) {
public record SendPushNotificationResult(boolean accepted,
Optional<String> errorCode,
boolean unregistered,
Optional<Instant> unregisteredTimestamp) {
}