mirror of
https://github.com/google/nomulus.git
synced 2025-07-14 06:55:20 +02:00
Include Cursor in the initial SQL population (#1323)
The test for this also required a bit of a fix in the Cursor scope initialization. If you persist a Key<?> in some object in Datastore, it persists just the standard data you'd expect, basically the parent, the kind, and the object's ID/name. Then, when you load it back in from Datastore it uses the app ID of whatever environment you're loading in (the Key contains this info even though it isn't included in the toString() of Key) If you persist the websafe string format of a Key (which is what we do for Cursors), it includes the app ID so when you load it, it contains the old app ID not the new one (if the app ID has changed). In the pipelines, we use the standard default environment which has a different app ID from the test environment that's set up by the DatastoreEntityExtension. As a result, we should check in Cursor to see if the key is *any* cross-tld-key, rather than the exact one that exists within this app environment.
This commit is contained in:
parent
b4f6280d6f
commit
92b83a9d7a
4 changed files with 574 additions and 431 deletions
|
@ -25,6 +25,7 @@ import google.registry.backup.VersionedEntity;
|
||||||
import google.registry.beam.common.RegistryJpaIO;
|
import google.registry.beam.common.RegistryJpaIO;
|
||||||
import google.registry.beam.initsql.Transforms.RemoveDomainBaseForeignKeys;
|
import google.registry.beam.initsql.Transforms.RemoveDomainBaseForeignKeys;
|
||||||
import google.registry.model.billing.BillingEvent;
|
import google.registry.model.billing.BillingEvent;
|
||||||
|
import google.registry.model.common.Cursor;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.domain.DomainBase;
|
import google.registry.model.domain.DomainBase;
|
||||||
import google.registry.model.domain.token.AllocationToken;
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
|
@ -62,6 +63,7 @@ import org.joda.time.DateTime;
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>{@link Registry}: Assumes that {@code PremiumList} and {@code ReservedList} have been set
|
* <li>{@link Registry}: Assumes that {@code PremiumList} and {@code ReservedList} have been set
|
||||||
* up in the SQL database.
|
* up in the SQL database.
|
||||||
|
* <li>{@link Cursor}: Logically can depend on {@code Registry}, but without foreign key.
|
||||||
* <li>{@link Registrar}: Logically depends on {@code Registry}, Foreign key not modeled yet.
|
* <li>{@link Registrar}: Logically depends on {@code Registry}, Foreign key not modeled yet.
|
||||||
* <li>{@link ContactResource}: references {@code Registrar}
|
* <li>{@link ContactResource}: references {@code Registrar}
|
||||||
* <li>{@link RegistrarContact}: references {@code Registrar}.
|
* <li>{@link RegistrarContact}: references {@code Registrar}.
|
||||||
|
@ -101,7 +103,11 @@ public class InitSqlPipeline implements Serializable {
|
||||||
*/
|
*/
|
||||||
private static final ImmutableList<Class<?>> PHASE_ONE_ORDERED =
|
private static final ImmutableList<Class<?>> PHASE_ONE_ORDERED =
|
||||||
ImmutableList.of(
|
ImmutableList.of(
|
||||||
Registry.class, Registrar.class, ContactResource.class, RegistrarContact.class);
|
Registry.class,
|
||||||
|
Cursor.class,
|
||||||
|
Registrar.class,
|
||||||
|
ContactResource.class,
|
||||||
|
RegistrarContact.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Datastore kinds to be written to the SQL database after the cleansed version of {@link
|
* Datastore kinds to be written to the SQL database after the cleansed version of {@link
|
||||||
|
|
|
@ -220,10 +220,10 @@ public class Cursor extends ImmutableObject implements DatastoreAndSqlEntity {
|
||||||
|
|
||||||
private static String getScopeFromId(String id) {
|
private static String getScopeFromId(String id) {
|
||||||
List<String> idSplit = Splitter.on('_').splitToList(id);
|
List<String> idSplit = Splitter.on('_').splitToList(id);
|
||||||
// The "parent" is always the crossTldKey; in order to find the scope (either Registry or
|
// The key is always either the cross-tld-key or the key of a TLD (whose parent is the
|
||||||
// cross-tld-key) we have to parse the part of the ID
|
// cross-tld-key).
|
||||||
Key<?> scopeKey = Key.valueOf(idSplit.get(0));
|
Key<?> scopeKey = Key.valueOf(idSplit.get(0));
|
||||||
return scopeKey.equals(getCrossTldKey()) ? GLOBAL : scopeKey.getName();
|
return scopeKey.getParent() == null ? GLOBAL : scopeKey.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CursorType getTypeFromId(String id) {
|
private static CursorType getTypeFromId(String id) {
|
||||||
|
|
|
@ -17,6 +17,8 @@ package google.registry.beam.initsql;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||||
import static google.registry.model.ImmutableObjectSubject.immutableObjectCorrespondence;
|
import static google.registry.model.ImmutableObjectSubject.immutableObjectCorrespondence;
|
||||||
|
import static google.registry.model.common.Cursor.CursorType.BRDA;
|
||||||
|
import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING;
|
||||||
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
|
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
|
||||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||||
import static google.registry.testing.DatabaseHelper.newRegistry;
|
import static google.registry.testing.DatabaseHelper.newRegistry;
|
||||||
|
@ -34,6 +36,7 @@ import google.registry.flows.domain.DomainFlowUtils;
|
||||||
import google.registry.model.billing.BillingEvent;
|
import google.registry.model.billing.BillingEvent;
|
||||||
import google.registry.model.billing.BillingEvent.Flag;
|
import google.registry.model.billing.BillingEvent.Flag;
|
||||||
import google.registry.model.billing.BillingEvent.Reason;
|
import google.registry.model.billing.BillingEvent.Reason;
|
||||||
|
import google.registry.model.common.Cursor;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.domain.DesignatedContact;
|
import google.registry.model.domain.DesignatedContact;
|
||||||
import google.registry.model.domain.DomainAuthInfo;
|
import google.registry.model.domain.DomainAuthInfo;
|
||||||
|
@ -86,6 +89,7 @@ class InitSqlPipelineTest {
|
||||||
private static final ImmutableList<Class<?>> ALL_KINDS =
|
private static final ImmutableList<Class<?>> ALL_KINDS =
|
||||||
ImmutableList.of(
|
ImmutableList.of(
|
||||||
Registry.class,
|
Registry.class,
|
||||||
|
Cursor.class,
|
||||||
Registrar.class,
|
Registrar.class,
|
||||||
ContactResource.class,
|
ContactResource.class,
|
||||||
RegistrarContact.class,
|
RegistrarContact.class,
|
||||||
|
@ -131,6 +135,9 @@ class InitSqlPipelineTest {
|
||||||
|
|
||||||
private transient DomainHistory historyEntry;
|
private transient DomainHistory historyEntry;
|
||||||
|
|
||||||
|
private transient Cursor globalCursor;
|
||||||
|
private transient Cursor tldCursor;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void beforeEach() throws Exception {
|
void beforeEach() throws Exception {
|
||||||
try (BackupTestStore store = new BackupTestStore(fakeClock)) {
|
try (BackupTestStore store = new BackupTestStore(fakeClock)) {
|
||||||
|
@ -304,6 +311,8 @@ class InitSqlPipelineTest {
|
||||||
.setRecurringEventKey(recurringBillEvent.createVKey())
|
.setRecurringEventKey(recurringBillEvent.createVKey())
|
||||||
.setParent(historyEntryKey)
|
.setParent(historyEntryKey)
|
||||||
.build());
|
.build());
|
||||||
|
globalCursor = persistResource(Cursor.createGlobal(RECURRING_BILLING, fakeClock.nowUtc()));
|
||||||
|
tldCursor = persistResource(Cursor.create(BRDA, fakeClock.nowUtc(), Registry.get("com")));
|
||||||
exportDir = store.export(exportRootDir.getAbsolutePath(), ALL_KINDS, ImmutableSet.of());
|
exportDir = store.export(exportRootDir.getAbsolutePath(), ALL_KINDS, ImmutableSet.of());
|
||||||
commitLogDir = Files.createDirectory(tmpDir.resolve("commits")).toFile();
|
commitLogDir = Files.createDirectory(tmpDir.resolve("commits")).toFile();
|
||||||
fakeClock.advanceOneMilli();
|
fakeClock.advanceOneMilli();
|
||||||
|
@ -332,6 +341,9 @@ class InitSqlPipelineTest {
|
||||||
.comparingElementsUsing(immutableObjectCorrespondence("revisions", "updateTimestamp"))
|
.comparingElementsUsing(immutableObjectCorrespondence("revisions", "updateTimestamp"))
|
||||||
.containsExactly(contact1, contact2);
|
.containsExactly(contact1, contact2);
|
||||||
assertDomainEquals(jpaTm().transact(() -> jpaTm().loadByKey(domain.createVKey())), domain);
|
assertDomainEquals(jpaTm().transact(() -> jpaTm().loadByKey(domain.createVKey())), domain);
|
||||||
|
assertThat(jpaTm().transact(() -> jpaTm().loadAllOf(Cursor.class)))
|
||||||
|
.comparingElementsUsing(immutableObjectCorrespondence())
|
||||||
|
.containsExactly(globalCursor, tldCursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue