mirror of
https://github.com/google/nomulus.git
synced 2025-05-03 13:37:51 +02:00
Preserve update_time when replicating to SQL (#1316)
* Preserve update_time when replicating to SQL Prevent InitSqlPipeline from changing the UpdateAutoTimestamp fields in entities.
This commit is contained in:
parent
ac21ee4151
commit
0fe2e6c976
3 changed files with 35 additions and 4 deletions
|
@ -22,6 +22,8 @@ import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Streams;
|
import com.google.common.collect.Streams;
|
||||||
import google.registry.backup.AppEngineEnvironment;
|
import google.registry.backup.AppEngineEnvironment;
|
||||||
import google.registry.beam.common.RegistryQuery.CriteriaQuerySupplier;
|
import google.registry.beam.common.RegistryQuery.CriteriaQuerySupplier;
|
||||||
|
import google.registry.model.UpdateAutoTimestamp;
|
||||||
|
import google.registry.model.UpdateAutoTimestamp.DisableAutoUpdateResource;
|
||||||
import google.registry.model.ofy.ObjectifyService;
|
import google.registry.model.ofy.ObjectifyService;
|
||||||
import google.registry.model.replay.SqlEntity;
|
import google.registry.model.replay.SqlEntity;
|
||||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||||
|
@ -274,6 +276,12 @@ public final class RegistryJpaIO {
|
||||||
|
|
||||||
public abstract SerializableFunction<T, Object> jpaConverter();
|
public abstract SerializableFunction<T, Object> jpaConverter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal to the writer that the {@link UpdateAutoTimestamp} property should be allowed to
|
||||||
|
* manipulate its value before persistence. The default value is {@code true}.
|
||||||
|
*/
|
||||||
|
abstract boolean withUpdateAutoTimestamp();
|
||||||
|
|
||||||
public Write<T> withName(String name) {
|
public Write<T> withName(String name) {
|
||||||
return toBuilder().name(name).build();
|
return toBuilder().name(name).build();
|
||||||
}
|
}
|
||||||
|
@ -294,6 +302,10 @@ public final class RegistryJpaIO {
|
||||||
return toBuilder().jpaConverter(jpaConverter).build();
|
return toBuilder().jpaConverter(jpaConverter).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Write<T> disableUpdateAutoTimestamp() {
|
||||||
|
return toBuilder().withUpdateAutoTimestamp(false).build();
|
||||||
|
}
|
||||||
|
|
||||||
abstract Builder<T> toBuilder();
|
abstract Builder<T> toBuilder();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -310,7 +322,7 @@ public final class RegistryJpaIO {
|
||||||
GroupIntoBatches.<Integer, T>ofSize(batchSize()).withShardedKey())
|
GroupIntoBatches.<Integer, T>ofSize(batchSize()).withShardedKey())
|
||||||
.apply(
|
.apply(
|
||||||
"Write in batch for " + name(),
|
"Write in batch for " + name(),
|
||||||
ParDo.of(new SqlBatchWriter<>(name(), jpaConverter())));
|
ParDo.of(new SqlBatchWriter<>(name(), jpaConverter(), withUpdateAutoTimestamp())));
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T> Builder<T> builder() {
|
static <T> Builder<T> builder() {
|
||||||
|
@ -318,7 +330,8 @@ public final class RegistryJpaIO {
|
||||||
.name(DEFAULT_NAME)
|
.name(DEFAULT_NAME)
|
||||||
.batchSize(DEFAULT_BATCH_SIZE)
|
.batchSize(DEFAULT_BATCH_SIZE)
|
||||||
.shards(DEFAULT_SHARDS)
|
.shards(DEFAULT_SHARDS)
|
||||||
.jpaConverter(x -> x);
|
.jpaConverter(x -> x)
|
||||||
|
.withUpdateAutoTimestamp(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AutoValue.Builder
|
@AutoValue.Builder
|
||||||
|
@ -332,6 +345,8 @@ public final class RegistryJpaIO {
|
||||||
|
|
||||||
abstract Builder<T> jpaConverter(SerializableFunction<T, Object> jpaConverter);
|
abstract Builder<T> jpaConverter(SerializableFunction<T, Object> jpaConverter);
|
||||||
|
|
||||||
|
abstract Builder<T> withUpdateAutoTimestamp(boolean withUpdateAutoTimestamp);
|
||||||
|
|
||||||
abstract Write<T> build();
|
abstract Write<T> build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,10 +355,13 @@ public final class RegistryJpaIO {
|
||||||
private static class SqlBatchWriter<T> extends DoFn<KV<ShardedKey<Integer>, Iterable<T>>, Void> {
|
private static class SqlBatchWriter<T> extends DoFn<KV<ShardedKey<Integer>, Iterable<T>>, Void> {
|
||||||
private final Counter counter;
|
private final Counter counter;
|
||||||
private final SerializableFunction<T, Object> jpaConverter;
|
private final SerializableFunction<T, Object> jpaConverter;
|
||||||
|
private final boolean withAutoTimestamp;
|
||||||
|
|
||||||
SqlBatchWriter(String type, SerializableFunction<T, Object> jpaConverter) {
|
SqlBatchWriter(
|
||||||
|
String type, SerializableFunction<T, Object> jpaConverter, boolean withAutoTimestamp) {
|
||||||
counter = Metrics.counter("SQL_WRITE", type);
|
counter = Metrics.counter("SQL_WRITE", type);
|
||||||
this.jpaConverter = jpaConverter;
|
this.jpaConverter = jpaConverter;
|
||||||
|
this.withAutoTimestamp = withAutoTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Setup
|
@Setup
|
||||||
|
@ -358,6 +376,16 @@ public final class RegistryJpaIO {
|
||||||
|
|
||||||
@ProcessElement
|
@ProcessElement
|
||||||
public void processElement(@Element KV<ShardedKey<Integer>, Iterable<T>> kv) {
|
public void processElement(@Element KV<ShardedKey<Integer>, Iterable<T>> kv) {
|
||||||
|
if (withAutoTimestamp) {
|
||||||
|
actuallyProcessElement(kv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try (DisableAutoUpdateResource disable = UpdateAutoTimestamp.disableAutoUpdate()) {
|
||||||
|
actuallyProcessElement(kv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void actuallyProcessElement(@Element KV<ShardedKey<Integer>, Iterable<T>> kv) {
|
||||||
try (AppEngineEnvironment env = new AppEngineEnvironment()) {
|
try (AppEngineEnvironment env = new AppEngineEnvironment()) {
|
||||||
ImmutableList<Object> entities =
|
ImmutableList<Object> entities =
|
||||||
Streams.stream(kv.getValue())
|
Streams.stream(kv.getValue())
|
||||||
|
|
|
@ -219,7 +219,8 @@ public class InitSqlPipeline implements Serializable {
|
||||||
.withName(transformId)
|
.withName(transformId)
|
||||||
.withBatchSize(options.getSqlWriteBatchSize())
|
.withBatchSize(options.getSqlWriteBatchSize())
|
||||||
.withShards(options.getSqlWriteShards())
|
.withShards(options.getSqlWriteShards())
|
||||||
.withJpaConverter(Transforms::convertVersionedEntityToSqlEntity));
|
.withJpaConverter(Transforms::convertVersionedEntityToSqlEntity)
|
||||||
|
.disableUpdateAutoTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ImmutableList<String> toKindStrings(Collection<Class<?>> entityClasses) {
|
private static ImmutableList<String> toKindStrings(Collection<Class<?>> entityClasses) {
|
||||||
|
|
|
@ -306,6 +306,7 @@ class InitSqlPipelineTest {
|
||||||
.build());
|
.build());
|
||||||
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,6 +363,7 @@ class InitSqlPipelineTest {
|
||||||
.isEqualTo(expected.getAutorenewPollMessage().getOfyKey());
|
.isEqualTo(expected.getAutorenewPollMessage().getOfyKey());
|
||||||
assertThat(actual.getDeletePollMessage().getOfyKey())
|
assertThat(actual.getDeletePollMessage().getOfyKey())
|
||||||
.isEqualTo(expected.getDeletePollMessage().getOfyKey());
|
.isEqualTo(expected.getDeletePollMessage().getOfyKey());
|
||||||
|
assertThat(actual.getUpdateTimestamp()).isEqualTo(expected.getUpdateTimestamp());
|
||||||
// TODO(weiminyu): check gracePeriods and transferData when it is easier to do
|
// TODO(weiminyu): check gracePeriods and transferData when it is easier to do
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue