mirror of
https://github.com/google/nomulus
synced 2026-08-15 11:46:08 +00:00
Ignore read-only when saving commit logs (#1584)
* Ignore read-only when saving commit logs Ignore read-only when saving commit logs and commit log mutations so that we can safely replicate in read-only mode. This should be safe, as we only ever to the situation of saving commit logs and mutations when something has already actually been modified in a transaction, meaning that we should have hit the "read only" sentinel already. This also introduces the ability to set the Clock in the TransactionManagerFactory so that we can test this functionality. * Changes per review * Fix issues affecting tests - Restore clobbered async phase in testNoInMigrationState_doesNothing - Restore system clock to TransactionManagerFactory to avoid affecting other tests.
This commit is contained in:
@@ -69,7 +69,7 @@ public class CommitLogMutation extends ImmutableObject implements DatastoreOnlyE
|
||||
* converted to a raw Datastore Entity, serialized to bytes, and stored within the mutation.
|
||||
*/
|
||||
public static CommitLogMutation create(Key<CommitLogManifest> parent, Object entity) {
|
||||
return createFromRaw(parent, auditedOfy().save().toEntity(entity));
|
||||
return createFromRaw(parent, auditedOfy().saveIgnoringReadOnlyWithBackup().toEntity(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -156,7 +156,7 @@ public class CommitLoggedWork<R> implements Runnable {
|
||||
.map(entity -> (ImmutableObject) CommitLogMutation.create(manifestKey, entity))
|
||||
.collect(toImmutableSet());
|
||||
auditedOfy()
|
||||
.saveWithoutBackup()
|
||||
.saveIgnoringReadOnlyWithoutBackup()
|
||||
.entities(
|
||||
new ImmutableSet.Builder<>()
|
||||
.add(manifest)
|
||||
|
||||
+14
-5
@@ -17,7 +17,6 @@ package google.registry.persistence.transaction;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState.DATASTORE_PRIMARY_NO_ASYNC;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import com.google.appengine.api.utils.SystemProperty;
|
||||
import com.google.appengine.api.utils.SystemProperty.Environment.Value;
|
||||
@@ -30,10 +29,11 @@ import google.registry.model.common.DatabaseMigrationStateSchedule.PrimaryDataba
|
||||
import google.registry.model.ofy.DatastoreTransactionManager;
|
||||
import google.registry.persistence.DaggerPersistenceComponent;
|
||||
import google.registry.tools.RegistryToolEnvironment;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.NonFinalForTesting;
|
||||
import google.registry.util.SystemClock;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Factory class to create {@link TransactionManager} instance. */
|
||||
// TODO: Rename this to PersistenceFactory and move to persistence package.
|
||||
@@ -44,6 +44,9 @@ public final class TransactionManagerFactory {
|
||||
/** Optional override to manually set the transaction manager per-test. */
|
||||
private static Optional<TransactionManager> tmForTest = Optional.empty();
|
||||
|
||||
/** The current clock (defined as a variable so we can override it in tests) */
|
||||
private static Clock clock = new SystemClock();
|
||||
|
||||
/** Supplier for jpaTm so that it is initialized only once, upon first usage. */
|
||||
@NonFinalForTesting
|
||||
private static Supplier<JpaTransactionManager> jpaTm =
|
||||
@@ -105,7 +108,7 @@ public final class TransactionManagerFactory {
|
||||
if (onBeam) {
|
||||
return jpaTm();
|
||||
}
|
||||
return DatabaseMigrationStateSchedule.getValueAtTime(DateTime.now(UTC))
|
||||
return DatabaseMigrationStateSchedule.getValueAtTime(clock.nowUtc())
|
||||
.getPrimaryDatabase()
|
||||
.equals(PrimaryDatabase.DATASTORE)
|
||||
? ofyTm()
|
||||
@@ -195,7 +198,7 @@ public final class TransactionManagerFactory {
|
||||
}
|
||||
|
||||
public static void assertNotReadOnlyMode() {
|
||||
if (DatabaseMigrationStateSchedule.getValueAtTime(DateTime.now(UTC)).isReadOnly()) {
|
||||
if (DatabaseMigrationStateSchedule.getValueAtTime(clock.nowUtc()).isReadOnly()) {
|
||||
throw new ReadOnlyModeException();
|
||||
}
|
||||
}
|
||||
@@ -210,12 +213,18 @@ public final class TransactionManagerFactory {
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public static void assertAsyncActionsAreAllowed() {
|
||||
if (DatabaseMigrationStateSchedule.getValueAtTime(DateTime.now(UTC))
|
||||
if (DatabaseMigrationStateSchedule.getValueAtTime(clock.nowUtc())
|
||||
.equals(DATASTORE_PRIMARY_NO_ASYNC)) {
|
||||
throw new ReadOnlyModeException();
|
||||
}
|
||||
}
|
||||
|
||||
/** Allows us to set the clock used by the factory in unit tests. */
|
||||
@VisibleForTesting
|
||||
public static void setClockForTesting(Clock clock) {
|
||||
TransactionManagerFactory.clock = clock;
|
||||
}
|
||||
|
||||
/** Registry is currently undergoing maintenance and is in read-only mode. */
|
||||
public static class ReadOnlyModeException extends IllegalStateException {
|
||||
public ReadOnlyModeException() {
|
||||
|
||||
Reference in New Issue
Block a user