Port /v1/archives/backupid/limits to gRPC

This commit is contained in:
Ameya Lokare authored and Chris Eager committed 2026-09-14 10:34:51 -04:00
1 parent ce3378354d
commit 5f124cc812
3 files changed
+41

No files matched your search

@@ -16,6 +16,7 @@ import java.util.Optional;
import java.util.stream.Collectors;
import org.signal.chat.backup.GetBackupAuthCredentialsRequest;
import org.signal.chat.backup.GetBackupAuthCredentialsResponse;
import org.signal.chat.backup.GetBackupIdLimitsResponse;
import org.signal.chat.backup.RedeemReceiptRequest;
import org.signal.chat.backup.RedeemReceiptResponse;
import org.signal.chat.backup.SetBackupIdRequest;
@@ -138,6 +139,16 @@ public class BackupsGrpcService extends SimpleBackupsGrpc.BackupsImplBase {
}
}
@Override
public GetBackupIdLimitsResponse getBackupIdLimits(final Empty request) {
final Account account = authenticatedAccount();
final BackupAuthManager.BackupIdRotationLimit limit = backupAuthManager.checkBackupIdRotationLimit(account);
return GetBackupIdLimitsResponse.newBuilder()
.setHasPermitsRemaining(limit.hasPermitsRemaining())
.setRetryAfterSeconds(limit.nextPermitAvailable().getSeconds())
.build();
}
@Override
public Throwable mapException(final Throwable throwable) {
return switch (throwable) {
@@ -59,6 +59,9 @@ service Backups {
// Clients must validate the receipt level on the credential matches a known
// receipt level before using it.
rpc GetBackupAuthCredentials(GetBackupAuthCredentialsRequest) returns (GetBackupAuthCredentialsResponse) {}
// Retrieve backup ID rotation limits
rpc GetBackupIdLimits(google.protobuf.Empty) returns (GetBackupIdLimitsResponse) {}
}
message SetBackupIdRequest {
@@ -125,6 +128,13 @@ message GetBackupAuthCredentialsResponse {
Credentials credentials = 1;
}
message GetBackupIdLimitsResponse {
// If true, a call to SetBackupId may succeed without waiting
bool hasPermitsRemaining = 1;
// How long to wait before a permit becomes available, in seconds
uint64 retryAfterSeconds = 2;
}
// Service for backup operations with anonymous credentials
//
// This service never requires account authentication. It instead requires a
@@ -14,6 +14,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.protobuf.ByteString;
import com.google.protobuf.Empty;
import io.grpc.Status;
import java.time.Clock;
import java.time.Duration;
@@ -35,6 +36,7 @@ import org.mockito.Mock;
import org.signal.chat.backup.BackupsGrpc;
import org.signal.chat.backup.GetBackupAuthCredentialsRequest;
import org.signal.chat.backup.GetBackupAuthCredentialsResponse;
import org.signal.chat.backup.GetBackupIdLimitsResponse;
import org.signal.chat.backup.RedeemReceiptRequest;
import org.signal.chat.backup.RedeemReceiptResponse;
import org.signal.chat.backup.SetBackupIdRequest;
@@ -263,4 +265,22 @@ class BackupsGrpcServiceTest extends SimpleBaseGrpcTest<BackupsGrpcService, Back
() -> authenticatedServiceStub().getBackupAuthCredentials(builder.build()));
}
@ParameterizedTest
@CsvSource({
"true, 0",
"false, 3600"
})
void getBackupIdLimits(final boolean hasPermitsRemaining, final long retryAfterSeconds) {
when(backupAuthManager.checkBackupIdRotationLimit(account))
.thenReturn(new BackupAuthManager.BackupIdRotationLimit(
hasPermitsRemaining, Duration.ofSeconds(retryAfterSeconds)));
final GetBackupIdLimitsResponse response =
authenticatedServiceStub().getBackupIdLimits(Empty.getDefaultInstance());
assertThat(response.getHasPermitsRemaining()).isEqualTo(hasPermitsRemaining);
assertThat(response.getRetryAfterSeconds()).isEqualTo(retryAfterSeconds);
verify(backupAuthManager).checkBackupIdRotationLimit(account);
}
}