mirror of
https://github.com/google/nomulus
synced 2026-08-08 08:16:10 +00:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
807ddf46b9 | ||
|
|
ff8f86090d | ||
|
|
5822f53e14 | ||
|
|
d04b3299aa | ||
|
|
ceade7f954 | ||
|
|
1fcf63facd | ||
|
|
f87e7eb6e6 |
@@ -110,7 +110,7 @@ public final class AsyncTaskEnqueuer {
|
||||
.method(Method.POST)
|
||||
.header("Host", backendHostname)
|
||||
.countdownMillis(etaDuration.getMillis())
|
||||
.param(PARAM_RESOURCE_KEY, entityKey.getOfyKey().getString())
|
||||
.param(PARAM_RESOURCE_KEY, entityKey.stringify())
|
||||
.param(PARAM_REQUESTED_TIME, now.toString());
|
||||
if (whenToResave.size() > 1) {
|
||||
task.param(PARAM_RESAVE_TIMES, Joiner.on(',').join(whenToResave.tailSet(firstResave, false)));
|
||||
@@ -131,7 +131,7 @@ public final class AsyncTaskEnqueuer {
|
||||
TaskOptions task =
|
||||
TaskOptions.Builder.withMethod(Method.PULL)
|
||||
.countdownMillis(asyncDeleteDelay.getMillis())
|
||||
.param(PARAM_RESOURCE_KEY, resourceToDelete.createVKey().getOfyKey().getString())
|
||||
.param(PARAM_RESOURCE_KEY, resourceToDelete.createVKey().stringify())
|
||||
.param(PARAM_REQUESTING_CLIENT_ID, requestingRegistrarId)
|
||||
.param(PARAM_SERVER_TRANSACTION_ID, trid.getServerTransactionId())
|
||||
.param(PARAM_IS_SUPERUSER, Boolean.toString(isSuperuser))
|
||||
@@ -148,7 +148,7 @@ public final class AsyncTaskEnqueuer {
|
||||
addTaskToQueueWithRetry(
|
||||
asyncDnsRefreshPullQueue,
|
||||
TaskOptions.Builder.withMethod(Method.PULL)
|
||||
.param(PARAM_HOST_KEY, hostKey.getOfyKey().getString())
|
||||
.param(PARAM_HOST_KEY, hostKey.stringify())
|
||||
.param(PARAM_REQUESTED_TIME, now.toString()));
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import google.registry.config.RegistryConfig.ConfigModule;
|
||||
import google.registry.persistence.PersistenceModule;
|
||||
import google.registry.persistence.PersistenceModule.BeamBulkQueryJpaTm;
|
||||
import google.registry.persistence.PersistenceModule.BeamJpaTm;
|
||||
import google.registry.persistence.PersistenceModule.BeamReadOnlyReplicaJpaTm;
|
||||
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import google.registry.privileges.secretmanager.SecretManagerModule;
|
||||
@@ -59,6 +60,13 @@ public interface RegistryPipelineComponent {
|
||||
@BeamBulkQueryJpaTm
|
||||
Lazy<JpaTransactionManager> getBulkQueryJpaTransactionManager();
|
||||
|
||||
/**
|
||||
* A {@link JpaTransactionManager} that uses the Postgres read-only replica if configured (uses
|
||||
* the standard DB otherwise).
|
||||
*/
|
||||
@BeamReadOnlyReplicaJpaTm
|
||||
Lazy<JpaTransactionManager> getReadOnlyReplicaJpaTransactionManager();
|
||||
|
||||
@Component.Builder
|
||||
interface Builder {
|
||||
|
||||
|
||||
@@ -56,6 +56,10 @@ public class RegistryPipelineWorkerInitializer implements JvmInitializer {
|
||||
case BULK_QUERY:
|
||||
transactionManagerLazy = registryPipelineComponent.getBulkQueryJpaTransactionManager();
|
||||
break;
|
||||
case READ_ONLY_REPLICA:
|
||||
transactionManagerLazy =
|
||||
registryPipelineComponent.getReadOnlyReplicaJpaTransactionManager();
|
||||
break;
|
||||
case REGULAR:
|
||||
default:
|
||||
transactionManagerLazy = registryPipelineComponent.getJpaTransactionManager();
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import google.registry.util.TaskQueueUtils;
|
||||
import google.registry.util.YamlUtils;
|
||||
import java.lang.annotation.Documented;
|
||||
@@ -392,19 +393,26 @@ public final class RegistryConfig {
|
||||
|
||||
@Provides
|
||||
@Config("cloudSqlJdbcUrl")
|
||||
public static String providesCloudSqlJdbcUrl(RegistryConfigSettings config) {
|
||||
public static String provideCloudSqlJdbcUrl(RegistryConfigSettings config) {
|
||||
return config.cloudSql.jdbcUrl;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("cloudSqlInstanceConnectionName")
|
||||
public static String providesCloudSqlInstanceConnectionName(RegistryConfigSettings config) {
|
||||
public static String provideCloudSqlInstanceConnectionName(RegistryConfigSettings config) {
|
||||
return config.cloudSql.instanceConnectionName;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("cloudSqlReplicaInstanceConnectionName")
|
||||
public static Optional<String> provideCloudSqlReplicaInstanceConnectionName(
|
||||
RegistryConfigSettings config) {
|
||||
return Optional.ofNullable(config.cloudSql.replicaInstanceConnectionName);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("cloudSqlDbInstanceName")
|
||||
public static String providesCloudSqlDbInstance(RegistryConfigSettings config) {
|
||||
public static String provideCloudSqlDbInstance(RegistryConfigSettings config) {
|
||||
// Format of instanceConnectionName: project-id:region:instance-name
|
||||
int lastColonIndex = config.cloudSql.instanceConnectionName.lastIndexOf(':');
|
||||
return config.cloudSql.instanceConnectionName.substring(lastColonIndex + 1);
|
||||
@@ -1524,6 +1532,31 @@ public final class RegistryConfig {
|
||||
return CONFIG_SETTINGS.get().hibernate.hikariIdleTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* JDBC-specific: driver default batch size is 0, which means that every INSERT statement will be
|
||||
* sent to the database individually. Batching allows us to group together multiple inserts into
|
||||
* one single INSERT statement which can dramatically increase speed in situations with many
|
||||
* inserts.
|
||||
*
|
||||
* <p>Hibernate docs, i.e.
|
||||
* https://docs.jboss.org/hibernate/orm/5.6/userguide/html_single/Hibernate_User_Guide.html,
|
||||
* recommend between 10 and 50.
|
||||
*/
|
||||
public static String getHibernateJdbcBatchSize() {
|
||||
return CONFIG_SETTINGS.get().hibernate.jdbcBatchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JDBC fetch size.
|
||||
*
|
||||
* <p>Postgresql-specific: driver default fetch size is 0, which disables streaming result sets.
|
||||
* Here we set a small default geared toward Nomulus server transactions. Large queries can
|
||||
* override the defaults using {@link JpaTransactionManager#setQueryFetchSize}.
|
||||
*/
|
||||
public static String getHibernateJdbcFetchSize() {
|
||||
return CONFIG_SETTINGS.get().hibernate.jdbcFetchSize;
|
||||
}
|
||||
|
||||
/** Returns the roid suffix to be used for the roids of all contacts and hosts. */
|
||||
public static String getContactAndHostRoidSuffix() {
|
||||
return CONFIG_SETTINGS.get().registryPolicy.contactAndHostRoidSuffix;
|
||||
|
||||
@@ -120,6 +120,8 @@ public class RegistryConfigSettings {
|
||||
public String hikariMinimumIdle;
|
||||
public String hikariMaximumPoolSize;
|
||||
public String hikariIdleTimeout;
|
||||
public String jdbcBatchSize;
|
||||
public String jdbcFetchSize;
|
||||
}
|
||||
|
||||
/** Configuration for Cloud SQL. */
|
||||
@@ -128,6 +130,7 @@ public class RegistryConfigSettings {
|
||||
// TODO(05012021): remove username field after it is removed from all yaml files.
|
||||
public String username;
|
||||
public String instanceConnectionName;
|
||||
public String replicaInstanceConnectionName;
|
||||
}
|
||||
|
||||
/** Configuration for Apache Beam (Cloud Dataflow). */
|
||||
|
||||
@@ -221,6 +221,17 @@ hibernate:
|
||||
hikariMinimumIdle: 1
|
||||
hikariMaximumPoolSize: 10
|
||||
hikariIdleTimeout: 300000
|
||||
# The batch size is basically the number of insertions / updates in a single
|
||||
# transaction that will be batched together into one INSERT/UPDATE statement.
|
||||
# A larger batch size is useful when inserting or updating many entities in a
|
||||
# single transaction. Hibernate docs
|
||||
# (https://docs.jboss.org/hibernate/orm/5.6/userguide/html_single/Hibernate_User_Guide.html)
|
||||
# recommend between 10 and 50.
|
||||
jdbcBatchSize: 50
|
||||
# The fetch size is the number of entities retrieved at a time from the
|
||||
# database cursor. Here we set a small default geared toward Nomulus server
|
||||
# transactions. Large queries can override the defaults on a per-query basis.
|
||||
jdbcFetchSize: 20
|
||||
|
||||
cloudSql:
|
||||
# jdbc url for the Cloud SQL database.
|
||||
@@ -231,6 +242,7 @@ cloudSql:
|
||||
jdbcUrl: jdbc:postgresql://localhost
|
||||
# This name is used by Cloud SQL when connecting to the database.
|
||||
instanceConnectionName: project-id:region:instance-id
|
||||
replicaInstanceConnectionName: null
|
||||
|
||||
cloudDns:
|
||||
# Set both properties to null in Production.
|
||||
|
||||
@@ -349,6 +349,15 @@
|
||||
<target>backend</target>
|
||||
</cron>
|
||||
|
||||
<cron>
|
||||
<url><![CDATA[/_dr/cron/replicateToDatastore]]></url>
|
||||
<description>
|
||||
Replays recent transactions from SQL to the Datastore secondary backend.
|
||||
</description>
|
||||
<schedule>every 3 minutes</schedule>
|
||||
<target>backend</target>
|
||||
</cron>
|
||||
|
||||
<cron>
|
||||
<url><![CDATA[/_dr/task/wipeOutContactHistoryPii]]></url>
|
||||
<description>
|
||||
|
||||
@@ -26,7 +26,6 @@ import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
@@ -143,7 +142,7 @@ public class ExportPremiumTermsAction implements Runnable {
|
||||
PremiumListDao.getLatestRevision(premiumListName).isPresent(),
|
||||
"Could not load premium list for " + tld);
|
||||
SortedSet<String> premiumTerms =
|
||||
Streams.stream(PremiumListDao.loadAllPremiumEntries(premiumListName))
|
||||
PremiumListDao.loadAllPremiumEntries(premiumListName).stream()
|
||||
.map(PremiumEntry::toString)
|
||||
.collect(ImmutableSortedSet.toImmutableSortedSet(String::compareTo));
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package google.registry.model;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
@@ -45,6 +46,7 @@ import google.registry.model.server.ServerSecret;
|
||||
import google.registry.model.tld.Registry;
|
||||
|
||||
/** Sets of classes of the Objectify-registered entities in use throughout the model. */
|
||||
@DeleteAfterMigration
|
||||
public final class EntityClasses {
|
||||
|
||||
/** Set of entity classes. */
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.google.appengine.api.datastore.DatastoreServiceFactory;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import google.registry.beam.common.RegistryPipelineWorkerInitializer;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
@@ -28,6 +29,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
* <p>In non-test, non-beam environments the Id is generated by Datastore, otherwise it's from an
|
||||
* atomic long number that's incremented every time this method is called.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public final class IdService {
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,12 +19,14 @@ import static com.google.common.base.Predicates.subtypeOf;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
import com.google.common.collect.Ordering;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/** Utility methods for getting the version of the model schema from the model code. */
|
||||
@DeleteAfterMigration
|
||||
public final class SchemaVersion {
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,11 +20,13 @@ import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.InCrossTld;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
/** A singleton entity in Datastore. */
|
||||
@DeleteAfterMigration
|
||||
@MappedSuperclass
|
||||
@InCrossTld
|
||||
public abstract class CrossTldSingleton extends ImmutableObject {
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.common.TimedTransitionProperty.TimedTransition;
|
||||
import google.registry.model.replay.SqlOnlyEntity;
|
||||
import java.time.Duration;
|
||||
@@ -39,6 +40,7 @@ import org.joda.time.DateTime;
|
||||
* <p>The entity is stored in SQL throughout the entire migration so as to have a single point of
|
||||
* access.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
@Entity
|
||||
public class DatabaseMigrationStateSchedule extends CrossTldSingleton implements SqlOnlyEntity {
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.replay.DatastoreOnlyEntity;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -37,6 +38,7 @@ import javax.annotation.Nullable;
|
||||
* entity group for the single namespace where global data applicable for all TLDs lived.
|
||||
*/
|
||||
@Entity
|
||||
@DeleteAfterMigration
|
||||
public class EntityGroupRoot extends BackupGroupRoot implements DatastoreOnlyEntity {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
||||
@@ -24,12 +24,15 @@ import com.googlecode.objectify.annotation.Index;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.replay.DatastoreOnlyEntity;
|
||||
import google.registry.persistence.VKey;
|
||||
|
||||
/** An index that allows for quick enumeration of all EppResource entities (e.g. via map reduce). */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@DeleteAfterMigration
|
||||
public class EppResourceIndex extends BackupGroupRoot implements DatastoreOnlyEntity {
|
||||
|
||||
@Id String id;
|
||||
@@ -64,8 +67,9 @@ public class EppResourceIndex extends BackupGroupRoot implements DatastoreOnlyEn
|
||||
EppResourceIndex instance = instantiate(EppResourceIndex.class);
|
||||
instance.reference = resourceKey;
|
||||
instance.kind = resourceKey.getKind();
|
||||
// TODO(b/207368050): figure out if this value has ever been used other than test cases
|
||||
instance.id = resourceKey.getString(); // creates a web-safe key string
|
||||
// creates a web-safe key string, this value is never used
|
||||
// TODO(b/211785379): remove unused id
|
||||
instance.id = VKey.from(resourceKey).stringify();
|
||||
instance.bucket = bucket;
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -23,12 +23,14 @@ import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.VirtualEntity;
|
||||
import google.registry.model.replay.DatastoreOnlyEntity;
|
||||
|
||||
/** A virtual entity to represent buckets to which EppResourceIndex objects are randomly added. */
|
||||
@Entity
|
||||
@VirtualEntity
|
||||
@DeleteAfterMigration
|
||||
public class EppResourceIndexBucket extends ImmutableObject implements DatastoreOnlyEntity {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.googlecode.objectify.annotation.Index;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
@@ -65,6 +66,7 @@ import org.joda.time.Duration;
|
||||
* the foreign key string. The instance is never deleted, but it is updated if a newer entity
|
||||
* becomes the active entity.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroupRoot {
|
||||
|
||||
/** The {@link ForeignKeyIndex} type for {@link ContactResource} entities. */
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.Result;
|
||||
import com.googlecode.objectify.cmd.DeleteType;
|
||||
import com.googlecode.objectify.cmd.Deleter;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -30,6 +31,7 @@ import java.util.stream.Stream;
|
||||
* A Deleter that forwards to {@code auditedOfy().delete()}, but can be augmented via subclassing to
|
||||
* do custom processing on the keys to be deleted prior to their deletion.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
abstract class AugmentedDeleter implements Deleter {
|
||||
private final Deleter delegate = ofy().delete();
|
||||
|
||||
|
||||
@@ -21,13 +21,15 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.Result;
|
||||
import com.googlecode.objectify.cmd.Saver;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A Saver that forwards to {@code ofy().save()}, but can be augmented via subclassing to
|
||||
* do custom processing on the entities to be saved prior to their saving.
|
||||
* A Saver that forwards to {@code ofy().save()}, but can be augmented via subclassing to do custom
|
||||
* processing on the entities to be saved prior to their saving.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
abstract class AugmentedSaver implements Saver {
|
||||
private final Saver delegate = ofy().save();
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.NotBackedUp.Reason;
|
||||
import google.registry.model.replay.DatastoreOnlyEntity;
|
||||
@@ -51,6 +52,7 @@ import org.joda.time.DateTime;
|
||||
*/
|
||||
@Entity
|
||||
@NotBackedUp(reason = Reason.COMMIT_LOGS)
|
||||
@DeleteAfterMigration
|
||||
public class CommitLogBucket extends ImmutableObject implements Buildable, DatastoreOnlyEntity {
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.NotBackedUp.Reason;
|
||||
import google.registry.model.replay.DatastoreOnlyEntity;
|
||||
@@ -45,6 +46,7 @@ import org.joda.time.DateTime;
|
||||
*/
|
||||
@Entity
|
||||
@NotBackedUp(reason = Reason.COMMIT_LOGS)
|
||||
@DeleteAfterMigration
|
||||
public class CommitLogCheckpoint extends ImmutableObject implements DatastoreOnlyEntity {
|
||||
|
||||
/** Shared singleton parent entity for commit log checkpoints. */
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.NotBackedUp.Reason;
|
||||
import google.registry.model.replay.DatastoreOnlyEntity;
|
||||
@@ -29,6 +30,7 @@ import org.joda.time.DateTime;
|
||||
/** Singleton parent entity for all commit log checkpoints. */
|
||||
@Entity
|
||||
@NotBackedUp(reason = Reason.COMMIT_LOGS)
|
||||
@DeleteAfterMigration
|
||||
public class CommitLogCheckpointRoot extends ImmutableObject implements DatastoreOnlyEntity {
|
||||
|
||||
public static final long SINGLETON_ID = 1; // There is always exactly one of these.
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.NotBackedUp.Reason;
|
||||
import google.registry.model.replay.DatastoreOnlyEntity;
|
||||
@@ -39,6 +40,7 @@ import org.joda.time.DateTime;
|
||||
*/
|
||||
@Entity
|
||||
@NotBackedUp(reason = Reason.COMMIT_LOGS)
|
||||
@DeleteAfterMigration
|
||||
public class CommitLogManifest extends ImmutableObject implements DatastoreOnlyEntity {
|
||||
|
||||
/** Commit log manifests are parented on a random bucket. */
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.NotBackedUp.Reason;
|
||||
import google.registry.model.replay.DatastoreOnlyEntity;
|
||||
@@ -34,6 +35,7 @@ import google.registry.model.replay.DatastoreOnlyEntity;
|
||||
/** Representation of a saved entity in a {@link CommitLogManifest} (not deletes). */
|
||||
@Entity
|
||||
@NotBackedUp(reason = Reason.COMMIT_LOGS)
|
||||
@DeleteAfterMigration
|
||||
public class CommitLogMutation extends ImmutableObject implements DatastoreOnlyEntity {
|
||||
|
||||
/** The manifest this belongs to. */
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.util.Clock;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@@ -39,6 +40,7 @@ import java.util.function.Supplier;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Wrapper for {@link Supplier} that associates a time with each attempt. */
|
||||
@DeleteAfterMigration
|
||||
class CommitLoggedWork<R> implements Runnable {
|
||||
|
||||
private final Supplier<R> work;
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.Result;
|
||||
import com.googlecode.objectify.cmd.Query;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.InCrossTld;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
@@ -55,6 +56,7 @@ import javax.persistence.NonUniqueResultException;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Datastore implementation of {@link TransactionManager}. */
|
||||
@DeleteAfterMigration
|
||||
public class DatastoreTransactionManager implements TransactionManager {
|
||||
|
||||
private Ofy injectedOfy;
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.model.ofy;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
|
||||
/**
|
||||
* Contains the mapping from class names to SQL-replay-write priorities.
|
||||
@@ -26,6 +27,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
* values represent an earlier write (and later delete). Higher-valued classes can have foreign keys
|
||||
* on lower-valued classes, but not vice versa.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public class EntityWritePriorities {
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,6 +35,7 @@ import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.EntityClasses;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.translators.BloomFilterOfStringTranslatorFactory;
|
||||
import google.registry.model.translators.CidrAddressBlockTranslatorFactory;
|
||||
import google.registry.model.translators.CommitLogRevisionsTranslatorFactory;
|
||||
@@ -52,6 +53,7 @@ import google.registry.model.translators.VKeyTranslatorFactory;
|
||||
* objects. The class contains a static initializer to call factory().register(...) on all
|
||||
* persistable objects in this package.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public class ObjectifyService {
|
||||
|
||||
/** A singleton instance of our Ofy wrapper. */
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.googlecode.objectify.ObjectifyFactory;
|
||||
import com.googlecode.objectify.cmd.Deleter;
|
||||
import com.googlecode.objectify.cmd.Loader;
|
||||
import com.googlecode.objectify.cmd.Saver;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.VirtualEntity;
|
||||
import google.registry.model.ofy.ReadOnlyWork.KillTransactionException;
|
||||
@@ -59,6 +60,7 @@ import org.joda.time.Duration;
|
||||
* simpler to wrap {@link Objectify} rather than extend it because this way we can remove some
|
||||
* methods that we don't really want exposed and add some shortcuts.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public class Ofy {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.model.ofy;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.io.IOException;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
@@ -23,6 +24,7 @@ import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
/** A filter that statically registers types with Objectify. */
|
||||
@DeleteAfterMigration
|
||||
public class OfyFilter implements Filter {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
|
||||
package google.registry.model.ofy;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.util.Clock;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/** Wrapper for {@link Supplier} that disallows mutations and fails the transaction at the end. */
|
||||
@DeleteAfterMigration
|
||||
class ReadOnlyWork<R> extends CommitLoggedWork<R> {
|
||||
|
||||
ReadOnlyWork(Supplier<R> work, Clock clock) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.UpdateAutoTimestamp;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.replay.DatastoreEntity;
|
||||
import google.registry.model.replay.ReplaySpecializer;
|
||||
import google.registry.persistence.VKey;
|
||||
@@ -34,6 +35,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
*
|
||||
* <p>This code is to be removed when the actual replay cron job is implemented.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public class ReplayQueue {
|
||||
|
||||
static ConcurrentLinkedQueue<ImmutableMap<Key<?>, Object>> queue =
|
||||
|
||||
+2
@@ -28,6 +28,7 @@ import com.google.appengine.api.datastore.Query;
|
||||
import com.google.appengine.api.datastore.Transaction;
|
||||
import com.google.appengine.api.datastore.TransactionOptions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -35,6 +36,7 @@ import java.util.Map;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/** A proxy for {@link AsyncDatastoreService} that exposes call counts. */
|
||||
@DeleteAfterMigration
|
||||
public class RequestCapturingAsyncDatastoreService implements AsyncDatastoreService {
|
||||
|
||||
private final AsyncDatastoreService delegate;
|
||||
|
||||
@@ -18,8 +18,10 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.ObjectifyFactory;
|
||||
import com.googlecode.objectify.impl.ObjectifyImpl;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
|
||||
/** Registry-specific Objectify subclass that exposes the keys used in the current session. */
|
||||
@DeleteAfterMigration
|
||||
public class SessionKeyExposingObjectify extends ObjectifyImpl<SessionKeyExposingObjectify> {
|
||||
|
||||
public SessionKeyExposingObjectify(ObjectifyFactory factory) {
|
||||
|
||||
@@ -17,6 +17,7 @@ package google.registry.model.ofy;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.Objectify;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -25,6 +26,7 @@ import org.joda.time.DateTime;
|
||||
* Exception when trying to write to Datastore with a timestamp that is inconsistent with a partial
|
||||
* ordering on transactions that touch the same entities.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
class TimestampInversionException extends RuntimeException {
|
||||
|
||||
static String getFileAndLine(StackTraceElement callsite) {
|
||||
|
||||
@@ -26,10 +26,12 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.Map;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Metadata for an {@link Ofy} transaction that saves commit logs. */
|
||||
@DeleteAfterMigration
|
||||
public class TransactionInfo {
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
|
||||
package google.registry.model.replay;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.Optional;
|
||||
|
||||
/** An entity that has the same Java object representation in SQL and Datastore. */
|
||||
@DeleteAfterMigration
|
||||
public interface DatastoreAndSqlEntity extends DatastoreEntity, SqlEntity {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.model.replay;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -24,6 +25,7 @@ import java.util.Optional;
|
||||
* transactions and data into the secondary SQL store during the first, Datastore-primary, phase of
|
||||
* the migration.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public interface DatastoreEntity {
|
||||
|
||||
Optional<SqlEntity> toSqlEntity();
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
|
||||
package google.registry.model.replay;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.Optional;
|
||||
|
||||
/** An entity that is only stored in Datastore, that should not be replayed to SQL. */
|
||||
@DeleteAfterMigration
|
||||
public interface DatastoreOnlyEntity extends DatastoreEntity {
|
||||
@Override
|
||||
default Optional<SqlEntity> toSqlEntity() {
|
||||
|
||||
@@ -22,9 +22,11 @@ import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
|
||||
/** Datastore entity to keep track of the last SQL transaction imported into the datastore. */
|
||||
@Entity
|
||||
@DeleteAfterMigration
|
||||
public class LastSqlTransaction extends ImmutableObject implements DatastoreOnlyEntity {
|
||||
|
||||
/** The key for this singleton. */
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.model.replay;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -21,6 +22,7 @@ import java.util.Optional;
|
||||
*
|
||||
* <p>We expect that this is a result of the entity being dually-written.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public interface NonReplicatedEntity extends DatastoreEntity, SqlEntity {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.model.replay;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -25,6 +26,7 @@ import java.lang.reflect.Method;
|
||||
* not directly present in the other database. This class allows us to do that by using reflection
|
||||
* to invoke special class methods if they are present.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public class ReplaySpecializer {
|
||||
|
||||
public static void beforeSqlDelete(VKey<?> key) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.model.UpdateAutoTimestamp;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.ReplayDirection;
|
||||
@@ -53,6 +54,7 @@ import org.joda.time.Duration;
|
||||
automaticallyPrintOk = true,
|
||||
auth = Auth.AUTH_INTERNAL_OR_ADMIN)
|
||||
@VisibleForTesting
|
||||
@DeleteAfterMigration
|
||||
public class ReplicateToDatastoreAction implements Runnable {
|
||||
public static final String PATH = "/_dr/cron/replicateToDatastore";
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.model.replay;
|
||||
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -25,6 +26,7 @@ import java.util.Optional;
|
||||
* <p>This will be used when replaying SQL transactions into Datastore, during the second,
|
||||
* SQL-primary, phase of the migration from Datastore to SQL.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public interface SqlEntity {
|
||||
|
||||
Optional<DatastoreEntity> toDatastoreEntity();
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
|
||||
package google.registry.model.replay;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.Optional;
|
||||
|
||||
/** An entity that is only stored in SQL, that should not be replayed to Datastore. */
|
||||
@DeleteAfterMigration
|
||||
public interface SqlOnlyEntity extends SqlEntity {
|
||||
@Override
|
||||
default Optional<DatastoreEntity> toDatastoreEntity() {
|
||||
|
||||
@@ -17,12 +17,14 @@ package google.registry.model.replay;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.common.CrossTldSingleton;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@Entity
|
||||
@DeleteAfterMigration
|
||||
public class SqlReplayCheckpoint extends CrossTldSingleton implements SqlOnlyEntity {
|
||||
|
||||
@Column(nullable = false)
|
||||
|
||||
@@ -21,7 +21,6 @@ import static com.google.common.hash.Funnels.stringFunnel;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.hash.BloomFilter;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.ImmutableObject;
|
||||
@@ -86,9 +85,8 @@ public final class PremiumList extends BaseDomainLabelList<BigDecimal, PremiumEn
|
||||
*/
|
||||
public synchronized ImmutableMap<String, BigDecimal> getLabelsToPrices() {
|
||||
if (labelsToPrices == null) {
|
||||
Iterable<PremiumEntry> entries = PremiumListDao.loadAllPremiumEntries(name);
|
||||
labelsToPrices =
|
||||
Streams.stream(entries)
|
||||
PremiumListDao.loadAllPremiumEntries(name).stream()
|
||||
.collect(
|
||||
toImmutableMap(
|
||||
PremiumEntry::getDomainLabel,
|
||||
|
||||
@@ -28,8 +28,8 @@ import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import google.registry.model.tld.label.PremiumList.PremiumEntry;
|
||||
import google.registry.util.NonFinalForTesting;
|
||||
import java.math.BigDecimal;
|
||||
@@ -56,8 +56,7 @@ public class PremiumListDao {
|
||||
* <p>This is cached for a shorter duration because we need to periodically reload this entity to
|
||||
* check if a new revision has been published, and if so, then use that.
|
||||
*
|
||||
* <p>We also cache the absence of premium lists with a given name to avoid unnecessary pointless
|
||||
* lookups. Note that this cache is only applicable to PremiumList objects stored in SQL.
|
||||
* <p>We also cache the absence of premium lists with a given name to avoid pointless lookups.
|
||||
*/
|
||||
@NonFinalForTesting
|
||||
static LoadingCache<String, Optional<PremiumList>> premiumListCache =
|
||||
@@ -170,11 +169,10 @@ public class PremiumListDao {
|
||||
|
||||
if (!isNullOrEmpty(premiumList.getLabelsToPrices())) {
|
||||
ImmutableSet.Builder<PremiumEntry> entries = new ImmutableSet.Builder<>();
|
||||
premiumList.getLabelsToPrices().entrySet().stream()
|
||||
premiumList
|
||||
.getLabelsToPrices()
|
||||
.forEach(
|
||||
entry ->
|
||||
entries.add(
|
||||
PremiumEntry.create(revisionId, entry.getValue(), entry.getKey())));
|
||||
(key, value) -> entries.add(PremiumEntry.create(revisionId, value, key)));
|
||||
jpaTm().insertAll(entries.build());
|
||||
}
|
||||
});
|
||||
@@ -217,7 +215,7 @@ public class PremiumListDao {
|
||||
*
|
||||
* <p>This is an expensive operation and should only be used when the entire list is required.
|
||||
*/
|
||||
public static Iterable<PremiumEntry> loadPremiumEntries(PremiumList premiumList) {
|
||||
public static List<PremiumEntry> loadPremiumEntries(PremiumList premiumList) {
|
||||
return jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
@@ -254,15 +252,14 @@ public class PremiumListDao {
|
||||
*
|
||||
* <p>This is an expensive operation and should only be used when the entire list is required.
|
||||
*/
|
||||
public static Iterable<PremiumEntry> loadAllPremiumEntries(String premiumListName) {
|
||||
public static ImmutableList<PremiumEntry> loadAllPremiumEntries(String premiumListName) {
|
||||
PremiumList premiumList =
|
||||
getLatestRevision(premiumListName)
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new IllegalArgumentException(
|
||||
String.format("No premium list with name %s.", premiumListName)));
|
||||
Iterable<PremiumEntry> entries = loadPremiumEntries(premiumList);
|
||||
return Streams.stream(entries)
|
||||
return loadPremiumEntries(premiumList).stream()
|
||||
.map(
|
||||
premiumEntry ->
|
||||
new PremiumEntry.Builder()
|
||||
|
||||
+7
-4
@@ -23,6 +23,7 @@ import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.ofy.CommitLogManifest;
|
||||
import google.registry.persistence.transaction.Transaction;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -31,11 +32,12 @@ import org.joda.time.DateTime;
|
||||
* Objectify translator for {@code ImmutableSortedMap<DateTime, Key<CommitLogManifest>>} fields.
|
||||
*
|
||||
* <p>This translator is responsible for doing three things:
|
||||
*
|
||||
* <ol>
|
||||
* <li>Translating the data into two lists of {@code Date} and {@code Key} objects, in a manner
|
||||
* similar to {@code @Mapify}.
|
||||
* <li>Inserting a key to the transaction's {@link CommitLogManifest} on save.
|
||||
* <li>Truncating the map to include only the last key per day for the last 30 days.
|
||||
* <li>Translating the data into two lists of {@code Date} and {@code Key} objects, in a manner
|
||||
* similar to {@code @Mapify}.
|
||||
* <li>Inserting a key to the transaction's {@link CommitLogManifest} on save.
|
||||
* <li>Truncating the map to include only the last key per day for the last 30 days.
|
||||
* </ol>
|
||||
*
|
||||
* <p>This allows you to have a field on your model object that tracks historical revisions of
|
||||
@@ -46,6 +48,7 @@ import org.joda.time.DateTime;
|
||||
*
|
||||
* @see google.registry.model.EppResource
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public final class CommitLogRevisionsTranslatorFactory
|
||||
extends ImmutableSortedMapTranslatorFactory<DateTime, Key<CommitLogManifest>> {
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import google.registry.config.CredentialModule;
|
||||
import google.registry.config.RegistryConfig.ConfigModule;
|
||||
import google.registry.keyring.kms.KmsModule;
|
||||
import google.registry.persistence.PersistenceModule.AppEngineJpaTm;
|
||||
import google.registry.persistence.PersistenceModule.ReadOnlyReplicaJpaTm;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import google.registry.privileges.secretmanager.SecretManagerModule;
|
||||
import google.registry.util.UtilsModule;
|
||||
@@ -40,4 +41,7 @@ public interface PersistenceComponent {
|
||||
|
||||
@AppEngineJpaTm
|
||||
JpaTransactionManager appEngineJpaTransactionManager();
|
||||
|
||||
@ReadOnlyReplicaJpaTm
|
||||
JpaTransactionManager readOnlyReplicaJpaTransactionManager();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import static google.registry.config.RegistryConfig.getHibernateHikariConnection
|
||||
import static google.registry.config.RegistryConfig.getHibernateHikariIdleTimeout;
|
||||
import static google.registry.config.RegistryConfig.getHibernateHikariMaximumPoolSize;
|
||||
import static google.registry.config.RegistryConfig.getHibernateHikariMinimumIdle;
|
||||
import static google.registry.config.RegistryConfig.getHibernateJdbcBatchSize;
|
||||
import static google.registry.config.RegistryConfig.getHibernateJdbcFetchSize;
|
||||
import static google.registry.config.RegistryConfig.getHibernateLogSqlQueries;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
@@ -76,15 +78,9 @@ public abstract class PersistenceModule {
|
||||
public static final String HIKARI_DS_CLOUD_SQL_INSTANCE =
|
||||
"hibernate.hikari.dataSource.cloudSqlInstance";
|
||||
|
||||
/**
|
||||
* Postgresql-specific: driver default fetch size is 0, which disables streaming result sets. Here
|
||||
* we set a small default geared toward Nomulus server transactions. Large queries can override
|
||||
* the defaults using {@link JpaTransactionManager#setQueryFetchSize}.
|
||||
*/
|
||||
public static final String JDBC_BATCH_SIZE = "hibernate.jdbc.batch_size";
|
||||
public static final String JDBC_FETCH_SIZE = "hibernate.jdbc.fetch_size";
|
||||
|
||||
private static final int DEFAULT_SERVER_FETCH_SIZE = 20;
|
||||
|
||||
@VisibleForTesting
|
||||
@Provides
|
||||
@DefaultHibernateConfigs
|
||||
@@ -111,7 +107,8 @@ public abstract class PersistenceModule {
|
||||
properties.put(HIKARI_MAXIMUM_POOL_SIZE, getHibernateHikariMaximumPoolSize());
|
||||
properties.put(HIKARI_IDLE_TIMEOUT, getHibernateHikariIdleTimeout());
|
||||
properties.put(Environment.DIALECT, NomulusPostgreSQLDialect.class.getName());
|
||||
properties.put(JDBC_FETCH_SIZE, Integer.toString(DEFAULT_SERVER_FETCH_SIZE));
|
||||
properties.put(JDBC_BATCH_SIZE, getHibernateJdbcBatchSize());
|
||||
properties.put(JDBC_FETCH_SIZE, getHibernateJdbcFetchSize());
|
||||
return properties.build();
|
||||
}
|
||||
|
||||
@@ -122,8 +119,11 @@ public abstract class PersistenceModule {
|
||||
@Config("cloudSqlJdbcUrl") String jdbcUrl,
|
||||
@Config("cloudSqlInstanceConnectionName") String instanceConnectionName,
|
||||
@DefaultHibernateConfigs ImmutableMap<String, String> defaultConfigs) {
|
||||
return createPartialSqlConfigs(
|
||||
jdbcUrl, instanceConnectionName, defaultConfigs, Optional.empty());
|
||||
HashMap<String, String> overrides = Maps.newHashMap(defaultConfigs);
|
||||
overrides.put(Environment.URL, jdbcUrl);
|
||||
overrides.put(HIKARI_DS_SOCKET_FACTORY, "com.google.cloud.sql.postgres.SocketFactory");
|
||||
overrides.put(HIKARI_DS_CLOUD_SQL_INSTANCE, instanceConnectionName);
|
||||
return ImmutableMap.copyOf(overrides);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,22 +184,6 @@ public abstract class PersistenceModule {
|
||||
return ImmutableMap.copyOf(overrides);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static ImmutableMap<String, String> createPartialSqlConfigs(
|
||||
String jdbcUrl,
|
||||
String instanceConnectionName,
|
||||
ImmutableMap<String, String> defaultConfigs,
|
||||
Optional<Provider<TransactionIsolationLevel>> isolationOverride) {
|
||||
HashMap<String, String> overrides = Maps.newHashMap(defaultConfigs);
|
||||
overrides.put(Environment.URL, jdbcUrl);
|
||||
overrides.put(HIKARI_DS_SOCKET_FACTORY, "com.google.cloud.sql.postgres.SocketFactory");
|
||||
overrides.put(HIKARI_DS_CLOUD_SQL_INSTANCE, instanceConnectionName);
|
||||
isolationOverride
|
||||
.map(Provider::get)
|
||||
.ifPresent(override -> overrides.put(Environment.ISOLATION, override.name()));
|
||||
return ImmutableMap.copyOf(overrides);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a {@link Supplier} of single-use JDBC {@link Connection connections} that can manage
|
||||
* the database DDL schema.
|
||||
@@ -280,6 +264,36 @@ public abstract class PersistenceModule {
|
||||
return new JpaTransactionManagerImpl(create(overrides), clock);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@ReadOnlyReplicaJpaTm
|
||||
static JpaTransactionManager provideReadOnlyReplicaJpaTm(
|
||||
SqlCredentialStore credentialStore,
|
||||
@PartialCloudSqlConfigs ImmutableMap<String, String> cloudSqlConfigs,
|
||||
@Config("cloudSqlReplicaInstanceConnectionName")
|
||||
Optional<String> replicaInstanceConnectionName,
|
||||
Clock clock) {
|
||||
HashMap<String, String> overrides = Maps.newHashMap(cloudSqlConfigs);
|
||||
setSqlCredential(credentialStore, new RobotUser(RobotId.NOMULUS), overrides);
|
||||
replicaInstanceConnectionName.ifPresent(
|
||||
name -> overrides.put(HIKARI_DS_CLOUD_SQL_INSTANCE, name));
|
||||
return new JpaTransactionManagerImpl(create(overrides), clock);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@BeamReadOnlyReplicaJpaTm
|
||||
static JpaTransactionManager provideBeamReadOnlyReplicaJpaTm(
|
||||
@BeamPipelineCloudSqlConfigs ImmutableMap<String, String> beamCloudSqlConfigs,
|
||||
@Config("cloudSqlReplicaInstanceConnectionName")
|
||||
Optional<String> replicaInstanceConnectionName,
|
||||
Clock clock) {
|
||||
HashMap<String, String> overrides = Maps.newHashMap(beamCloudSqlConfigs);
|
||||
replicaInstanceConnectionName.ifPresent(
|
||||
name -> overrides.put(HIKARI_DS_CLOUD_SQL_INSTANCE, name));
|
||||
return new JpaTransactionManagerImpl(create(overrides), clock);
|
||||
}
|
||||
|
||||
/** Constructs the {@link EntityManagerFactory} instance. */
|
||||
@VisibleForTesting
|
||||
static EntityManagerFactory create(
|
||||
@@ -357,7 +371,12 @@ public abstract class PersistenceModule {
|
||||
* The {@link JpaTransactionManager} optimized for bulk loading multi-level JPA entities. Please
|
||||
* see {@link google.registry.model.bulkquery.BulkQueryEntities} for more information.
|
||||
*/
|
||||
BULK_QUERY
|
||||
BULK_QUERY,
|
||||
/**
|
||||
* The {@link JpaTransactionManager} that uses the read-only Postgres replica if configured, or
|
||||
* the standard DB if not.
|
||||
*/
|
||||
READ_ONLY_REPLICA
|
||||
}
|
||||
|
||||
/** Dagger qualifier for JDBC {@link Connection} with schema management privilege. */
|
||||
@@ -383,6 +402,22 @@ public abstract class PersistenceModule {
|
||||
@Documented
|
||||
public @interface BeamBulkQueryJpaTm {}
|
||||
|
||||
/**
|
||||
* Dagger qualifier for {@link JpaTransactionManager} used inside BEAM pipelines that uses the
|
||||
* read-only Postgres replica if one is configured (otherwise it uses the standard DB).
|
||||
*/
|
||||
@Qualifier
|
||||
@Documented
|
||||
public @interface BeamReadOnlyReplicaJpaTm {}
|
||||
|
||||
/**
|
||||
* Dagger qualifier for {@link JpaTransactionManager} that uses the read-only Postgres replica if
|
||||
* one is configured (otherwise it uses the standard DB).
|
||||
*/
|
||||
@Qualifier
|
||||
@Documented
|
||||
public @interface ReadOnlyReplicaJpaTm {}
|
||||
|
||||
/** Dagger qualifier for {@link JpaTransactionManager} used for Nomulus tool. */
|
||||
@Qualifier
|
||||
@Documented
|
||||
|
||||
@@ -144,7 +144,7 @@ public class VKey<T> extends ImmutableObject implements Serializable {
|
||||
*/
|
||||
public static <T> VKey<T> create(String keyString) {
|
||||
if (!keyString.startsWith(CLASS_TYPE + KV_SEPARATOR)) {
|
||||
// to handle the existing ofy key string
|
||||
// handle the existing ofy key string
|
||||
return fromWebsafeKey(keyString);
|
||||
} else {
|
||||
ImmutableMap<String, String> kvs =
|
||||
@@ -307,6 +307,7 @@ public class VKey<T> extends ImmutableObject implements Serializable {
|
||||
if (maybeGetSqlKey().isPresent()) {
|
||||
key += DELIMITER + SQL_LOOKUP_KEY + KV_SEPARATOR + SerializeUtils.stringify(getSqlKey());
|
||||
}
|
||||
// getString() method returns a Base64 encoded web safe of ofy key
|
||||
if (maybeGetOfyKey().isPresent()) {
|
||||
key += DELIMITER + OFY_LOOKUP_KEY + KV_SEPARATOR + getOfyKey().getString();
|
||||
}
|
||||
|
||||
+2
@@ -15,6 +15,7 @@
|
||||
package google.registry.persistence.converter;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationStateTransition;
|
||||
@@ -23,6 +24,7 @@ import javax.persistence.Converter;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** JPA converter for {@link DatabaseMigrationStateSchedule} transitions. */
|
||||
@DeleteAfterMigration
|
||||
@Converter(autoApply = true)
|
||||
public class DatabaseMigrationScheduleTransitionConverter
|
||||
extends TimedTransitionPropertyConverterBase<MigrationState, MigrationStateTransition> {
|
||||
|
||||
+2
@@ -16,6 +16,7 @@ package google.registry.persistence.transaction;
|
||||
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.assertNotReadOnlyMode;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.EntityGraph;
|
||||
@@ -34,6 +35,7 @@ import javax.persistence.criteria.CriteriaUpdate;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
|
||||
/** An {@link EntityManager} that throws exceptions on write actions if in read-only mode. */
|
||||
@DeleteAfterMigration
|
||||
public class ReadOnlyCheckingEntityManager implements EntityManager {
|
||||
|
||||
private final EntityManager delegate;
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.persistence.transaction;
|
||||
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.assertNotReadOnlyMode;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -29,6 +30,7 @@ import javax.persistence.Query;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
/** A {@link Query} that throws exceptions on write actions if in read-only mode. */
|
||||
@DeleteAfterMigration
|
||||
class ReadOnlyCheckingQuery implements Query {
|
||||
|
||||
private final Query delegate;
|
||||
|
||||
+2
@@ -16,6 +16,7 @@ package google.registry.persistence.transaction;
|
||||
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.assertNotReadOnlyMode;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -29,6 +30,7 @@ import javax.persistence.TemporalType;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
/** A {@link TypedQuery <T>} that throws exceptions on write actions if in read-only mode. */
|
||||
@DeleteAfterMigration
|
||||
class ReadOnlyCheckingTypedQuery<T> implements TypedQuery<T> {
|
||||
|
||||
private final TypedQuery<T> delegate;
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.rde;
|
||||
|
||||
import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
|
||||
import static google.registry.request.RequestParameters.extractBooleanParameter;
|
||||
import static google.registry.request.RequestParameters.extractOptionalIntParameter;
|
||||
import static google.registry.request.RequestParameters.extractOptionalParameter;
|
||||
@@ -22,7 +21,6 @@ import static google.registry.request.RequestParameters.extractRequiredDatetimeP
|
||||
import static google.registry.request.RequestParameters.extractSetOfDatetimeParameters;
|
||||
import static google.registry.request.RequestParameters.extractSetOfParameters;
|
||||
|
||||
import com.google.appengine.api.taskqueue.Queue;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.jcraft.jsch.SftpProgressMonitor;
|
||||
import dagger.Binds;
|
||||
@@ -30,7 +28,6 @@ import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.request.Parameter;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Named;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@@ -110,12 +107,6 @@ public abstract class RdeModule {
|
||||
return extractOptionalParameter(req, PARAM_PREFIX);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named("rde-report")
|
||||
static Queue provideQueueRdeReport() {
|
||||
return getQueue("rde-report");
|
||||
}
|
||||
|
||||
@Binds
|
||||
abstract SftpProgressMonitor provideSftpProgressMonitor(
|
||||
LoggingSftpProgressMonitor loggingSftpProgressMonitor);
|
||||
|
||||
@@ -56,6 +56,7 @@ import google.registry.model.host.HostResource;
|
||||
import google.registry.model.index.EppResourceIndex;
|
||||
import google.registry.model.rde.RdeMode;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.persistence.PersistenceModule.JpaTransactionManagerType;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.HttpException.BadRequestException;
|
||||
import google.registry.request.Parameter;
|
||||
@@ -340,6 +341,9 @@ public final class RdeStagingAction implements Runnable {
|
||||
.encode(stagingKeyBytes))
|
||||
.put("registryEnvironment", RegistryEnvironment.get().name())
|
||||
.put("workerMachineType", machineType)
|
||||
.put(
|
||||
"jpaTransactionManagerType",
|
||||
JpaTransactionManagerType.READ_ONLY_REPLICA.toString())
|
||||
// TODO (jianglai): Investigate turning off public IPs (for which
|
||||
// there is a quota) in order to increase the total number of
|
||||
// workers allowed (also under quota).
|
||||
|
||||
@@ -17,6 +17,7 @@ package google.registry.tools;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Sets.SetView;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
@@ -27,6 +28,7 @@ import java.io.File;
|
||||
* two-level directory hierarchy with data files in level-db format (output-*) and Datastore
|
||||
* metadata files (*.export_metadata).
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
class CompareDbBackups {
|
||||
private static final String DS_V3_BACKUP_FILE_PREFIX = "output-";
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl;
|
||||
import static google.registry.model.tld.Registries.assertTldsExist;
|
||||
import static google.registry.rde.RdeModule.PARAM_BEAM;
|
||||
import static google.registry.rde.RdeModule.PARAM_DIRECTORY;
|
||||
@@ -23,23 +22,22 @@ import static google.registry.rde.RdeModule.PARAM_MANUAL;
|
||||
import static google.registry.rde.RdeModule.PARAM_MODE;
|
||||
import static google.registry.rde.RdeModule.PARAM_REVISION;
|
||||
import static google.registry.rde.RdeModule.PARAM_WATERMARKS;
|
||||
import static google.registry.rde.RdeModule.RDE_REPORT_QUEUE;
|
||||
import static google.registry.request.RequestParameters.PARAM_TLDS;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.appengine.api.taskqueue.Queue;
|
||||
import com.google.appengine.api.taskqueue.TaskOptions;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import google.registry.model.rde.RdeMode;
|
||||
import google.registry.rde.RdeStagingAction;
|
||||
import google.registry.request.Action.Service;
|
||||
import google.registry.tools.params.DateTimeParameter;
|
||||
import google.registry.util.AppEngineServiceUtils;
|
||||
import google.registry.util.CloudTasksUtils;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
@@ -94,15 +92,7 @@ final class GenerateEscrowDepositCommand implements CommandWithRemoteApi {
|
||||
|
||||
@Inject AppEngineServiceUtils appEngineServiceUtils;
|
||||
|
||||
@Inject
|
||||
@Named("rde-report")
|
||||
Queue queue;
|
||||
|
||||
// ETA is a required property for TaskOptions but we let the service to set it when submitting the
|
||||
// task to the task queue. However, the local test service doesn't do that for us during the unit
|
||||
// test, so we add this field here to let the unit test be able to inject the ETA to pass the
|
||||
// test.
|
||||
@VisibleForTesting Optional<Long> maybeEtaMillis = Optional.empty();
|
||||
@Inject CloudTasksUtils cloudTasksUtils;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -126,27 +116,25 @@ final class GenerateEscrowDepositCommand implements CommandWithRemoteApi {
|
||||
throw new ParameterException("Output subdirectory must not be empty");
|
||||
}
|
||||
|
||||
// Unlike many tool commands, this command is actually invoking an action on the backend module
|
||||
// (because it's a mapreduce). So we invoke it in a different way.
|
||||
String hostname = appEngineServiceUtils.getCurrentVersionHostname("backend");
|
||||
TaskOptions opts =
|
||||
withUrl(RdeStagingAction.PATH)
|
||||
.header("Host", hostname)
|
||||
.param(PARAM_MANUAL, String.valueOf(true))
|
||||
.param(PARAM_MODE, mode.toString())
|
||||
.param(PARAM_DIRECTORY, outdir)
|
||||
.param(PARAM_LENIENT, Boolean.toString(lenient))
|
||||
.param(PARAM_BEAM, Boolean.toString(beam))
|
||||
.param(PARAM_TLDS, tlds.stream().collect(Collectors.joining(",")))
|
||||
.param(
|
||||
ImmutableMultimap.Builder<String, String> paramsBuilder =
|
||||
new ImmutableMultimap.Builder<String, String>()
|
||||
.put(PARAM_MANUAL, String.valueOf(true))
|
||||
.put(PARAM_MODE, mode.toString())
|
||||
.put(PARAM_DIRECTORY, outdir)
|
||||
.put(PARAM_LENIENT, Boolean.toString(lenient))
|
||||
.put(PARAM_BEAM, Boolean.toString(beam))
|
||||
.put(PARAM_TLDS, tlds.stream().collect(Collectors.joining(",")))
|
||||
.put(
|
||||
PARAM_WATERMARKS,
|
||||
watermarks.stream().map(DateTime::toString).collect(Collectors.joining(",")));
|
||||
|
||||
if (revision != null) {
|
||||
opts = opts.param(PARAM_REVISION, String.valueOf(revision));
|
||||
paramsBuilder.put(PARAM_REVISION, String.valueOf(revision));
|
||||
}
|
||||
if (maybeEtaMillis.isPresent()) {
|
||||
opts = opts.etaMillis(maybeEtaMillis.get());
|
||||
}
|
||||
queue.add(opts);
|
||||
cloudTasksUtils.enqueue(
|
||||
RDE_REPORT_QUEUE,
|
||||
CloudTasksUtils.createPostTask(
|
||||
RdeStagingAction.PATH, Service.BACKEND.toString(), paramsBuilder.build()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
package google.registry.tools;
|
||||
|
||||
import com.beust.jcommander.Parameters;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationStateTransition;
|
||||
import google.registry.model.common.TimedTransitionProperty;
|
||||
|
||||
/** A command to check the current Registry 3.0 migration state of the database. */
|
||||
@DeleteAfterMigration
|
||||
@Parameters(separators = " =", commandDescription = "Check current Registry 3.0 migration state")
|
||||
public class GetDatabaseMigrationStateCommand implements CommandWithRemoteApi {
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ abstract class GetEppResourceCommand implements CommandWithRemoteApi {
|
||||
? String.format(
|
||||
"%s\n\nWebsafe key: %s",
|
||||
expand ? resource.get().toHydratedString() : resource.get(),
|
||||
resource.get().createVKey().getOfyKey().getString())
|
||||
resource.get().createVKey().stringify())
|
||||
: String.format("%s '%s' does not exist or is deleted\n", resourceType, uniqueId));
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ package google.registry.tools;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.collect.Streams;
|
||||
import google.registry.model.tld.label.PremiumList;
|
||||
import google.registry.model.tld.label.PremiumList.PremiumEntry;
|
||||
import google.registry.model.tld.label.PremiumListDao;
|
||||
@@ -40,7 +39,7 @@ public class GetPremiumListCommand implements CommandWithRemoteApi {
|
||||
System.out.printf(
|
||||
"%s:\n%s\n",
|
||||
premiumListName,
|
||||
Streams.stream(PremiumListDao.loadAllPremiumEntries(premiumListName))
|
||||
PremiumListDao.loadAllPremiumEntries(premiumListName).stream()
|
||||
.sorted(Comparator.comparing(PremiumEntry::getDomainLabel))
|
||||
.map(premiumEntry -> premiumEntry.toString(premiumList.get().getCurrency()))
|
||||
.collect(Collectors.joining("\n")));
|
||||
|
||||
@@ -20,12 +20,12 @@ import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command to get info on a Datastore resource by websafe key.
|
||||
*/
|
||||
/** Command to get info on a Datastore resource by websafe key. */
|
||||
@DeleteAfterMigration
|
||||
@Parameters(separators = " =", commandDescription = "Fetch a Datastore resource by websafe key")
|
||||
final class GetResourceByKeyCommand implements CommandWithRemoteApi {
|
||||
|
||||
|
||||
@@ -19,11 +19,13 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import google.registry.model.SchemaVersion;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
/** Generates the schema file used for model versioning. */
|
||||
@DeleteAfterMigration
|
||||
@Parameters(commandDescription = "Generate a model schema file")
|
||||
final class GetSchemaCommand implements Command {
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.VirtualEntity;
|
||||
import java.io.Serializable;
|
||||
@@ -40,6 +41,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/** Visualizes the schema parentage tree. */
|
||||
@DeleteAfterMigration
|
||||
@Parameters(commandDescription = "Generate a model schema file")
|
||||
final class GetSchemaTreeCommand implements Command {
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.google.common.base.Ascii;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.export.datastore.DatastoreAdmin;
|
||||
import google.registry.export.datastore.Operation;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -35,6 +36,7 @@ import org.joda.time.Duration;
|
||||
* href="http://playbooks/domain_registry/procedures/backup-restore-testing.md">the playbook</a> for
|
||||
* the entire process.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
@Parameters(separators = " =", commandDescription = "Imports a backup of the Datastore.")
|
||||
public class ImportDatastoreCommand extends ConfirmingCommand {
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.google.api.client.json.JsonFactory;
|
||||
import com.google.api.client.json.jackson2.JacksonFactory;
|
||||
import google.registry.export.datastore.DatastoreAdmin;
|
||||
import google.registry.export.datastore.DatastoreAdmin.ListOperations;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.util.Clock;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -28,6 +29,7 @@ import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** Command that lists Datastore operations. */
|
||||
@DeleteAfterMigration
|
||||
@Parameters(separators = " =", commandDescription = "List Datastore operations.")
|
||||
public class ListDatastoreOperationsCommand implements Command {
|
||||
|
||||
|
||||
@@ -26,12 +26,14 @@ import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import google.registry.bigquery.BigqueryUtils.SourceFormat;
|
||||
import google.registry.export.AnnotatedEntities;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/** Command to load Datastore snapshots into Bigquery. */
|
||||
@DeleteAfterMigration
|
||||
@Parameters(separators = " =", commandDescription = "Load Datastore snapshot into Bigquery")
|
||||
final class LoadSnapshotCommand extends BigqueryCommand {
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.google.common.io.CharStreams;
|
||||
import com.google.common.io.Files;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.util.NonFinalForTesting;
|
||||
@@ -40,6 +41,7 @@ import java.util.List;
|
||||
* <p>The key path is the value of column __key__.path of the entity's BigQuery table. Its value is
|
||||
* converted from the entity's key.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
abstract class ReadEntityFromKeyPathCommand<T> extends MutatingCommand {
|
||||
|
||||
@Parameter(
|
||||
|
||||
@@ -19,6 +19,7 @@ import dagger.Component;
|
||||
import dagger.Lazy;
|
||||
import google.registry.batch.BatchModule;
|
||||
import google.registry.bigquery.BigqueryModule;
|
||||
import google.registry.config.CloudTasksUtilsModule;
|
||||
import google.registry.config.CredentialModule.LocalCredentialJson;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.config.RegistryConfig.ConfigModule;
|
||||
@@ -64,6 +65,7 @@ import javax.inject.Singleton;
|
||||
BigqueryModule.class,
|
||||
ConfigModule.class,
|
||||
CloudDnsWriterModule.class,
|
||||
CloudTasksUtilsModule.class,
|
||||
DatastoreAdminModule.class,
|
||||
DatastoreServiceModule.class,
|
||||
DummyKeyringModule.class,
|
||||
|
||||
@@ -19,12 +19,14 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
|
||||
import google.registry.tools.params.TransitionListParameter.MigrationStateTransitions;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Command to set the Registry 3.0 database migration state schedule. */
|
||||
@DeleteAfterMigration
|
||||
@Parameters(
|
||||
separators = " =",
|
||||
commandDescription = "Set the current database migration state schedule.")
|
||||
|
||||
@@ -15,21 +15,15 @@
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.model.tld.label.PremiumListUtils.parseToPremiumList;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.util.ListNamingUtils.convertFilePathToName;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import google.registry.model.tld.label.PremiumList;
|
||||
import google.registry.model.tld.label.PremiumList.PremiumEntry;
|
||||
import google.registry.model.tld.label.PremiumListDao;
|
||||
import google.registry.model.tld.label.PremiumListUtils;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/** Command to safely update {@link PremiumList} in Database for a given TLD. */
|
||||
@@ -43,46 +37,12 @@ class UpdatePremiumListCommand extends CreateOrUpdatePremiumListCommand {
|
||||
checkArgument(
|
||||
list.isPresent(),
|
||||
String.format("Could not update premium list %s because it doesn't exist.", name));
|
||||
List<String> existingEntry = getExistingPremiumEntry(list.get()).asList();
|
||||
inputData = Files.readAllLines(inputFile, UTF_8);
|
||||
checkArgument(!inputData.isEmpty(), "New premium list data cannot be empty");
|
||||
currency = list.get().getCurrency();
|
||||
// reconstructing existing premium list to bypass Hibernate lazy initialization exception
|
||||
PremiumList existingPremiumList = parseToPremiumList(name, currency, existingEntry);
|
||||
PremiumList updatedPremiumList = parseToPremiumList(name, currency, inputData);
|
||||
|
||||
PremiumList updatedPremiumList = PremiumListUtils.parseToPremiumList(name, currency, inputData);
|
||||
return String.format(
|
||||
"Update premium list for %s?\n Old List: %s\n New List: %s",
|
||||
name, existingPremiumList, updatedPremiumList);
|
||||
}
|
||||
|
||||
/*
|
||||
To get premium list content as a set of string. This is a workaround to avoid dealing with
|
||||
Hibernate.LazyInitizationException error. It occurs when trying to access data of the
|
||||
latest revision of an existing premium list.
|
||||
"Cannot evaluate google.registry.model.tld.label.PremiumList.toString()'".
|
||||
Ideally, the following should be the way to verify info in latest revision of a premium list:
|
||||
|
||||
PremiumList existingPremiumList =
|
||||
PremiumListSqlDao.getLatestRevision(name)
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new IllegalArgumentException(
|
||||
String.format(
|
||||
"Could not update premium list %s because it doesn't exist.", name)));
|
||||
assertThat(persistedList.getLabelsToPrices()).containsEntry("foo", new BigDecimal("9000.00"));
|
||||
assertThat(persistedList.size()).isEqualTo(1);
|
||||
*/
|
||||
protected ImmutableSet<String> getExistingPremiumEntry(PremiumList list) {
|
||||
|
||||
Iterable<PremiumEntry> sqlListEntries =
|
||||
jpaTm().transact(() -> PremiumListDao.loadPremiumEntries(list));
|
||||
return Streams.stream(sqlListEntries)
|
||||
.map(
|
||||
premiumEntry ->
|
||||
String.format(
|
||||
"%s,%s %s",
|
||||
premiumEntry.getDomainLabel(), list.getCurrency(), premiumEntry.getValue()))
|
||||
.collect(toImmutableSet());
|
||||
name, list, updatedPremiumList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,12 @@
|
||||
"^PRODUCTION|SANDBOX|CRASH|QA|ALPHA$"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "jpaTransactionManagerType",
|
||||
"label": "The type of JPA transaction manager to use",
|
||||
"helpText": "The standard SQL instance or a read-only replica may be used",
|
||||
"regexes": ["^REGULAR|READ_ONLY_REPLICA$"]
|
||||
},
|
||||
{
|
||||
"name": "pendings",
|
||||
"label": "The pendings deposits to generate.",
|
||||
|
||||
@@ -103,7 +103,7 @@ public class AsyncTaskEnqueuerTest {
|
||||
.method("POST")
|
||||
.header("Host", "backend.hostname.fake")
|
||||
.header("content-type", "application/x-www-form-urlencoded")
|
||||
.param(PARAM_RESOURCE_KEY, contact.createVKey().getOfyKey().getString())
|
||||
.param(PARAM_RESOURCE_KEY, contact.createVKey().stringify())
|
||||
.param(PARAM_REQUESTED_TIME, clock.nowUtc().toString())
|
||||
.etaDelta(
|
||||
standardDays(5).minus(standardSeconds(30)),
|
||||
@@ -125,7 +125,7 @@ public class AsyncTaskEnqueuerTest {
|
||||
.method("POST")
|
||||
.header("Host", "backend.hostname.fake")
|
||||
.header("content-type", "application/x-www-form-urlencoded")
|
||||
.param(PARAM_RESOURCE_KEY, contact.createVKey().getOfyKey().getString())
|
||||
.param(PARAM_RESOURCE_KEY, contact.createVKey().stringify())
|
||||
.param(PARAM_REQUESTED_TIME, now.toString())
|
||||
.param(PARAM_RESAVE_TIMES, "2015-05-20T14:34:56.000Z,2015-05-21T15:34:56.000Z")
|
||||
.etaDelta(
|
||||
|
||||
@@ -18,6 +18,7 @@ import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
|
||||
import static com.google.common.collect.MoreCollectors.onlyElement;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
|
||||
import static google.registry.batch.AsyncTaskMetrics.OperationResult.STALE;
|
||||
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||
@@ -496,7 +497,7 @@ public class DeleteContactsAndHostsActionTest
|
||||
QUEUE_ASYNC_DELETE,
|
||||
new TaskMatcher()
|
||||
.etaDelta(standardHours(23), standardHours(25))
|
||||
.param("resourceKey", contactNotSaved.createVKey().getOfyKey().getString())
|
||||
.param(PARAM_RESOURCE_KEY, contactNotSaved.createVKey().stringify())
|
||||
.param("requestingClientId", "TheRegistrar")
|
||||
.param("clientTransactionId", "fakeClientTrid")
|
||||
.param("serverTransactionId", "fakeServerTrid")
|
||||
@@ -504,7 +505,7 @@ public class DeleteContactsAndHostsActionTest
|
||||
.param("requestedTime", timeBeforeRun.toString()),
|
||||
new TaskMatcher()
|
||||
.etaDelta(standardHours(23), standardHours(25))
|
||||
.param("resourceKey", hostNotSaved.createVKey().getOfyKey().getString())
|
||||
.param(PARAM_RESOURCE_KEY, hostNotSaved.createVKey().stringify())
|
||||
.param("requestingClientId", "TheRegistrar")
|
||||
.param("clientTransactionId", "fakeClientTrid")
|
||||
.param("serverTransactionId", "fakeServerTrid")
|
||||
|
||||
@@ -145,7 +145,7 @@ public class RefreshDnsOnHostRenameActionTest
|
||||
assertTasksEnqueued(
|
||||
QUEUE_ASYNC_HOST_RENAME,
|
||||
new TaskMatcher()
|
||||
.param(PARAM_HOST_KEY, host.createVKey().getOfyKey().getString())
|
||||
.param(PARAM_HOST_KEY, host.createVKey().stringify())
|
||||
.param(PARAM_REQUESTED_TIME, timeEnqueued.toString()));
|
||||
verify(action.asyncTaskMetrics).recordDnsRefreshBatchSize(1L);
|
||||
verifyNoMoreInteractions(action.asyncTaskMetrics);
|
||||
@@ -237,7 +237,7 @@ public class RefreshDnsOnHostRenameActionTest
|
||||
QUEUE_ASYNC_HOST_RENAME,
|
||||
new TaskMatcher()
|
||||
.etaDelta(standardHours(23), standardHours(25))
|
||||
.param("hostKey", host.createVKey().getOfyKey().getString()));
|
||||
.param(PARAM_HOST_KEY, host.createVKey().stringify()));
|
||||
assertThat(acquireLock()).isPresent();
|
||||
}
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ public class ResaveEntityActionTest {
|
||||
.method("POST")
|
||||
.header("Host", "backend.hostname.fake")
|
||||
.header("content-type", "application/x-www-form-urlencoded")
|
||||
.param(PARAM_RESOURCE_KEY, resavedDomain.createVKey().getOfyKey().getString())
|
||||
.param(PARAM_RESOURCE_KEY, resavedDomain.createVKey().stringify())
|
||||
.param(PARAM_REQUESTED_TIME, requestedTime.toString())
|
||||
.etaDelta(
|
||||
standardDays(5).minus(standardSeconds(30)),
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.flows;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
|
||||
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
@@ -146,7 +147,7 @@ public abstract class ResourceFlowTestCase<F extends Flow, R extends EppResource
|
||||
TaskMatcher expected =
|
||||
new TaskMatcher()
|
||||
.etaDelta(Duration.standardSeconds(75), Duration.standardSeconds(105)) // expected: 90
|
||||
.param("resourceKey", resource.createVKey().getOfyKey().getString())
|
||||
.param(PARAM_RESOURCE_KEY, resource.createVKey().stringify())
|
||||
.param("requestingClientId", requestingClientId)
|
||||
.param("serverTransactionId", trid.getServerTransactionId())
|
||||
.param("isSuperuser", Boolean.toString(isSuperuser))
|
||||
|
||||
@@ -321,7 +321,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
|
||||
.method("POST")
|
||||
.header("Host", "backend.hostname.fake")
|
||||
.header("content-type", "application/x-www-form-urlencoded")
|
||||
.param(PARAM_RESOURCE_KEY, domain.createVKey().getOfyKey().getString())
|
||||
.param(PARAM_RESOURCE_KEY, domain.createVKey().stringify())
|
||||
.param(PARAM_REQUESTED_TIME, clock.nowUtc().toString())
|
||||
.param(PARAM_RESAVE_TIMES, clock.nowUtc().plusDays(5).toString())
|
||||
.etaDelta(when.minus(standardSeconds(30)), when.plus(standardSeconds(30))));
|
||||
|
||||
@@ -521,7 +521,7 @@ class DomainTransferRequestFlowTest
|
||||
.method("POST")
|
||||
.header("Host", "backend.hostname.fake")
|
||||
.header("content-type", "application/x-www-form-urlencoded")
|
||||
.param(PARAM_RESOURCE_KEY, domain.createVKey().getOfyKey().getString())
|
||||
.param(PARAM_RESOURCE_KEY, domain.createVKey().stringify())
|
||||
.param(PARAM_REQUESTED_TIME, clock.nowUtc().toString())
|
||||
.etaDelta(
|
||||
registry.getAutomaticTransferLength().minus(standardSeconds(30)),
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.flows.host;
|
||||
|
||||
import static com.google.common.base.Strings.nullToEmpty;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_HOST_KEY;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_HOST_RENAME;
|
||||
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
@@ -230,7 +231,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, HostResour
|
||||
assertTasksEnqueued(
|
||||
QUEUE_ASYNC_HOST_RENAME,
|
||||
new TaskMatcher()
|
||||
.param("hostKey", renamedHost.createVKey().getOfyKey().getString())
|
||||
.param(PARAM_HOST_KEY, renamedHost.createVKey().stringify())
|
||||
.param("requestedTime", clock.nowUtc().toString()));
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.model.tld.label;
|
||||
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
@@ -24,14 +25,18 @@ import static org.joda.money.CurrencyUnit.USD;
|
||||
import static org.joda.time.Duration.standardDays;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.persistence.transaction.TransactionManagerUtil;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.TestCacheExtension;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.IntStream;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -41,6 +46,8 @@ import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
/** Unit tests for {@link PremiumListDao}. */
|
||||
public class PremiumListDaoTest {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private final FakeClock fakeClock = new FakeClock();
|
||||
|
||||
@RegisterExtension
|
||||
@@ -260,6 +267,27 @@ public class PremiumListDaoTest {
|
||||
assertThat(PremiumListDao.premiumListCache.getIfPresent("testname")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSave_largeSize_savedQuickly() {
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
ImmutableMap<String, BigDecimal> prices =
|
||||
IntStream.range(0, 20000).boxed().collect(toImmutableMap(String::valueOf, BigDecimal::new));
|
||||
PremiumList list =
|
||||
new PremiumList.Builder()
|
||||
.setName("testname")
|
||||
.setCurrency(USD)
|
||||
.setLabelsToPrices(prices)
|
||||
.setCreationTimestamp(fakeClock.nowUtc())
|
||||
.build();
|
||||
PremiumListDao.save(list);
|
||||
long duration = stopwatch.stop().elapsed(TimeUnit.MILLISECONDS);
|
||||
if (duration >= 6000) {
|
||||
// Don't fail directly since we can't rely on what sort of machines the test is running on
|
||||
logger.atSevere().log(
|
||||
"Expected premium list update to take 2-3 seconds but it took %d ms", duration);
|
||||
}
|
||||
}
|
||||
|
||||
private static Money moneyOf(CurrencyUnit unit, double amount) {
|
||||
return Money.of(unit, BigDecimal.valueOf(amount).setScale(unit.getDecimalPlaces()));
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.googlecode.objectify.annotation.Entity;
|
||||
import google.registry.model.billing.BillingEvent.OneTime;
|
||||
import google.registry.model.common.ClassPathManager;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.TaskQueueHelper.TaskMatcher;
|
||||
@@ -207,6 +208,29 @@ class VKeyTest {
|
||||
.isEqualTo(VKey.createSql(TestObject.class, "foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreate_stringifiedVKey_resourceKeyFromTaskQueue() throws Exception {
|
||||
VKey<HostResource> vkeyFromNewWebsafeKey =
|
||||
VKey.create(
|
||||
"kind:HostResource@sql:rO0ABXQADzZCQjJGNDc2LUdPT0dMRQ@ofy:ahdzfm"
|
||||
+ "RvbWFpbi1yZWdpc3RyeS1hbHBoYXIhCxIMSG9zdFJlc291cmNlIg82QkIyRjQ3Ni1HT09HTEUM");
|
||||
|
||||
assertThat(vkeyFromNewWebsafeKey.getSqlKey()).isEqualTo("6BB2F476-GOOGLE");
|
||||
assertThat(vkeyFromNewWebsafeKey.getOfyKey().getString())
|
||||
.isEqualTo(
|
||||
"ahdzfmRvbWFpb"
|
||||
+ "i1yZWdpc3RyeS1hbHBoYXIhCxIMSG9zdFJlc291cmNlIg82QkIyRjQ3Ni1HT09HTEUM");
|
||||
|
||||
// the ofy portion of the new vkey string representation was the old vkey string representation
|
||||
VKey<HostResource> vkeyFromOldWebsafeString =
|
||||
VKey.fromWebsafeKey(
|
||||
"ahdzfmRvbW"
|
||||
+ "Fpbi1yZWdpc3RyeS1hbHBoYXIhCxIMSG9zdFJlc291cmNlIg82QkIyRjQ3Ni1HT09HTEUM");
|
||||
|
||||
// the following is assertion is ensure backwork compatibility
|
||||
assertThat(vkeyFromNewWebsafeKey).isEqualTo(vkeyFromOldWebsafeString);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreate_stringifedVKey_ofyOnlyVKeyString() {
|
||||
assertThat(VKey.create("kind:TestObject@ofy:agR0ZXN0chMLEgpUZXN0T2JqZWN0IgNmb28M"))
|
||||
|
||||
@@ -60,7 +60,6 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.dns.writer.VoidDnsWriter;
|
||||
@@ -1264,7 +1263,7 @@ public class DatabaseHelper {
|
||||
|
||||
/** Returns the entire map of {@link PremiumEntry}s for the given {@link PremiumList}. */
|
||||
public static ImmutableMap<String, PremiumEntry> loadPremiumEntries(PremiumList premiumList) {
|
||||
return Streams.stream(PremiumListDao.loadAllPremiumEntries(premiumList.getName()))
|
||||
return PremiumListDao.loadAllPremiumEntries(premiumList.getName()).stream()
|
||||
.collect(toImmutableMap(PremiumEntry::getDomainLabel, Function.identity()));
|
||||
}
|
||||
|
||||
|
||||
@@ -14,18 +14,16 @@
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.TaskQueueHelper.assertTasksEnqueued;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.testing.TaskQueueHelper.TaskMatcher;
|
||||
import google.registry.util.AppEngineServiceUtils;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
@@ -42,14 +40,15 @@ public class GenerateEscrowDepositCommandTest
|
||||
|
||||
@Mock AppEngineServiceUtils appEngineServiceUtils;
|
||||
|
||||
CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("tld");
|
||||
createTld("anothertld");
|
||||
command = new GenerateEscrowDepositCommand();
|
||||
command.appEngineServiceUtils = appEngineServiceUtils;
|
||||
command.queue = getQueue("rde-report");
|
||||
command.maybeEtaMillis = Optional.of(fakeClock.nowUtc().getMillis());
|
||||
command.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||
when(appEngineServiceUtils.getCurrentVersionHostname("backend"))
|
||||
.thenReturn("backend.test.localhost");
|
||||
}
|
||||
@@ -197,11 +196,10 @@ public class GenerateEscrowDepositCommandTest
|
||||
"-r 42",
|
||||
"-o test");
|
||||
|
||||
assertTasksEnqueued(
|
||||
cloudTasksHelper.assertTasksEnqueued(
|
||||
"rde-report",
|
||||
new TaskMatcher()
|
||||
.url("/_dr/task/rdeStaging")
|
||||
.header("Host", "backend.test.localhost")
|
||||
.param("mode", "THIN")
|
||||
.param("lenient", "true")
|
||||
.param("watermarks", "2017-01-01T00:00:00.000Z")
|
||||
@@ -221,11 +219,10 @@ public class GenerateEscrowDepositCommandTest
|
||||
"-r 42",
|
||||
"-o test");
|
||||
|
||||
assertTasksEnqueued(
|
||||
cloudTasksHelper.assertTasksEnqueued(
|
||||
"rde-report",
|
||||
new TaskMatcher()
|
||||
.url("/_dr/task/rdeStaging")
|
||||
.header("Host", "backend.test.localhost")
|
||||
.param("mode", "THIN")
|
||||
.param("beam", "true")
|
||||
.param("watermarks", "2017-01-01T00:00:00.000Z")
|
||||
@@ -239,11 +236,10 @@ public class GenerateEscrowDepositCommandTest
|
||||
void testCommand_successWithDefaultValidationMode() throws Exception {
|
||||
runCommand("--tld=tld", "--watermark=2017-01-01T00:00:00Z", "--mode=thin", "-r 42", "-o test");
|
||||
|
||||
assertTasksEnqueued(
|
||||
cloudTasksHelper.assertTasksEnqueued(
|
||||
"rde-report",
|
||||
new TaskMatcher()
|
||||
.url("/_dr/task/rdeStaging")
|
||||
.header("Host", "backend.test.localhost")
|
||||
.param("mode", "THIN")
|
||||
.param("lenient", "false")
|
||||
.param("watermarks", "2017-01-01T00:00:00.000Z")
|
||||
@@ -257,11 +253,10 @@ public class GenerateEscrowDepositCommandTest
|
||||
void testCommand_successWithDefaultRevision() throws Exception {
|
||||
runCommand("--tld=tld", "--watermark=2017-01-01T00:00:00Z", "--mode=thin", "-o test");
|
||||
|
||||
assertTasksEnqueued(
|
||||
cloudTasksHelper.assertTasksEnqueued(
|
||||
"rde-report",
|
||||
new TaskMatcher()
|
||||
.url("/_dr/task/rdeStaging")
|
||||
.header("Host", "backend.test.localhost")
|
||||
.param("lenient", "false")
|
||||
.param("beam", "false")
|
||||
.param("mode", "THIN")
|
||||
@@ -275,11 +270,10 @@ public class GenerateEscrowDepositCommandTest
|
||||
void testCommand_successWithDefaultMode() throws Exception {
|
||||
runCommand("--tld=tld", "--watermark=2017-01-01T00:00:00Z", "-r=42", "-o test");
|
||||
|
||||
assertTasksEnqueued(
|
||||
cloudTasksHelper.assertTasksEnqueued(
|
||||
"rde-report",
|
||||
new TaskMatcher()
|
||||
.url("/_dr/task/rdeStaging")
|
||||
.header("Host", "backend.test.localhost")
|
||||
.param("mode", "FULL")
|
||||
.param("lenient", "false")
|
||||
.param("beam", "false")
|
||||
@@ -299,11 +293,10 @@ public class GenerateEscrowDepositCommandTest
|
||||
"-r 42",
|
||||
"-o test");
|
||||
|
||||
assertTasksEnqueued(
|
||||
cloudTasksHelper.assertTasksEnqueued(
|
||||
"rde-report",
|
||||
new TaskMatcher()
|
||||
.url("/_dr/task/rdeStaging")
|
||||
.header("Host", "backend.test.localhost")
|
||||
.param("mode", "THIN")
|
||||
.param("lenient", "false")
|
||||
.param("beam", "false")
|
||||
|
||||
@@ -42,7 +42,11 @@ class GetContactCommandTest extends CommandTestCase<GetContactCommand> {
|
||||
persistActiveContact("sh8013");
|
||||
runCommand("sh8013");
|
||||
assertInStdout("contactId=sh8013");
|
||||
assertInStdout("Websafe key: agR0ZXN0chsLEg9Db250YWN0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
assertInStdout(
|
||||
"Websafe key: "
|
||||
+ "kind:ContactResource"
|
||||
+ "@sql:rO0ABXQABjItUk9JRA"
|
||||
+ "@ofy:agR0ZXN0chsLEg9Db250YWN0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -50,7 +54,11 @@ class GetContactCommandTest extends CommandTestCase<GetContactCommand> {
|
||||
persistActiveContact("sh8013");
|
||||
runCommand("sh8013", "--expand");
|
||||
assertInStdout("contactId=sh8013");
|
||||
assertInStdout("Websafe key: agR0ZXN0chsLEg9Db250YWN0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
assertInStdout(
|
||||
"Websafe key: "
|
||||
+ "kind:ContactResource"
|
||||
+ "@sql:rO0ABXQABjItUk9JRA"
|
||||
+ "@ofy:agR0ZXN0chsLEg9Db250YWN0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
assertNotInStdout("LiveRef");
|
||||
}
|
||||
|
||||
@@ -61,8 +69,16 @@ class GetContactCommandTest extends CommandTestCase<GetContactCommand> {
|
||||
runCommand("sh8013", "jd1234");
|
||||
assertInStdout("contactId=sh8013");
|
||||
assertInStdout("contactId=jd1234");
|
||||
assertInStdout("Websafe key: agR0ZXN0chsLEg9Db250YWN0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
assertInStdout("Websafe key: agR0ZXN0chsLEg9Db250YWN0UmVzb3VyY2UiBjMtUk9JRAw");
|
||||
assertInStdout(
|
||||
"Websafe key: "
|
||||
+ "kind:ContactResource"
|
||||
+ "@sql:rO0ABXQABjItUk9JRA"
|
||||
+ "@ofy:agR0ZXN0chsLEg9Db250YWN0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
assertInStdout(
|
||||
"Websafe key: "
|
||||
+ "kind:ContactResource"
|
||||
+ "@sql:rO0ABXQABjItUk9JRA"
|
||||
+ "@ofy:agR0ZXN0chsLEg9Db250YWN0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -43,7 +43,11 @@ class GetDomainCommandTest extends CommandTestCase<GetDomainCommand> {
|
||||
runCommand("example.tld");
|
||||
assertInStdout("fullyQualifiedDomainName=example.tld");
|
||||
assertInStdout("contact=Key<?>(ContactResource(\"3-ROID\"))");
|
||||
assertInStdout("Websafe key: agR0ZXN0chULEgpEb21haW5CYXNlIgUyLVRMRAw");
|
||||
assertInStdout(
|
||||
"Websafe key: "
|
||||
+ "kind:DomainBase"
|
||||
+ "@sql:rO0ABXQABTItVExE"
|
||||
+ "@ofy:agR0ZXN0chULEgpEb21haW5CYXNlIgUyLVRMRAw");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -52,7 +56,11 @@ class GetDomainCommandTest extends CommandTestCase<GetDomainCommand> {
|
||||
runCommand("example.tld", "--expand");
|
||||
assertInStdout("fullyQualifiedDomainName=example.tld");
|
||||
assertInStdout("contactId=contact1234");
|
||||
assertInStdout("Websafe key: agR0ZXN0chULEgpEb21haW5CYXNlIgUyLVRMRAw");
|
||||
assertInStdout(
|
||||
"Websafe key: "
|
||||
+ "kind:DomainBase"
|
||||
+ "@sql:rO0ABXQABTItVExE"
|
||||
+ "@ofy:agR0ZXN0chULEgpEb21haW5CYXNlIgUyLVRMRAw");
|
||||
assertNotInStdout("LiveRef");
|
||||
}
|
||||
|
||||
@@ -63,8 +71,16 @@ class GetDomainCommandTest extends CommandTestCase<GetDomainCommand> {
|
||||
runCommand("example.tld", "example2.tld");
|
||||
assertInStdout("fullyQualifiedDomainName=example.tld");
|
||||
assertInStdout("fullyQualifiedDomainName=example2.tld");
|
||||
assertInStdout("Websafe key: agR0ZXN0chULEgpEb21haW5CYXNlIgUyLVRMRAw");
|
||||
assertInStdout("Websafe key: agR0ZXN0chULEgpEb21haW5CYXNlIgU0LVRMRAw");
|
||||
assertInStdout(
|
||||
"Websafe key: "
|
||||
+ "kind:DomainBase"
|
||||
+ "@sql:rO0ABXQABTQtVExE"
|
||||
+ "@ofy:agR0ZXN0chULEgpEb21haW5CYXNlIgU0LVRMRAw");
|
||||
assertInStdout(
|
||||
"Websafe key: "
|
||||
+ "kind:DomainBase"
|
||||
+ "@sql:rO0ABXQABTQtVExE"
|
||||
+ "@ofy:agR0ZXN0chULEgpEb21haW5CYXNlIgU0LVRMRAw");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -42,7 +42,11 @@ class GetHostCommandTest extends CommandTestCase<GetHostCommand> {
|
||||
persistActiveHost("ns1.example.tld");
|
||||
runCommand("ns1.example.tld");
|
||||
assertInStdout("fullyQualifiedHostName=ns1.example.tld");
|
||||
assertInStdout("Websafe key: agR0ZXN0chgLEgxIb3N0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
assertInStdout(
|
||||
"Websafe key: "
|
||||
+ "kind:HostResource"
|
||||
+ "@sql:rO0ABXQABjItUk9JRA"
|
||||
+ "@ofy:agR0ZXN0chgLEgxIb3N0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -50,7 +54,11 @@ class GetHostCommandTest extends CommandTestCase<GetHostCommand> {
|
||||
persistActiveHost("ns1.example.tld");
|
||||
runCommand("ns1.example.tld", "--expand");
|
||||
assertInStdout("fullyQualifiedHostName=ns1.example.tld");
|
||||
assertInStdout("Websafe key: agR0ZXN0chgLEgxIb3N0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
assertInStdout(
|
||||
"Websafe key: "
|
||||
+ "kind:HostResource"
|
||||
+ "@sql:rO0ABXQABjItUk9JRA"
|
||||
+ "@ofy:agR0ZXN0chgLEgxIb3N0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
assertNotInStdout("LiveRef");
|
||||
}
|
||||
|
||||
@@ -61,8 +69,16 @@ class GetHostCommandTest extends CommandTestCase<GetHostCommand> {
|
||||
runCommand("ns1.example.tld", "ns2.example.tld");
|
||||
assertInStdout("fullyQualifiedHostName=ns1.example.tld");
|
||||
assertInStdout("fullyQualifiedHostName=ns2.example.tld");
|
||||
assertInStdout("Websafe key: agR0ZXN0chgLEgxIb3N0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
assertInStdout("Websafe key: agR0ZXN0chgLEgxIb3N0UmVzb3VyY2UiBjMtUk9JRAw");
|
||||
assertInStdout(
|
||||
"Websafe key: "
|
||||
+ "kind:HostResource"
|
||||
+ "@sql:rO0ABXQABjItUk9JRA"
|
||||
+ "@ofy:agR0ZXN0chgLEgxIb3N0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
assertInStdout(
|
||||
"Websafe key: "
|
||||
+ "kind:HostResource"
|
||||
+ "@sql:rO0ABXQABjItUk9JRA"
|
||||
+ "@ofy:agR0ZXN0chgLEgxIb3N0UmVzb3VyY2UiBjItUk9JRAw");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -52,6 +52,26 @@ class ResaveEntitiesCommandTest extends CommandTestCase<ResaveEntitiesCommand> {
|
||||
.containsExactlyElementsIn(auditedOfy().load().entities(contact1, contact2).values());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_createsCommitLogs_withNewWebsafeKey() throws Exception {
|
||||
ContactResource contact1 = persistActiveContact("contact1");
|
||||
ContactResource contact2 = persistActiveContact("contact2");
|
||||
deleteEntitiesOfTypes(CommitLogManifest.class, CommitLogMutation.class);
|
||||
assertThat(auditedOfy().load().type(CommitLogManifest.class).keys()).isEmpty();
|
||||
assertThat(auditedOfy().load().type(CommitLogMutation.class).keys()).isEmpty();
|
||||
runCommandForced(contact1.createVKey().stringify(), contact2.createVKey().stringify());
|
||||
|
||||
assertThat(auditedOfy().load().type(CommitLogManifest.class).keys()).hasSize(1);
|
||||
Iterable<ImmutableObject> savedEntities =
|
||||
transform(
|
||||
auditedOfy().load().type(CommitLogMutation.class).list(),
|
||||
mutation -> auditedOfy().load().fromEntity(mutation.getEntity()));
|
||||
// Reload the contacts before asserting, since their update times will have changed.
|
||||
auditedOfy().clearSessionCache();
|
||||
assertThat(savedEntities)
|
||||
.containsExactlyElementsIn(auditedOfy().load().entities(contact1, contact2).values());
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private static void deleteEntitiesOfTypes(Class<? extends ImmutableObject>... types) {
|
||||
for (Class<? extends ImmutableObject> type : types) {
|
||||
|
||||
@@ -14,17 +14,20 @@
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ImmutableObjectSubject.immutableObjectCorrespondence;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.joda.money.CurrencyUnit.USD;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.io.Files;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.tld.label.PremiumList;
|
||||
import google.registry.model.tld.label.PremiumList.PremiumEntry;
|
||||
import google.registry.model.tld.label.PremiumListDao;
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Optional;
|
||||
@@ -46,12 +49,10 @@ class UpdatePremiumListCommandTest<C extends UpdatePremiumListCommand>
|
||||
Optional<PremiumList> list = PremiumListDao.getLatestRevision(TLD_TEST);
|
||||
// ensure that no premium list is created before running the command
|
||||
assertThat(list.isPresent()).isTrue();
|
||||
// ensure that there's value in existing premium list;
|
||||
UpdatePremiumListCommand command = new UpdatePremiumListCommand();
|
||||
ImmutableSet<String> entries = command.getExistingPremiumEntry(list.get());
|
||||
assertThat(entries.size()).isEqualTo(1);
|
||||
// data from @beforeEach of CreateOrUpdatePremiumListCommandTestCase.java
|
||||
assertThat(entries.contains("doge,USD 9090.00")).isTrue();
|
||||
assertThat(PremiumListDao.loadPremiumEntries(list.get()))
|
||||
.comparingElementsUsing(immutableObjectCorrespondence("revisionId"))
|
||||
.containsExactly(PremiumEntry.create(0L, new BigDecimal("9090.00"), "doge"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -77,11 +78,9 @@ class UpdatePremiumListCommandTest<C extends UpdatePremiumListCommand>
|
||||
command.inputFile = Paths.get(tmpFile.getPath());
|
||||
runCommandForced("--name=" + TLD_TEST, "--input=" + command.inputFile);
|
||||
|
||||
ImmutableSet<String> entries =
|
||||
command.getExistingPremiumEntry(PremiumListDao.getLatestRevision(TLD_TEST).get());
|
||||
assertThat(entries.size()).isEqualTo(1);
|
||||
// verify that list is updated; cannot use only string since price is formatted;
|
||||
assertThat(entries.contains("eth,USD 9999.00")).isTrue();
|
||||
assertThat(PremiumListDao.loadAllPremiumEntries(TLD_TEST))
|
||||
.comparingElementsUsing(immutableObjectCorrespondence("revisionId"))
|
||||
.containsExactly(PremiumEntry.create(0L, new BigDecimal("9999.00"), "eth"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -98,11 +97,9 @@ class UpdatePremiumListCommandTest<C extends UpdatePremiumListCommand>
|
||||
command.inputFile = Paths.get(newPremiumFile.getPath());
|
||||
runCommandForced("--name=" + TLD_TEST, "--input=" + command.inputFile);
|
||||
|
||||
ImmutableSet<String> entries =
|
||||
command.getExistingPremiumEntry(PremiumListDao.getLatestRevision(TLD_TEST).get());
|
||||
assertThat(entries.size()).isEqualTo(1);
|
||||
// verify that list is updated; cannot use only string since price is formatted;
|
||||
assertThat(entries.contains("eth,USD 9999.00")).isTrue();
|
||||
assertThat(PremiumListDao.loadAllPremiumEntries(TLD_TEST))
|
||||
.comparingElementsUsing(immutableObjectCorrespondence("revisionId"))
|
||||
.containsExactly(PremiumEntry.create(0L, new BigDecimal("9999.00"), "eth"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -116,12 +113,11 @@ class UpdatePremiumListCommandTest<C extends UpdatePremiumListCommand>
|
||||
runCommandForced("--name=" + TLD_TEST, "--input=" + command.inputFile);
|
||||
|
||||
// assert all three lines from premiumTerms are added
|
||||
ImmutableSet<String> entries =
|
||||
command.getExistingPremiumEntry(PremiumListDao.getLatestRevision(TLD_TEST).get());
|
||||
assertThat(entries.size()).isEqualTo(3);
|
||||
assertThat(entries.contains("foo,USD 9000.00")).isTrue();
|
||||
assertThat(entries.contains("doge,USD 100.00")).isTrue();
|
||||
assertThat(entries.contains("elon,USD 2021.00")).isTrue();
|
||||
assertThat(
|
||||
PremiumListDao.loadAllPremiumEntries(TLD_TEST).stream()
|
||||
.map(Object::toString)
|
||||
.collect(toImmutableList()))
|
||||
.containsExactly("foo, 9000.00", "doge, 100.00", "elon, 2021.00");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -19,11 +19,21 @@
|
||||
# expanded in the copies sent to Spinnaker, we preserve the brackets around
|
||||
# them for safe pattern matching during release.
|
||||
# See https://github.com/spinnaker/spinnaker/issues/3028 for more information.
|
||||
steps:
|
||||
# Delete unused GAE versions.
|
||||
#
|
||||
# GAE has a limit of ~250 versions per-project, including unused versions. We
|
||||
# therefore need to periodically delete old versions. This GCB job finds all
|
||||
# stopped versions and delete all but the last 3 (in case we need to rollback).
|
||||
steps:
|
||||
# Pull the credential for nomulus tool.
|
||||
- name: 'gcr.io/$PROJECT_ID/builder:latest'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
gcloud secrets versions access latest \
|
||||
--secret nomulus-tool-cloudbuild-credential > tool-credential.json
|
||||
# Delete unused GAE versions.
|
||||
- name: 'gcr.io/$PROJECT_ID/builder:latest'
|
||||
entrypoint: /bin/bash
|
||||
args:
|
||||
@@ -36,6 +46,8 @@ steps:
|
||||
project_id="domain-registry-${_ENV}"
|
||||
fi
|
||||
|
||||
gcloud auth activate-service-account --key-file=tool-credential.json
|
||||
|
||||
for service in default pubapi backend tools
|
||||
do
|
||||
for version in $(gcloud app versions list \
|
||||
|
||||
Reference in New Issue
Block a user