Save indexes when replaying EppResources SQL->DS (#1300)

* Save indexes when replaying EppResources SQL->DS

We implement this similarly to how we implement the
beforeSqlSaveOnReplay callback in the other direction -- a
beforeDatastoreSaveOnReplay method that is called when replaying a
Mutation to Datastore. This means that the asynchronous replay will
create the relevant ForeignKeyIndex and EppResourceIndex objects for
EppResources saved when SQL is primary.
This commit is contained in:
gbrodman
2021-08-25 14:44:44 -06:00
committed by GitHub
parent 5b41f0b9b6
commit 2641d0d462
12 changed files with 159 additions and 41 deletions
@@ -20,6 +20,7 @@ import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.union;
import static google.registry.config.RegistryConfig.getEppResourceCachingDuration;
import static google.registry.config.RegistryConfig.getEppResourceMaxCachedEntries;
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
@@ -37,6 +38,8 @@ import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Index;
import google.registry.config.RegistryConfig;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.index.EppResourceIndex;
import google.registry.model.index.ForeignKeyIndex;
import google.registry.model.ofy.CommitLogManifest;
import google.registry.model.transfer.TransferData;
import google.registry.persistence.VKey;
@@ -219,6 +222,14 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
@Override
public abstract Builder<?, ?> asBuilder();
/** Used when replaying from SQL to DS to populate the Datastore indexes. */
protected void saveIndexesToDatastore() {
ofyTm()
.putAll(
ForeignKeyIndex.create(this, getDeletionTime()),
EppResourceIndex.create(Key.create(this)));
}
/** EppResources that are loaded via foreign keys should implement this marker interface. */
public interface ForeignKeyedEppResource {}
@@ -66,6 +66,11 @@ public class ContactResource extends ContactBase
return ContactBase.cloneContactProjectedAtTime(this, now);
}
@Override
public void beforeDatastoreSaveOnReplay() {
saveIndexesToDatastore();
}
@Override
public Builder asBuilder() {
return new Builder(clone(this));
@@ -163,6 +163,11 @@ public class DomainBase extends DomainContent
return cloneDomainProjectedAtTime(this, now);
}
@Override
public void beforeDatastoreSaveOnReplay() {
saveIndexesToDatastore();
}
public static VKey<DomainBase> createVKey(Key<DomainBase> key) {
return VKey.create(DomainBase.class, key.getName(), key);
}
@@ -51,6 +51,11 @@ public class HostResource extends HostBase
return VKey.create(HostResource.class, getRepoId(), Key.create(this));
}
@Override
public void beforeDatastoreSaveOnReplay() {
saveIndexesToDatastore();
}
@Override
public Builder asBuilder() {
return new Builder(clone(this));
@@ -27,4 +27,7 @@ import java.util.Optional;
public interface DatastoreEntity {
Optional<SqlEntity> toSqlEntity();
/** A method called before the object is saved to Datastore in asynchronous replay. */
default void beforeDatastoreSaveOnReplay() {}
}
@@ -29,10 +29,10 @@ public interface SqlEntity {
Optional<DatastoreEntity> toDatastoreEntity();
/** A method that will ber called before the object is saved to SQL in asynchronous replay. */
/** A method that will be called before the object is saved to SQL in asynchronous replay. */
default void beforeSqlSaveOnReplay() {}
/* Returns this entity's primary key field(s) in a string. */
/** Returns this entity's primary key field(s) in a string. */
default String getPrimaryKeyString() {
return jpaTm()
.transact(
@@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList;
import com.google.storage.onestore.v3.OnestoreEntity.EntityProto;
import google.registry.model.Buildable;
import google.registry.model.ImmutableObject;
import google.registry.model.replay.DatastoreEntity;
import google.registry.model.replay.SqlEntity;
import google.registry.persistence.VKey;
import java.io.ByteArrayInputStream;
@@ -237,6 +238,10 @@ public class Transaction extends ImmutableObject implements Buildable {
@Override
public void writeToDatastore() {
// this should always be the case, but check just in case
if (entity instanceof DatastoreEntity) {
((DatastoreEntity) entity).beforeDatastoreSaveOnReplay();
}
ofyTm().put(entity);
}