diff --git a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index 968ab382c..58bbc9d55 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -74,6 +74,7 @@ import org.whispersystems.textsecuregcm.util.Constants; import org.whispersystems.textsecuregcm.util.UrlSigner; import org.whispersystems.textsecuregcm.websocket.WebsocketControllerFactory; import org.whispersystems.textsecuregcm.workers.DirectoryCommand; +import org.whispersystems.textsecuregcm.workers.VacuumCommand; import javax.servlet.DispatcherType; import javax.servlet.FilterRegistration; @@ -101,6 +102,7 @@ public class WhisperServerService extends Application bootstrap) { bootstrap.addCommand(new DirectoryCommand()); + bootstrap.addCommand(new VacuumCommand()); bootstrap.addBundle(new MigrationsBundle() { @Override public DataSourceFactory getDataSourceFactory(WhisperServerConfiguration configuration) { diff --git a/src/main/java/org/whispersystems/textsecuregcm/storage/Accounts.java b/src/main/java/org/whispersystems/textsecuregcm/storage/Accounts.java index 9eccb834d..085502419 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/storage/Accounts.java +++ b/src/main/java/org/whispersystems/textsecuregcm/storage/Accounts.java @@ -85,6 +85,9 @@ public abstract class Accounts { return insertStep(account); } + @SqlUpdate("VACUUM accounts") + public abstract void vacuum(); + public static class AccountMapper implements ResultSetMapper { @Override public Account map(int i, ResultSet resultSet, StatementContext statementContext) diff --git a/src/main/java/org/whispersystems/textsecuregcm/storage/Keys.java b/src/main/java/org/whispersystems/textsecuregcm/storage/Keys.java index e226c34ae..50a980f26 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/storage/Keys.java +++ b/src/main/java/org/whispersystems/textsecuregcm/storage/Keys.java @@ -31,8 +31,6 @@ import org.skife.jdbi.v2.sqlobject.Transaction; import org.skife.jdbi.v2.sqlobject.customizers.Mapper; import org.skife.jdbi.v2.tweak.ResultSetMapper; import org.whispersystems.textsecuregcm.entities.PreKeyBase; -import org.whispersystems.textsecuregcm.entities.PreKeyV1; -import org.whispersystems.textsecuregcm.entities.PreKeyV2; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; @@ -114,6 +112,9 @@ public abstract class Keys { else return Optional.absent(); } + @SqlUpdate("VACUUM keys") + public abstract void vacuum(); + @BindingAnnotation(PreKeyBinder.PreKeyBinderFactory.class) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER}) diff --git a/src/main/java/org/whispersystems/textsecuregcm/storage/PendingAccounts.java b/src/main/java/org/whispersystems/textsecuregcm/storage/PendingAccounts.java index bd1a374e5..7b943a190 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/storage/PendingAccounts.java +++ b/src/main/java/org/whispersystems/textsecuregcm/storage/PendingAccounts.java @@ -31,4 +31,7 @@ public interface PendingAccounts { @SqlUpdate("DELETE FROM pending_accounts WHERE number = :number") void remove(@Bind("number") String number); + + @SqlUpdate("VACUUM pending_accounts") + public void vacuum(); } diff --git a/src/main/java/org/whispersystems/textsecuregcm/workers/VacuumCommand.java b/src/main/java/org/whispersystems/textsecuregcm/workers/VacuumCommand.java new file mode 100644 index 000000000..ecfe4b8e6 --- /dev/null +++ b/src/main/java/org/whispersystems/textsecuregcm/workers/VacuumCommand.java @@ -0,0 +1,59 @@ +package org.whispersystems.textsecuregcm.workers; + +import net.sourceforge.argparse4j.inf.Namespace; +import org.skife.jdbi.v2.DBI; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.whispersystems.textsecuregcm.WhisperServerConfiguration; +import org.whispersystems.textsecuregcm.storage.Accounts; +import org.whispersystems.textsecuregcm.storage.Keys; +import org.whispersystems.textsecuregcm.storage.PendingAccounts; + +import io.dropwizard.cli.ConfiguredCommand; +import io.dropwizard.db.DataSourceFactory; +import io.dropwizard.jdbi.ImmutableListContainerFactory; +import io.dropwizard.jdbi.ImmutableSetContainerFactory; +import io.dropwizard.jdbi.OptionalContainerFactory; +import io.dropwizard.jdbi.args.OptionalArgumentFactory; +import io.dropwizard.setup.Bootstrap; + + +public class VacuumCommand extends ConfiguredCommand { + + private final Logger logger = LoggerFactory.getLogger(DirectoryCommand.class); + + public VacuumCommand() { + super("vacuum", "Vacuum Postgres Tables"); + } + + @Override + protected void run(Bootstrap bootstrap, + Namespace namespace, + WhisperServerConfiguration config) + throws Exception + { + DataSourceFactory dbConfig = config.getDataSourceFactory(); + DBI dbi = new DBI(dbConfig.getUrl(), dbConfig.getUser(), dbConfig.getPassword()); + + dbi.registerArgumentFactory(new OptionalArgumentFactory(dbConfig.getDriverClass())); + dbi.registerContainerFactory(new ImmutableListContainerFactory()); + dbi.registerContainerFactory(new ImmutableSetContainerFactory()); + dbi.registerContainerFactory(new OptionalContainerFactory()); + + Accounts accounts = dbi.onDemand(Accounts.class ); + Keys keys = dbi.onDemand(Keys.class ); + PendingAccounts pendingAccounts = dbi.onDemand(PendingAccounts.class); + + logger.warn("Vacuuming accounts..."); + accounts.vacuum(); + + logger.warn("Vacuuming pending_accounts..."); + pendingAccounts.vacuum(); + + logger.warn("Vacuuming keys..."); + keys.vacuum(); + + Thread.sleep(3000); + System.exit(0); + } +}