Delete any leftover usernames in the accounts db

The account username field should not currently be populated
This commit is contained in:
Ravi Khadiwala
2022-08-09 16:51:53 -05:00
committed by ravi-signal
parent 4d78437fe4
commit a44c18e9b7
4 changed files with 101 additions and 0 deletions

View File

@@ -185,6 +185,7 @@ import org.whispersystems.textsecuregcm.storage.MessagesCache;
import org.whispersystems.textsecuregcm.storage.MessagesDynamoDb;
import org.whispersystems.textsecuregcm.storage.MessagesManager;
import org.whispersystems.textsecuregcm.storage.NonNormalizedAccountCrawlerListener;
import org.whispersystems.textsecuregcm.storage.UsernameCleaner;
import org.whispersystems.textsecuregcm.storage.PhoneNumberIdentifiers;
import org.whispersystems.textsecuregcm.storage.Profiles;
import org.whispersystems.textsecuregcm.storage.ProfilesManager;
@@ -531,6 +532,17 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
config.getAccountDatabaseCrawlerConfiguration().getChunkIntervalMs()
);
AccountDatabaseCrawlerCache usernameCleanerAccountDatabaseCrawlerCache =
new AccountDatabaseCrawlerCache(cacheCluster, AccountDatabaseCrawlerCache.USERNAME_CLEANER_PREFIX);
AccountDatabaseCrawler usernameCleanerAccountDatabaseCrawler = new AccountDatabaseCrawler("username cleaner crawler",
accountsManager,
usernameCleanerAccountDatabaseCrawlerCache,
List.of(new UsernameCleaner(accountsManager)),
config.getAccountDatabaseCrawlerConfiguration().getChunkSize(),
config.getAccountDatabaseCrawlerConfiguration().getChunkIntervalMs()
);
// TODO listeners must be ordered so that ones that directly update accounts come last, so that read-only ones are not working with stale data
final List<AccountDatabaseCrawlerListener> accountDatabaseCrawlerListeners = List.of(
new NonNormalizedAccountCrawlerListener(accountsManager, metricsCluster),
@@ -560,6 +572,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
environment.lifecycle().manage(accountDatabaseCrawler);
environment.lifecycle().manage(directoryReconciliationAccountDatabaseCrawler);
environment.lifecycle().manage(accountCleanerAccountDatabaseCrawler);
environment.lifecycle().manage(usernameCleanerAccountDatabaseCrawler);
environment.lifecycle().manage(deletedAccountsTableCrawler);
environment.lifecycle().manage(messagesCache);
environment.lifecycle().manage(messagePersister);

View File

@@ -19,6 +19,7 @@ public class AccountDatabaseCrawlerCache {
public static final String GENERAL_PURPOSE_PREFIX = "";
public static final String DIRECTORY_RECONCILER_PREFIX = "directory-reconciler";
public static final String ACCOUNT_CLEANER_PREFIX = "account-cleaner";
public static final String USERNAME_CLEANER_PREFIX = "username-cleaner";
private static final String ACTIVE_WORKER_KEY = "account_database_crawler_cache_active_worker";
private static final String LAST_UUID_KEY = "account_database_crawler_cache_last_uuid";

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2022 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.textsecuregcm.storage;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Tags;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name;
public class UsernameCleaner extends AccountDatabaseCrawlerListener {
private static final String DELETED_USERNAME_COUNTER = name(UsernameCleaner.class, "deletedUsernames");
private static final Logger logger = LoggerFactory.getLogger(UsernameCleaner.class);
private final AccountsManager accountsManager;
public UsernameCleaner(AccountsManager accountsManager) {
this.accountsManager = accountsManager;
}
@Override
public void onCrawlStart() {
}
@Override
protected void onCrawlChunk(final Optional<UUID> fromUuid, final List<Account> chunkAccounts) {
for (Account account : chunkAccounts) {
if (account.getUsername().isPresent()) {
logger.info("Deleting username present for account {}", account.getUuid());
try {
this.accountsManager.clearUsername(account);
Metrics.counter(DELETED_USERNAME_COUNTER, Tags.of("outcome", "success")).increment();
} catch (Exception e) {
logger.warn("Failed to clear username on account {}", account.getUuid(), e);
Metrics.counter(DELETED_USERNAME_COUNTER, Tags.of("outcome", "error")).increment();
}
}
}
}
@Override
public void onCrawlEnd(final Optional<UUID> fromUuid) {
logger.info("Username cleaner crawl completed");
}
}