diff --git a/core/src/main/java/google/registry/beam/common/RegistryPipelineComponent.java b/core/src/main/java/google/registry/beam/common/RegistryPipelineComponent.java index f89d11eaa..461461b6a 100644 --- a/core/src/main/java/google/registry/beam/common/RegistryPipelineComponent.java +++ b/core/src/main/java/google/registry/beam/common/RegistryPipelineComponent.java @@ -20,9 +20,7 @@ import dagger.Lazy; import google.registry.config.CredentialModule; import google.registry.config.RegistryConfig.Config; import google.registry.config.RegistryConfig.ConfigModule; -import google.registry.model.domain.Domain; 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; @@ -52,14 +50,6 @@ public interface RegistryPipelineComponent { @BeamJpaTm Lazy getJpaTransactionManager(); - /** - * Returns a {@link JpaTransactionManager} optimized for bulk loading multi-level JPA entities - * ({@link Domain} and {@link google.registry.model.domain.DomainHistory}). Please refer to {@link - * google.registry.model.bulkquery.BulkQueryEntities} for more information. - */ - @BeamBulkQueryJpaTm - Lazy getBulkQueryJpaTransactionManager(); - /** * A {@link JpaTransactionManager} that uses the Postgres read-only replica if configured (uses * the standard DB otherwise). diff --git a/core/src/main/java/google/registry/beam/common/RegistryPipelineWorkerInitializer.java b/core/src/main/java/google/registry/beam/common/RegistryPipelineWorkerInitializer.java index ea6899b68..9a4dea183 100644 --- a/core/src/main/java/google/registry/beam/common/RegistryPipelineWorkerInitializer.java +++ b/core/src/main/java/google/registry/beam/common/RegistryPipelineWorkerInitializer.java @@ -55,9 +55,6 @@ public class RegistryPipelineWorkerInitializer implements JvmInitializer { toRegistryPipelineComponent(registryOptions); Lazy transactionManagerLazy; switch (registryOptions.getJpaTransactionManagerType()) { - case BULK_QUERY: - transactionManagerLazy = registryPipelineComponent.getBulkQueryJpaTransactionManager(); - break; case READ_ONLY_REPLICA: transactionManagerLazy = registryPipelineComponent.getReadOnlyReplicaJpaTransactionManager(); diff --git a/core/src/main/java/google/registry/model/bulkquery/BulkQueryEntities.java b/core/src/main/java/google/registry/model/bulkquery/BulkQueryEntities.java deleted file mode 100644 index 4aaba85a3..000000000 --- a/core/src/main/java/google/registry/model/bulkquery/BulkQueryEntities.java +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2021 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.model.bulkquery; - -import static com.google.common.collect.ImmutableSet.toImmutableSet; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import google.registry.model.domain.Domain; -import google.registry.model.domain.DomainBase; -import google.registry.model.domain.DomainHistory; -import google.registry.model.domain.GracePeriod; -import google.registry.model.domain.GracePeriod.GracePeriodHistory; -import google.registry.model.domain.secdns.DomainDsData; -import google.registry.model.domain.secdns.DomainDsDataHistory; -import google.registry.model.host.Host; -import google.registry.model.reporting.DomainTransactionRecord; -import google.registry.persistence.VKey; -import google.registry.persistence.transaction.JpaTransactionManager; - -/** - * Utilities for managing an alternative JPA entity model optimized for bulk loading multi-level - * entities such as {@link Domain} and {@link DomainHistory}. - * - *

In a bulk query for a multi-level JPA entity type, the JPA framework only generates a bulk - * query (SELECT * FROM table) for the base table. Then, for each row in the base table, additional - * queries are issued to load associated rows in child tables. This can be very slow when an entity - * type has multiple child tables. - * - *

We have defined an alternative entity model for {@link Domain} and {@link DomainHistory}, - * where the base table as well as the child tables are mapped to single-level entity types. The - * idea is to load each of these types using a bulk query, and assemble them into the target type in - * memory in a pipeline. The main use case is Datastore-Cloud SQL validation during the Registry - * database migration, where we will need the full database snapshots frequently. - */ -public class BulkQueryEntities { - /** - * The JPA entity classes in persistence.xml to replace when creating the {@link - * JpaTransactionManager} for bulk query. - */ - public static final ImmutableMap JPA_ENTITIES_REPLACEMENTS = - ImmutableMap.of( - Domain.class.getCanonicalName(), - DomainLite.class.getCanonicalName(), - DomainHistory.class.getCanonicalName(), - DomainHistoryLite.class.getCanonicalName()); - - /* The JPA entity classes that are not included in persistence.xml and need to be added to - * the {@link JpaTransactionManager} for bulk query.*/ - public static final ImmutableList JPA_ENTITIES_NEW = - ImmutableList.of( - DomainHost.class.getCanonicalName(), DomainHistoryHost.class.getCanonicalName()); - - public static Domain assembleDomain( - DomainLite domainLite, - ImmutableSet gracePeriods, - ImmutableSet domainDsData, - ImmutableSet> nsHosts) { - Domain.Builder builder = new Domain.Builder(); - builder.copyFrom(domainLite); - builder.setGracePeriods(gracePeriods); - builder.setDsData(domainDsData); - builder.setNameservers(nsHosts); - // Restore the original update timestamp (this gets cleared when we set nameservers or DS data). - builder.setUpdateTimestamp(domainLite.getUpdateTimestamp()); - return builder.build(); - } - - public static DomainHistory assembleDomainHistory( - DomainHistoryLite domainHistoryLite, - ImmutableSet dsDataHistories, - ImmutableSet> domainHistoryHosts, - ImmutableSet gracePeriodHistories, - ImmutableSet transactionRecords) { - DomainHistory.Builder builder = new DomainHistory.Builder(); - builder.copyFrom(domainHistoryLite); - DomainBase rawDomainBase = domainHistoryLite.domainBase; - if (rawDomainBase != null) { - DomainBase newDomainBase = - domainHistoryLite - .domainBase - .asBuilder() - .setNameservers(domainHistoryHosts) - .setGracePeriods( - gracePeriodHistories.stream() - .map(GracePeriod::createFromHistory) - .collect(toImmutableSet())) - .setDsData( - dsDataHistories.stream().map(DomainDsData::create).collect(toImmutableSet())) - // Restore the original update timestamp (this gets cleared when we set nameservers or - // DS data). - .setUpdateTimestamp(domainHistoryLite.domainBase.getUpdateTimestamp()) - .build(); - builder.setDomain(newDomainBase); - } - return builder.buildAndAssemble( - dsDataHistories, domainHistoryHosts, gracePeriodHistories, transactionRecords); - } -} diff --git a/core/src/main/java/google/registry/model/bulkquery/DomainHistoryHost.java b/core/src/main/java/google/registry/model/bulkquery/DomainHistoryHost.java deleted file mode 100644 index 8b328a26d..000000000 --- a/core/src/main/java/google/registry/model/bulkquery/DomainHistoryHost.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2021 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.model.bulkquery; - -import com.google.common.base.Objects; -import google.registry.model.domain.DomainHistory.DomainHistoryId; -import google.registry.model.host.Host; -import google.registry.persistence.VKey; -import java.io.Serializable; -import javax.persistence.Access; -import javax.persistence.AccessType; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; - -/** - * A name server host referenced by a {@link google.registry.model.domain.DomainHistory} record. - * Please refer to {@link BulkQueryEntities} for usage. - */ -@Entity -@Access(AccessType.FIELD) -@IdClass(DomainHistoryHost.class) -public class DomainHistoryHost implements Serializable { - - @Id private Long domainHistoryHistoryRevisionId; - @Id private String domainHistoryDomainRepoId; - @Id private String hostRepoId; - - private DomainHistoryHost() {} - - public DomainHistoryId getDomainHistoryId() { - return new DomainHistoryId(domainHistoryDomainRepoId, domainHistoryHistoryRevisionId); - } - - public VKey getHostVKey() { - return VKey.create(Host.class, hostRepoId); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof DomainHistoryHost)) { - return false; - } - DomainHistoryHost that = (DomainHistoryHost) o; - return Objects.equal(domainHistoryHistoryRevisionId, that.domainHistoryHistoryRevisionId) - && Objects.equal(domainHistoryDomainRepoId, that.domainHistoryDomainRepoId) - && Objects.equal(hostRepoId, that.hostRepoId); - } - - @Override - public int hashCode() { - return Objects.hashCode(domainHistoryHistoryRevisionId, domainHistoryDomainRepoId, hostRepoId); - } -} diff --git a/core/src/main/java/google/registry/model/bulkquery/DomainHistoryLite.java b/core/src/main/java/google/registry/model/bulkquery/DomainHistoryLite.java deleted file mode 100644 index 65243e8bd..000000000 --- a/core/src/main/java/google/registry/model/bulkquery/DomainHistoryLite.java +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2021 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.model.bulkquery; - -import com.googlecode.objectify.Key; -import google.registry.model.domain.Domain; -import google.registry.model.domain.DomainBase; -import google.registry.model.domain.DomainHistory; -import google.registry.model.domain.DomainHistory.DomainHistoryId; -import google.registry.model.domain.Period; -import google.registry.model.reporting.HistoryEntry; -import google.registry.persistence.VKey; -import javax.annotation.Nullable; -import javax.persistence.Access; -import javax.persistence.AccessType; -import javax.persistence.AttributeOverride; -import javax.persistence.AttributeOverrides; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.persistence.PostLoad; - -/** - * A 'light' version of {@link DomainHistory} with only base table ("DomainHistory") attributes, - * which allows fast bulk loading. They are used in in-memory assembly of {@code DomainHistory} - * instances along with bulk-loaded child entities ({@code GracePeriodHistory} etc). The in-memory - * assembly achieves much higher performance than loading {@code DomainHistory} directly. - * - *

Please refer to {@link BulkQueryEntities} for more information. - * - *

This class is adapted from {@link DomainHistory} by removing the {@code dsDataHistories}, - * {@code gracePeriodHistories}, and {@code nsHosts} fields and associated methods. - */ -@Entity(name = "DomainHistory") -@Access(AccessType.FIELD) -@IdClass(DomainHistoryId.class) -public class DomainHistoryLite extends HistoryEntry { - - // Store DomainBase instead of Domain so we don't pick up its @Id - // Nullable for the sake of pre-Registry-3.0 history objects - @Nullable DomainBase domainBase; - - @Id - @Access(AccessType.PROPERTY) - public String getDomainRepoId() { - // We need to handle null case here because Hibernate sometimes accesses this method before - // parent gets initialized - return parent == null ? null : parent.getName(); - } - - /** This method is private because it is only used by Hibernate. */ - @SuppressWarnings("unused") - private void setDomainRepoId(String domainRepoId) { - parent = Key.create(Domain.class, domainRepoId); - } - - @Override - @Nullable - @Access(AccessType.PROPERTY) - @AttributeOverrides({ - @AttributeOverride(name = "unit", column = @Column(name = "historyPeriodUnit")), - @AttributeOverride(name = "value", column = @Column(name = "historyPeriodValue")) - }) - public Period getPeriod() { - return super.getPeriod(); - } - - /** - * For transfers, the id of the other registrar. - * - *

For requests and cancels, the other registrar is the losing party (because the registrar - * sending the EPP transfer command is the gaining party). For approves and rejects, the other - * registrar is the gaining party. - */ - @Nullable - @Access(AccessType.PROPERTY) - @Column(name = "historyOtherRegistrarId") - @Override - public String getOtherRegistrarId() { - return super.getOtherRegistrarId(); - } - - @Id - @Column(name = "historyRevisionId") - @Access(AccessType.PROPERTY) - @Override - public long getId() { - return super.getId(); - } - - /** The key to the {@link Domain} this is based off of. */ - public VKey getParentVKey() { - return VKey.create(Domain.class, getDomainRepoId()); - } - - public DomainHistoryId getDomainHistoryId() { - return new DomainHistoryId(getDomainRepoId(), getId()); - } - - @PostLoad - void postLoad() { - if (domainBase == null) { - return; - } - // See inline comments in DomainHistory.postLoad for reasons for the following lines. - if (domainBase.getDomainName() == null) { - domainBase = null; - } else if (domainBase.getRepoId() == null) { - domainBase.setRepoId(parent.getName()); - } - } -} diff --git a/core/src/main/java/google/registry/model/bulkquery/DomainHost.java b/core/src/main/java/google/registry/model/bulkquery/DomainHost.java deleted file mode 100644 index a543cfb47..000000000 --- a/core/src/main/java/google/registry/model/bulkquery/DomainHost.java +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2021 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.model.bulkquery; - -import com.google.common.base.Objects; -import google.registry.model.host.Host; -import google.registry.persistence.VKey; -import java.io.Serializable; -import javax.persistence.Access; -import javax.persistence.AccessType; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; - -/** A name server host of a domain. Please refer to {@link BulkQueryEntities} for usage. */ -@Entity -@Access(AccessType.FIELD) -@IdClass(DomainHost.class) -public class DomainHost implements Serializable { - - @Id private String domainRepoId; - - @Id private String hostRepoId; - - DomainHost() {} - - public String getDomainRepoId() { - return domainRepoId; - } - - public VKey getHostVKey() { - return VKey.create(Host.class, hostRepoId); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof DomainHost)) { - return false; - } - DomainHost that = (DomainHost) o; - return Objects.equal(domainRepoId, that.domainRepoId) - && Objects.equal(hostRepoId, that.hostRepoId); - } - - @Override - public int hashCode() { - return Objects.hashCode(domainRepoId, hostRepoId); - } -} diff --git a/core/src/main/java/google/registry/model/bulkquery/DomainLite.java b/core/src/main/java/google/registry/model/bulkquery/DomainLite.java deleted file mode 100644 index a9f436c0d..000000000 --- a/core/src/main/java/google/registry/model/bulkquery/DomainLite.java +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2021 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.model.bulkquery; - -import google.registry.model.domain.Domain; -import google.registry.model.domain.DomainBase; -import google.registry.persistence.VKey; -import google.registry.persistence.WithVKey; -import javax.persistence.Access; -import javax.persistence.AccessType; -import javax.persistence.Entity; - -/** - * A 'light' version of {@link Domain} with only base table ("Domain") attributes, which allows fast - * bulk loading. They are used in in-memory assembly of {@code Domain} instances along with - * bulk-loaded child entities ({@code GracePeriod} etc). The in-memory assembly achieves much higher - * performance than loading {@code Domain} directly. - * - *

Please refer to {@link BulkQueryEntities} for more information. - */ -@Entity(name = "Domain") -@WithVKey(String.class) -@Access(AccessType.FIELD) -public class DomainLite extends DomainBase { - - @Override - @javax.persistence.Id - @Access(AccessType.PROPERTY) - public String getRepoId() { - return super.getRepoId(); - } - - public static VKey createVKey(String repoId) { - return VKey.createSql(DomainLite.class, repoId); - } -} diff --git a/core/src/main/java/google/registry/model/domain/DomainHistory.java b/core/src/main/java/google/registry/model/domain/DomainHistory.java index aa9117ebf..10f1c030c 100644 --- a/core/src/main/java/google/registry/model/domain/DomainHistory.java +++ b/core/src/main/java/google/registry/model/domain/DomainHistory.java @@ -403,19 +403,5 @@ public class DomainHistory extends HistoryEntry { fillAuxiliaryFieldsFromDomain(instance); return instance; } - - public DomainHistory buildAndAssemble( - ImmutableSet dsDataHistories, - ImmutableSet> domainHistoryHosts, - ImmutableSet gracePeriodHistories, - ImmutableSet transactionRecords) { - DomainHistory instance = super.build(); - instance.dsDataHistories = dsDataHistories; - instance.nsHosts = domainHistoryHosts; - instance.gracePeriodHistories = gracePeriodHistories; - instance.domainTransactionRecords = transactionRecords; - instance.hashCode = null; - return instance; - } } } diff --git a/core/src/main/java/google/registry/persistence/BulkQueryJpaFactory.java b/core/src/main/java/google/registry/persistence/BulkQueryJpaFactory.java deleted file mode 100644 index b846cf08c..000000000 --- a/core/src/main/java/google/registry/persistence/BulkQueryJpaFactory.java +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2021 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.persistence; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Streams; -import google.registry.model.bulkquery.BulkQueryEntities; -import google.registry.persistence.transaction.JpaTransactionManager; -import google.registry.persistence.transaction.JpaTransactionManagerImpl; -import google.registry.util.Clock; -import java.util.List; -import javax.persistence.EntityManagerFactory; -import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor; -import org.hibernate.jpa.boot.spi.Bootstrap; - -/** - * Defines factory method for instantiating the bulk-query optimized {@link JpaTransactionManager}. - */ -public final class BulkQueryJpaFactory { - - private BulkQueryJpaFactory() {} - - static EntityManagerFactory createBulkQueryEntityManagerFactory( - ImmutableMap cloudSqlConfigs) { - ParsedPersistenceXmlDescriptor descriptor = - PersistenceXmlUtility.getParsedPersistenceXmlDescriptor(); - - List updatedManagedClasses = - Streams.concat( - descriptor.getManagedClassNames().stream(), - BulkQueryEntities.JPA_ENTITIES_NEW.stream()) - .map( - name -> { - if (BulkQueryEntities.JPA_ENTITIES_REPLACEMENTS.containsKey(name)) { - return BulkQueryEntities.JPA_ENTITIES_REPLACEMENTS.get(name); - } - return name; - }) - .collect(ImmutableList.toImmutableList()); - - descriptor.getManagedClassNames().clear(); - descriptor.getManagedClassNames().addAll(updatedManagedClasses); - - return Bootstrap.getEntityManagerFactoryBuilder(descriptor, cloudSqlConfigs).build(); - } - - public static JpaTransactionManager createBulkQueryJpaTransactionManager( - ImmutableMap cloudSqlConfigs, Clock clock) { - return new JpaTransactionManagerImpl( - createBulkQueryEntityManagerFactory(cloudSqlConfigs), clock); - } -} diff --git a/core/src/main/java/google/registry/persistence/PersistenceModule.java b/core/src/main/java/google/registry/persistence/PersistenceModule.java index bee057e11..62ff1334c 100644 --- a/core/src/main/java/google/registry/persistence/PersistenceModule.java +++ b/core/src/main/java/google/registry/persistence/PersistenceModule.java @@ -241,15 +241,6 @@ public abstract class PersistenceModule { return new JpaTransactionManagerImpl(create(beamCloudSqlConfigs), clock); } - @Provides - @Singleton - @BeamBulkQueryJpaTm - static JpaTransactionManager provideBeamBulkQueryJpaTm( - @BeamPipelineCloudSqlConfigs ImmutableMap beamCloudSqlConfigs, Clock clock) { - return new JpaTransactionManagerImpl( - BulkQueryJpaFactory.createBulkQueryEntityManagerFactory(beamCloudSqlConfigs), clock); - } - @Provides @Singleton @NomulusToolJpaTm @@ -371,11 +362,6 @@ public abstract class PersistenceModule { public enum JpaTransactionManagerType { /** The regular {@link JpaTransactionManager} for general use. */ REGULAR, - /** - * The {@link JpaTransactionManager} optimized for bulk loading multi-level JPA entities. Please - * see {@link google.registry.model.bulkquery.BulkQueryEntities} for more information. - */ - BULK_QUERY, /** * The {@link JpaTransactionManager} that uses the read-only Postgres replica if configured, or * the standard DB if not. @@ -398,14 +384,6 @@ public abstract class PersistenceModule { @Documented public @interface BeamJpaTm {} - /** - * Dagger qualifier for {@link JpaTransactionManager} that uses an alternative entity model for - * faster bulk queries. - */ - @Qualifier - @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). diff --git a/core/src/test/java/google/registry/beam/common/RegistryPipelineOptionsTest.java b/core/src/test/java/google/registry/beam/common/RegistryPipelineOptionsTest.java index fc8d981e6..e5c61ef4d 100644 --- a/core/src/test/java/google/registry/beam/common/RegistryPipelineOptionsTest.java +++ b/core/src/test/java/google/registry/beam/common/RegistryPipelineOptionsTest.java @@ -145,16 +145,4 @@ class RegistryPipelineOptionsTest { .as(RegistryPipelineOptions.class); assertThat(options.getJpaTransactionManagerType()).isEqualTo(JpaTransactionManagerType.REGULAR); } - - @Test - void jpaTransactionManagerType_bulkQueryJpa() { - RegistryPipelineOptions options = - PipelineOptionsFactory.fromArgs( - "--registryEnvironment=" + RegistryEnvironment.UNITTEST.name(), - "--jpaTransactionManagerType=BULK_QUERY") - .withValidation() - .as(RegistryPipelineOptions.class); - assertThat(options.getJpaTransactionManagerType()) - .isEqualTo(JpaTransactionManagerType.BULK_QUERY); - } } diff --git a/core/src/test/java/google/registry/model/bulkquery/BulkQueryHelper.java b/core/src/test/java/google/registry/model/bulkquery/BulkQueryHelper.java deleted file mode 100644 index ad9ff4a4b..000000000 --- a/core/src/test/java/google/registry/model/bulkquery/BulkQueryHelper.java +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2021 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.model.bulkquery; - -import static com.google.common.collect.ImmutableSet.toImmutableSet; -import static google.registry.model.bulkquery.BulkQueryEntities.assembleDomain; -import static google.registry.model.bulkquery.BulkQueryEntities.assembleDomainHistory; -import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; - -import google.registry.model.domain.Domain; -import google.registry.model.domain.DomainHistory; -import google.registry.model.domain.DomainHistory.DomainHistoryId; -import google.registry.model.domain.GracePeriod; -import google.registry.model.domain.GracePeriod.GracePeriodHistory; -import google.registry.model.domain.secdns.DomainDsData; -import google.registry.model.domain.secdns.DomainDsDataHistory; -import google.registry.model.reporting.DomainTransactionRecord; -import google.registry.persistence.VKey; - -/** - * Helpers for bulk-loading {@link Domain} and {@link google.registry.model.domain.DomainHistory} - * entities in tests. - */ -public class BulkQueryHelper { - - static Domain loadAndAssembleDomain(String domainRepoId) { - return jpaTm() - .transact( - () -> - assembleDomain( - jpaTm().loadByKey(DomainLite.createVKey(domainRepoId)), - jpaTm() - .loadAllOfStream(GracePeriod.class) - .filter(gracePeriod -> gracePeriod.getDomainRepoId().equals(domainRepoId)) - .collect(toImmutableSet()), - jpaTm() - .loadAllOfStream(DomainDsData.class) - .filter(dsData -> dsData.getDomainRepoId().equals(domainRepoId)) - .collect(toImmutableSet()), - jpaTm() - .loadAllOfStream(DomainHost.class) - .filter(domainHost -> domainHost.getDomainRepoId().equals(domainRepoId)) - .map(DomainHost::getHostVKey) - .collect(toImmutableSet()))); - } - - static DomainHistory loadAndAssembleDomainHistory(DomainHistoryId domainHistoryId) { - return jpaTm() - .transact( - () -> - assembleDomainHistory( - jpaTm().loadByKey(VKey.createSql(DomainHistoryLite.class, domainHistoryId)), - jpaTm() - .loadAllOfStream(DomainDsDataHistory.class) - .filter( - domainDsDataHistory -> - domainDsDataHistory.getDomainHistoryId().equals(domainHistoryId)) - .collect(toImmutableSet()), - jpaTm() - .loadAllOfStream(DomainHistoryHost.class) - .filter( - domainHistoryHost -> - domainHistoryHost.getDomainHistoryId().equals(domainHistoryId)) - .map(DomainHistoryHost::getHostVKey) - .collect(toImmutableSet()), - jpaTm() - .loadAllOfStream(GracePeriodHistory.class) - .filter( - gracePeriodHistory -> - gracePeriodHistory.getDomainHistoryId().equals(domainHistoryId)) - .collect(toImmutableSet()), - jpaTm() - .loadAllOfStream(DomainTransactionRecord.class) - .filter(x -> true) - .collect(toImmutableSet()))); - } -} diff --git a/core/src/test/java/google/registry/model/bulkquery/DomainHistoryLiteTest.java b/core/src/test/java/google/registry/model/bulkquery/DomainHistoryLiteTest.java deleted file mode 100644 index db9ed65d9..000000000 --- a/core/src/test/java/google/registry/model/bulkquery/DomainHistoryLiteTest.java +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2021 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.model.bulkquery; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; -import static org.joda.time.DateTimeZone.UTC; - -import com.google.common.collect.Sets; -import com.google.common.collect.Sets.SetView; -import com.google.common.truth.Truth8; -import google.registry.model.domain.DomainHistory; -import google.registry.testing.AppEngineExtension; -import google.registry.testing.FakeClock; -import java.util.Set; -import java.util.stream.Collectors; -import javax.persistence.metamodel.Attribute; -import org.joda.time.DateTime; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -/** Unit tests for {@link DomainHistoryLite}. */ -public class DomainHistoryLiteTest { - - protected FakeClock fakeClock = new FakeClock(DateTime.now(UTC)); - - @RegisterExtension - public final AppEngineExtension appEngine = - AppEngineExtension.builder().withCloudSql().withClock(fakeClock).build(); - - private final TestSetupHelper setupHelper = new TestSetupHelper(fakeClock); - - @BeforeEach - void setUp() { - setupHelper.initializeAllEntities(); - } - - @AfterEach - void afterEach() { - setupHelper.tearDownBulkQueryJpaTm(); - } - - @Test - void readDomainHistoryHost() { - setupHelper.applyChangeToDomainAndHistory(); - setupHelper.setupBulkQueryJpaTm(appEngine); - Truth8.assertThat( - jpaTm().transact(() -> jpaTm().loadAllOf(DomainHistoryHost.class)).stream() - .map(DomainHistoryHost::getHostVKey)) - .containsExactly(setupHelper.host.createVKey()); - } - - @Test - void domainHistoryLiteAttributes_versusDomainHistory() { - Set domainHistoryAttributes = - jpaTm() - .transact( - () -> - jpaTm() - .getEntityManager() - .getMetamodel() - .entity(DomainHistory.class) - .getAttributes()) - .stream() - .map(Attribute::getName) - .collect(Collectors.toSet()); - setupHelper.setupBulkQueryJpaTm(appEngine); - Set domainHistoryLiteAttributes = - jpaTm() - .transact( - () -> - jpaTm() - .getEntityManager() - .getMetamodel() - .entity(DomainHistoryLite.class) - .getAttributes()) - .stream() - .map(Attribute::getName) - .collect(Collectors.toSet()); - - assertThat(domainHistoryAttributes).containsAtLeastElementsIn(domainHistoryLiteAttributes); - - SetView excludedFromDomainHistory = - Sets.difference(domainHistoryAttributes, domainHistoryLiteAttributes); - assertThat(excludedFromDomainHistory) - .containsExactly( - "dsDataHistories", - "gracePeriodHistories", - "internalDomainTransactionRecords", - "nsHosts"); - } - - @Test - void readDomainHistory_noContent() { - setupHelper.setupBulkQueryJpaTm(appEngine); - assertThat( - BulkQueryHelper.loadAndAssembleDomainHistory( - setupHelper.domainHistory.getDomainHistoryId())) - .isEqualTo(setupHelper.domainHistory); - } - - @Test - void readDomainHistory_full() { - setupHelper.applyChangeToDomainAndHistory(); - setupHelper.setupBulkQueryJpaTm(appEngine); - assertThat( - BulkQueryHelper.loadAndAssembleDomainHistory( - setupHelper.domainHistory.getDomainHistoryId())) - .isEqualTo(setupHelper.domainHistory); - } -} diff --git a/core/src/test/java/google/registry/model/bulkquery/DomainLiteTest.java b/core/src/test/java/google/registry/model/bulkquery/DomainLiteTest.java deleted file mode 100644 index a8a5c5569..000000000 --- a/core/src/test/java/google/registry/model/bulkquery/DomainLiteTest.java +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2021 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.model.bulkquery; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.model.bulkquery.BulkQueryHelper.loadAndAssembleDomain; -import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; -import static org.joda.time.DateTimeZone.UTC; - -import com.google.common.collect.Sets; -import com.google.common.collect.Sets.SetView; -import com.google.common.truth.Truth8; -import google.registry.model.domain.Domain; -import google.registry.testing.AppEngineExtension; -import google.registry.testing.FakeClock; -import java.util.Set; -import java.util.stream.Collectors; -import javax.persistence.metamodel.Attribute; -import org.joda.time.DateTime; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -/** Unit tests for reading {@link DomainLite}. */ -class DomainLiteTest { - - protected FakeClock fakeClock = new FakeClock(DateTime.now(UTC)); - - @RegisterExtension - public final AppEngineExtension appEngine = - AppEngineExtension.builder().withCloudSql().withClock(fakeClock).build(); - - private final TestSetupHelper setupHelper = new TestSetupHelper(fakeClock); - - @BeforeEach - void setUp() { - setupHelper.initializeAllEntities(); - } - - @AfterEach - void afterEach() { - setupHelper.tearDownBulkQueryJpaTm(); - } - - @Test - void readDomainHost() { - setupHelper.applyChangeToDomainAndHistory(); - setupHelper.setupBulkQueryJpaTm(appEngine); - Truth8.assertThat( - jpaTm().transact(() -> jpaTm().loadAllOf(DomainHost.class)).stream() - .map(DomainHost::getHostVKey)) - .containsExactly(setupHelper.host.createVKey()); - } - - @Test - void domainLiteAttributes_versusDomain() { - Set domainAttributes = - jpaTm() - .transact( - () -> - jpaTm().getEntityManager().getMetamodel().entity(Domain.class).getAttributes()) - .stream() - .map(Attribute::getName) - .collect(Collectors.toSet()); - setupHelper.setupBulkQueryJpaTm(appEngine); - Set domainLiteAttributes = - jpaTm() - .transact( - () -> - jpaTm() - .getEntityManager() - .getMetamodel() - .entity(DomainLite.class) - .getAttributes()) - .stream() - .map(Attribute::getName) - .collect(Collectors.toSet()); - - assertThat(domainAttributes).containsAtLeastElementsIn(domainLiteAttributes); - - SetView excludedFromDomain = Sets.difference(domainAttributes, domainLiteAttributes); - assertThat(excludedFromDomain) - .containsExactly("internalDelegationSignerData", "internalGracePeriods", "nsHosts"); - } - - @Test - void readDomainLite_simple() { - setupHelper.setupBulkQueryJpaTm(appEngine); - assertThat(loadAndAssembleDomain(TestSetupHelper.DOMAIN_REPO_ID)).isEqualTo(setupHelper.domain); - } - - @Test - void readDomainLite_full() { - setupHelper.applyChangeToDomainAndHistory(); - setupHelper.setupBulkQueryJpaTm(appEngine); - assertThat(loadAndAssembleDomain(TestSetupHelper.DOMAIN_REPO_ID)).isEqualTo(setupHelper.domain); - } -} diff --git a/core/src/test/java/google/registry/model/bulkquery/TestSetupHelper.java b/core/src/test/java/google/registry/model/bulkquery/TestSetupHelper.java deleted file mode 100644 index e5ad5062a..000000000 --- a/core/src/test/java/google/registry/model/bulkquery/TestSetupHelper.java +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2021 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.model.bulkquery; - -import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; -import static google.registry.testing.SqlHelper.saveRegistrar; -import static google.registry.util.DateTimeUtils.END_OF_TIME; -import static google.registry.util.DateTimeUtils.START_OF_TIME; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.base.Ascii; -import com.google.common.collect.ImmutableSet; -import google.registry.model.contact.Contact; -import google.registry.model.domain.DesignatedContact; -import google.registry.model.domain.Domain; -import google.registry.model.domain.DomainAuthInfo; -import google.registry.model.domain.DomainHistory; -import google.registry.model.domain.GracePeriod; -import google.registry.model.domain.Period; -import google.registry.model.domain.launch.LaunchNotice; -import google.registry.model.domain.rgp.GracePeriodStatus; -import google.registry.model.domain.secdns.DomainDsData; -import google.registry.model.eppcommon.AuthInfo.PasswordAuth; -import google.registry.model.eppcommon.StatusValue; -import google.registry.model.eppcommon.Trid; -import google.registry.model.host.Host; -import google.registry.model.registrar.Registrar; -import google.registry.model.reporting.DomainTransactionRecord; -import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField; -import google.registry.model.reporting.HistoryEntry; -import google.registry.model.tld.Registry; -import google.registry.model.transfer.ContactTransferData; -import google.registry.persistence.BulkQueryJpaFactory; -import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension; -import google.registry.persistence.transaction.JpaTransactionManager; -import google.registry.persistence.transaction.TransactionManagerFactory; -import google.registry.testing.AppEngineExtension; -import google.registry.testing.DatabaseHelper; -import google.registry.testing.FakeClock; - -/** - * Utilities for managing domain-related SQL test scenarios. - * - *

The {@link #initializeAllEntities} method initializes the database, and the {@link - * #applyChangeToDomainAndHistory} makes one change to the domain, generating an additional history - * event. The most up-to-date values of the relevant entities are saved in public instance - * variables, {@link #domain} etc. - * - *

This class makes use of {@link DatabaseHelper}, which requires Datastore. Tests that use this - * class should use {@link AppEngineExtension}. - */ -public final class TestSetupHelper { - - public static final String TLD = "tld"; - public static final String DOMAIN_REPO_ID = "4-TLD"; - public static final String DOMAIN_NAME = "example.tld"; - public static final String REGISTRAR_ID = "AnRegistrar"; - - private final FakeClock fakeClock; - - public Registry registry; - public Registrar registrar; - public Contact contact; - public Domain domain; - public DomainHistory domainHistory; - public Host host; - - private JpaTransactionManager originalJpaTm; - private JpaTransactionManager bulkQueryJpaTm; - - public TestSetupHelper(FakeClock fakeClock) { - this.fakeClock = fakeClock; - } - - public void initializeAllEntities() { - registry = putInDb(DatabaseHelper.newRegistry(TLD, Ascii.toUpperCase(TLD))); - registrar = saveRegistrar(REGISTRAR_ID); - contact = putInDb(createContact(DOMAIN_REPO_ID, REGISTRAR_ID)); - domain = putInDb(createSimpleDomain(contact)); - domainHistory = putInDb(createHistoryWithoutContent(domain, fakeClock)); - host = putInDb(createHost()); - } - - public void applyChangeToDomainAndHistory() { - domain = putInDb(createFullDomain(contact, host, fakeClock)); - domainHistory = putInDb(createFullHistory(domain, fakeClock)); - } - - public void setupBulkQueryJpaTm(AppEngineExtension appEngineExtension) { - bulkQueryJpaTm = - BulkQueryJpaFactory.createBulkQueryJpaTransactionManager( - appEngineExtension - .getJpaIntegrationTestExtension() - .map(JpaIntegrationTestExtension::getJpaProperties) - .orElseThrow( - () -> new IllegalStateException("Expecting JpaIntegrationTestExtension.")), - fakeClock); - originalJpaTm = TransactionManagerFactory.jpaTm(); - TransactionManagerFactory.setJpaTm(() -> bulkQueryJpaTm); - } - - public void tearDownBulkQueryJpaTm() { - if (bulkQueryJpaTm != null) { - bulkQueryJpaTm.teardown(); - TransactionManagerFactory.setJpaTm(() -> originalJpaTm); - } - } - - static Contact createContact(String repoId, String registrarId) { - return new Contact.Builder() - .setRepoId(repoId) - .setCreationRegistrarId(registrarId) - .setTransferData(new ContactTransferData.Builder().build()) - .setPersistedCurrentSponsorRegistrarId(registrarId) - .build(); - } - - static Domain createSimpleDomain(Contact contact) { - return DatabaseHelper.newDomain(DOMAIN_NAME, DOMAIN_REPO_ID, contact) - .asBuilder() - .setCreationRegistrarId(REGISTRAR_ID) - .setPersistedCurrentSponsorRegistrarId(REGISTRAR_ID) - .build(); - } - - static Domain createFullDomain(Contact contact, Host host, FakeClock fakeClock) { - return createSimpleDomain(contact) - .asBuilder() - .setDomainName(DOMAIN_NAME) - .setRepoId(DOMAIN_REPO_ID) - .setCreationRegistrarId(REGISTRAR_ID) - .setLastEppUpdateTime(fakeClock.nowUtc()) - .setLastEppUpdateRegistrarId(REGISTRAR_ID) - .setLastTransferTime(fakeClock.nowUtc()) - .setNameservers(host.createVKey()) - .setStatusValues( - ImmutableSet.of( - StatusValue.CLIENT_DELETE_PROHIBITED, - StatusValue.SERVER_DELETE_PROHIBITED, - StatusValue.SERVER_TRANSFER_PROHIBITED, - StatusValue.SERVER_UPDATE_PROHIBITED, - StatusValue.SERVER_RENEW_PROHIBITED, - StatusValue.SERVER_HOLD)) - .setContacts( - ImmutableSet.of( - DesignatedContact.create(DesignatedContact.Type.ADMIN, contact.createVKey()))) - .setSubordinateHosts(ImmutableSet.of("ns1.example.com")) - .setPersistedCurrentSponsorRegistrarId(REGISTRAR_ID) - .setRegistrationExpirationTime(fakeClock.nowUtc().plusYears(1)) - .setAuthInfo(DomainAuthInfo.create(PasswordAuth.create("password"))) - .setDsData(ImmutableSet.of(DomainDsData.create(1, 2, 3, new byte[] {0, 1, 2}))) - .setLaunchNotice(LaunchNotice.create("tcnid", "validatorId", START_OF_TIME, START_OF_TIME)) - .setSmdId("smdid") - .addGracePeriod( - GracePeriod.create( - GracePeriodStatus.ADD, DOMAIN_REPO_ID, END_OF_TIME, REGISTRAR_ID, null, 100L)) - .build(); - } - - static Host createHost() { - return new Host.Builder() - .setRepoId("host1") - .setHostName("ns1.example.com") - .setCreationRegistrarId(REGISTRAR_ID) - .setPersistedCurrentSponsorRegistrarId(REGISTRAR_ID) - .build(); - } - - static DomainTransactionRecord createDomainTransactionRecord(FakeClock fakeClock) { - return new DomainTransactionRecord.Builder() - .setTld(TLD) - .setReportingTime(fakeClock.nowUtc()) - .setReportField(TransactionReportField.NET_ADDS_1_YR) - .setReportAmount(1) - .build(); - } - - static DomainHistory createHistoryWithoutContent(Domain domain, FakeClock fakeClock) { - return new DomainHistory.Builder() - .setType(HistoryEntry.Type.DOMAIN_CREATE) - .setXmlBytes("".getBytes(UTF_8)) - .setModificationTime(fakeClock.nowUtc()) - .setRegistrarId(REGISTRAR_ID) - .setTrid(Trid.create("ABC-123", "server-trid")) - .setBySuperuser(false) - .setReason("reason") - .setRequestedByRegistrar(true) - .setDomainRepoId(domain.getRepoId()) - .setOtherRegistrarId("otherClient") - .setPeriod(Period.create(1, Period.Unit.YEARS)) - .build(); - } - - static DomainHistory createFullHistory(Domain domain, FakeClock fakeClock) { - return createHistoryWithoutContent(domain, fakeClock) - .asBuilder() - .setType(HistoryEntry.Type.DOMAIN_TRANSFER_APPROVE) - .setDomain(domain) - .setDomainTransactionRecords(ImmutableSet.of(createDomainTransactionRecord(fakeClock))) - .build(); - } - - static T putInDb(T entity) { - jpaTm().transact(() -> jpaTm().put(entity)); - return jpaTm().transact(() -> jpaTm().loadByEntity(entity)); - } -}