public CompletableFuture<Void> commitBackupId(final Account account,
      final BackupAuthCredentialRequest backupAuthCredentialRequest) {
    if (configuredBackupLevel(account).isEmpty()) {
      throw Status.PERMISSION_DENIED.withDescription("Backups not allowed on account").asRuntimeException();
    }

    byte[] serializedRequest = backupAuthCredentialRequest.serialize();
    byte[] existingRequest = account.getBackupCredentialRequest();
    if (existingRequest != null && MessageDigest.isEqual(serializedRequest, existingRequest)) {
      // No need to update or enforce rate limits, this is the credential that the user has already
      // committed to.
      return CompletableFuture.completedFuture(null);
    }

    return rateLimiters.forDescriptor(RateLimiters.For.SET_BACKUP_ID)
        .validateAsync(account.getUuid())
        .thenCompose(ignored -> this.accountsManager
            .updateAsync(account, acc -> acc.setBackupCredentialRequest(serializedRequest))
            .thenRun(Util.NOOP))
        .toCompletableFuture();
  }
@Test
  void testRateLimits() {
    final AccountsManager accountsManager = mock(AccountsManager.class);
    final BackupAuthManager authManager = create(BackupLevel.MESSAGES, true);

    final BackupAuthCredentialRequest credentialRequest = backupAuthTestUtil.getRequest(backupKey, aci);

    final Account account = mock(Account.class);
    when(account.getUuid()).thenReturn(aci);
    when(accountsManager.updateAsync(any(), any())).thenReturn(CompletableFuture.completedFuture(account));

    // Should be rate limited
    final RateLimitExceededException ex = CompletableFutureTestUtil.assertFailsWithCause(
        RateLimitExceededException.class,
        authManager.commitBackupId(account, credentialRequest));

    // If we don't change the request, shouldn't be rate limited
    when(account.getBackupCredentialRequest()).thenReturn(credentialRequest.serialize());
    assertDoesNotThrow(() -> authManager.commitBackupId(account, credentialRequest).join());
  }