mirror of
https://github.com/google/nomulus
synced 2026-08-27 19:37:07 +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:
@@ -44,6 +44,7 @@ import google.registry.model.server.Lock;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.JpaTransactionManagerImpl;
|
||||
import google.registry.persistence.transaction.TransactionEntity;
|
||||
import google.registry.persistence.transaction.TransactionManagerFactory;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
@@ -52,6 +53,7 @@ import google.registry.testing.InjectExtension;
|
||||
import google.registry.testing.ReplayExtension;
|
||||
import google.registry.testing.TestObject;
|
||||
import google.registry.util.RequestStatusChecker;
|
||||
import google.registry.util.SystemClock;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
@@ -105,6 +107,7 @@ public class ReplicateToDatastoreActionTest {
|
||||
void tearDown() {
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
fakeClock.disableAutoIncrement();
|
||||
TransactionManagerFactory.setClockForTesting(new SystemClock());
|
||||
}
|
||||
|
||||
@RetryingTest(4)
|
||||
@@ -392,6 +395,50 @@ public class ReplicateToDatastoreActionTest {
|
||||
+ " DATASTORE_PRIMARY.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void replicationWorksInReadOnly() {
|
||||
|
||||
// Put us in SQL primary now, readonly in an hour, then in datastore primary after 25 hours.
|
||||
// And we'll need the TransactionManagerFactory to use the fake clock.
|
||||
DateTime now = fakeClock.nowUtc();
|
||||
TransactionManagerFactory.setClockForTesting(fakeClock);
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
DatabaseMigrationStateSchedule.set(
|
||||
ImmutableSortedMap.<DateTime, MigrationState>naturalOrder()
|
||||
.put(START_OF_TIME, MigrationState.DATASTORE_ONLY)
|
||||
.put(START_OF_TIME.plusHours(1), MigrationState.DATASTORE_PRIMARY)
|
||||
.put(START_OF_TIME.plusHours(2), MigrationState.DATASTORE_PRIMARY_NO_ASYNC)
|
||||
.put(START_OF_TIME.plusHours(3), MigrationState.DATASTORE_PRIMARY_READ_ONLY)
|
||||
.put(START_OF_TIME.plusHours(4), MigrationState.SQL_PRIMARY_READ_ONLY)
|
||||
.put(START_OF_TIME.plusHours(5), MigrationState.SQL_PRIMARY)
|
||||
.put(now.plusHours(1), MigrationState.SQL_PRIMARY_READ_ONLY)
|
||||
.put(now.plusHours(25), MigrationState.DATASTORE_PRIMARY_READ_ONLY)
|
||||
.put(now.plusHours(26), MigrationState.DATASTORE_PRIMARY_READ_ONLY)
|
||||
.build()));
|
||||
|
||||
TestObject foo = TestObject.create("foo");
|
||||
insertInDb(foo);
|
||||
TestObject bar = TestObject.create("bar");
|
||||
insertInDb(bar);
|
||||
TestObject baz = TestObject.create("baz");
|
||||
insertInDb(baz);
|
||||
jpaTm().transact(() -> jpaTm().delete(baz.key()));
|
||||
|
||||
// get to read-only
|
||||
fakeClock.advanceBy(Duration.standardDays(1));
|
||||
|
||||
// process the transaction in readonly.
|
||||
action.run();
|
||||
|
||||
// Forward the next day (datastore primary). Verify that datastore has all of the changes.
|
||||
fakeClock.advanceBy(Duration.standardDays(1));
|
||||
assertThat(ofyTm().transact(() -> ofyTm().loadByKey(foo.key()))).isEqualTo(foo);
|
||||
assertThat(ofyTm().transact(() -> ofyTm().loadByKey(bar.key()))).isEqualTo(bar);
|
||||
assertThat(ofyTm().transact(() -> ofyTm().loadByKeyIfPresent(baz.key()).isPresent())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_cannotAcquireLock() {
|
||||
assumeTrue(ReplayExtension.replayTestsEnabled());
|
||||
|
||||
Reference in New Issue
Block a user