Embed a ZonedDateTime as the UpdateAutoTimestamp in SQL (#1033)

* Embed a ZonedDateTime as the UpdateAutoTimestamp in SQL

This means we can get rid of the converter and more importantly, means
that reading the object from SQL does not affect the last-read time (the
test added to UpdateAutoTimestampTest failed prior to the production
code change).

For now we keep both time fields in UpdateAutoTimestamp however
post-migration, we can remove the joda-time field if we wish.

Note: I'm not sure why <now> is the time that we started getting
LazyInitializationExceptions in the LegacyHistoryObject and
ReplayExtension tests but we can solve that by just examining /
initializing the object within the transaction.
This commit is contained in:
gbrodman 2021-03-29 11:59:08 -04:00 committed by GitHub
parent 2de27b5716
commit bc4cd573b5
28 changed files with 2875 additions and 2932 deletions

View file

@ -16,6 +16,8 @@ package google.registry.model;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.AttributeOverride;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.xml.bind.annotation.XmlTransient;
@ -40,6 +42,7 @@ public abstract class BackupGroupRoot extends ImmutableObject {
// Prevents subclasses from unexpectedly accessing as property (e.g., HostResource), which would
// require an unnecessary non-private setter method.
@Access(AccessType.FIELD)
@AttributeOverride(name = "lastUpdateTime", column = @Column(name = "updateTimestamp"))
UpdateAutoTimestamp updateTimestamp = UpdateAutoTimestamp.create(null);
/** Get the {@link UpdateAutoTimestamp} for this entity. */

View file

@ -14,11 +14,22 @@
package google.registry.model;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import com.googlecode.objectify.annotation.Ignore;
import com.googlecode.objectify.annotation.OnLoad;
import google.registry.model.translators.UpdateAutoTimestampTranslatorFactory;
import google.registry.util.DateTimeUtils;
import java.time.ZonedDateTime;
import java.util.Optional;
import javax.annotation.Nullable;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.PostLoad;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Transient;
import org.joda.time.DateTime;
/**
@ -26,14 +37,44 @@ import org.joda.time.DateTime;
*
* @see UpdateAutoTimestampTranslatorFactory
*/
@Embeddable
public class UpdateAutoTimestamp extends ImmutableObject {
// When set to true, database converters/translators should do tha auto update. When set to
// When set to true, database converters/translators should do the auto update. When set to
// false, auto update should be suspended (this exists to allow us to preserve the original value
// during a replay).
private static ThreadLocal<Boolean> autoUpdateEnabled = ThreadLocal.withInitial(() -> true);
DateTime timestamp;
@Transient DateTime timestamp;
@Ignore
@Column(nullable = false)
ZonedDateTime lastUpdateTime;
// Unfortunately, we cannot use the @UpdateTimestamp annotation on "lastUpdateTime" in this class
// because Hibernate does not allow it to be used on @Embeddable classes, see
// https://hibernate.atlassian.net/browse/HHH-13235. This is a workaround.
@PrePersist
@PreUpdate
void setTimestamp() {
if (autoUpdateEnabled() || lastUpdateTime == null) {
lastUpdateTime = DateTimeUtils.toZonedDateTime(jpaTm().getTransactionTime());
}
}
@OnLoad
void onLoad() {
if (timestamp != null) {
lastUpdateTime = DateTimeUtils.toZonedDateTime(timestamp);
}
}
@PostLoad
void postLoad() {
if (lastUpdateTime != null) {
timestamp = DateTimeUtils.toJodaDateTime(lastUpdateTime);
}
}
/** Returns the timestamp, or {@code START_OF_TIME} if it's null. */
public DateTime getTimestamp() {
@ -43,6 +84,7 @@ public class UpdateAutoTimestamp extends ImmutableObject {
public static UpdateAutoTimestamp create(@Nullable DateTime timestamp) {
UpdateAutoTimestamp instance = new UpdateAutoTimestamp();
instance.timestamp = timestamp;
instance.lastUpdateTime = timestamp == null ? null : DateTimeUtils.toZonedDateTime(timestamp);
return instance;
}

View file

@ -51,10 +51,8 @@ public final class RegistryLockDao {
return ImmutableList.copyOf(
jpaTm()
.query(
"SELECT lock FROM RegistryLock lock"
+ " WHERE lock.registrarId = :registrarId"
+ " AND lock.unlockCompletionTimestamp IS NULL"
+ " ORDER BY lock.domainName ASC",
"SELECT lock FROM RegistryLock lock WHERE lock.registrarId = :registrarId"
+ " AND lock.unlockCompletionTime IS NULL ORDER BY lock.domainName ASC",
RegistryLock.class)
.setParameter("registrarId", registrarId)
.getResultList());
@ -89,9 +87,8 @@ public final class RegistryLockDao {
return jpaTm()
.query(
"SELECT lock FROM RegistryLock lock WHERE lock.repoId = :repoId AND"
+ " lock.lockCompletionTimestamp IS NOT NULL AND"
+ " lock.unlockCompletionTimestamp IS NULL ORDER BY lock.revisionId"
+ " DESC",
+ " lock.lockCompletionTime IS NOT NULL AND lock.unlockCompletionTime IS NULL"
+ " ORDER BY lock.revisionId DESC",
RegistryLock.class)
.setParameter("repoId", repoId)
.setMaxResults(1)
@ -110,8 +107,7 @@ public final class RegistryLockDao {
return jpaTm()
.query(
"SELECT lock FROM RegistryLock lock WHERE lock.repoId = :repoId AND"
+ " lock.unlockCompletionTimestamp IS NOT NULL ORDER BY lock.revisionId"
+ " DESC",
+ " lock.unlockCompletionTime IS NOT NULL ORDER BY lock.revisionId DESC",
RegistryLock.class)
.setParameter("repoId", repoId)
.setMaxResults(1)

View file

@ -1,53 +0,0 @@
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.persistence.converter;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import google.registry.model.UpdateAutoTimestamp;
import google.registry.util.DateTimeUtils;
import java.sql.Timestamp;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import javax.annotation.Nullable;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
/** JPA converter for storing/retrieving UpdateAutoTimestamp objects. */
@Converter(autoApply = true)
public class UpdateAutoTimestampConverter
implements AttributeConverter<UpdateAutoTimestamp, Timestamp> {
@Override
public Timestamp convertToDatabaseColumn(UpdateAutoTimestamp entity) {
return Timestamp.from(
DateTimeUtils.toZonedDateTime(
UpdateAutoTimestamp.autoUpdateEnabled()
|| entity == null
|| entity.getTimestamp() == null
? jpaTm().getTransactionTime()
: entity.getTimestamp())
.toInstant());
}
@Override
@Nullable
public UpdateAutoTimestamp convertToEntityAttribute(@Nullable Timestamp columnValue) {
if (columnValue == null) {
return null;
}
ZonedDateTime zdt = ZonedDateTime.ofInstant(columnValue.toInstant(), ZoneOffset.UTC);
return UpdateAutoTimestamp.create(DateTimeUtils.toJodaDateTime(zdt));
}
}

View file

@ -102,22 +102,22 @@ public final class RegistryLock extends ImmutableObject implements Buildable, Sq
/** When the lock is first requested. */
@Column(nullable = false)
private CreateAutoTimestamp lockRequestTimestamp = CreateAutoTimestamp.create(null);
private CreateAutoTimestamp lockRequestTime = CreateAutoTimestamp.create(null);
/** When the unlock is first requested. */
private ZonedDateTime unlockRequestTimestamp;
private ZonedDateTime unlockRequestTime;
/**
* When the user has verified the lock. If this field is null, it means the lock has not been
* verified yet (and thus not been put into effect).
*/
private ZonedDateTime lockCompletionTimestamp;
private ZonedDateTime lockCompletionTime;
/**
* When the user has verified the unlock of this lock. If this field is null, it means the unlock
* action has not been verified yet (and has not been put into effect).
*/
private ZonedDateTime unlockCompletionTimestamp;
private ZonedDateTime unlockCompletionTime;
/** The user must provide the random verification code in order to complete the action. */
@Column(nullable = false)
@ -140,7 +140,7 @@ public final class RegistryLock extends ImmutableObject implements Buildable, Sq
private Duration relockDuration;
/** Time that this entity was last updated. */
private UpdateAutoTimestamp lastUpdateTimestamp;
private UpdateAutoTimestamp lastUpdateTime = UpdateAutoTimestamp.create(null);
public String getRepoId() {
return repoId;
@ -158,25 +158,25 @@ public final class RegistryLock extends ImmutableObject implements Buildable, Sq
return registrarPocId;
}
public DateTime getLockRequestTimestamp() {
return lockRequestTimestamp.getTimestamp();
public DateTime getLockRequestTime() {
return lockRequestTime.getTimestamp();
}
/** Returns the unlock request timestamp or null if an unlock has not been requested yet. */
public Optional<DateTime> getUnlockRequestTimestamp() {
return Optional.ofNullable(unlockRequestTimestamp).map(DateTimeUtils::toJodaDateTime);
public Optional<DateTime> getUnlockRequestTime() {
return Optional.ofNullable(unlockRequestTime).map(DateTimeUtils::toJodaDateTime);
}
/** Returns the completion timestamp, or empty if this lock has not been completed yet. */
public Optional<DateTime> getLockCompletionTimestamp() {
return Optional.ofNullable(lockCompletionTimestamp).map(DateTimeUtils::toJodaDateTime);
public Optional<DateTime> getLockCompletionTime() {
return Optional.ofNullable(lockCompletionTime).map(DateTimeUtils::toJodaDateTime);
}
/**
* Returns the unlock completion timestamp, or empty if this unlock has not been completed yet.
*/
public Optional<DateTime> getUnlockCompletionTimestamp() {
return Optional.ofNullable(unlockCompletionTimestamp).map(DateTimeUtils::toJodaDateTime);
public Optional<DateTime> getUnlockCompletionTime() {
return Optional.ofNullable(unlockCompletionTime).map(DateTimeUtils::toJodaDateTime);
}
public String getVerificationCode() {
@ -187,8 +187,8 @@ public final class RegistryLock extends ImmutableObject implements Buildable, Sq
return isSuperuser;
}
public DateTime getLastUpdateTimestamp() {
return lastUpdateTimestamp.getTimestamp();
public DateTime getLastUpdateTime() {
return lastUpdateTime.getTimestamp();
}
public Long getRevisionId() {
@ -211,20 +211,20 @@ public final class RegistryLock extends ImmutableObject implements Buildable, Sq
}
public boolean isLocked() {
return lockCompletionTimestamp != null && unlockCompletionTimestamp == null;
return lockCompletionTime != null && unlockCompletionTime == null;
}
/** Returns true iff the lock was requested &gt;= 1 hour ago and has not been verified. */
public boolean isLockRequestExpired(DateTime now) {
return !getLockCompletionTimestamp().isPresent()
&& isBeforeOrAt(getLockRequestTimestamp(), now.minusHours(1));
return !getLockCompletionTime().isPresent()
&& isBeforeOrAt(getLockRequestTime(), now.minusHours(1));
}
/** Returns true iff the unlock was requested &gt;= 1 hour ago and has not been verified. */
public boolean isUnlockRequestExpired(DateTime now) {
Optional<DateTime> unlockRequestTimestamp = getUnlockRequestTimestamp();
Optional<DateTime> unlockRequestTimestamp = getUnlockRequestTime();
return unlockRequestTimestamp.isPresent()
&& !getUnlockCompletionTimestamp().isPresent()
&& !getUnlockCompletionTime().isPresent()
&& isBeforeOrAt(unlockRequestTimestamp.get(), now.minusHours(1));
}
@ -278,18 +278,18 @@ public final class RegistryLock extends ImmutableObject implements Buildable, Sq
return this;
}
public Builder setUnlockRequestTimestamp(DateTime unlockRequestTimestamp) {
getInstance().unlockRequestTimestamp = toZonedDateTime(unlockRequestTimestamp);
public Builder setUnlockRequestTime(DateTime unlockRequestTime) {
getInstance().unlockRequestTime = toZonedDateTime(unlockRequestTime);
return this;
}
public Builder setLockCompletionTimestamp(DateTime lockCompletionTimestamp) {
getInstance().lockCompletionTimestamp = toZonedDateTime(lockCompletionTimestamp);
public Builder setLockCompletionTime(DateTime lockCompletionTime) {
getInstance().lockCompletionTime = toZonedDateTime(lockCompletionTime);
return this;
}
public Builder setUnlockCompletionTimestamp(DateTime unlockCompletionTimestamp) {
getInstance().unlockCompletionTimestamp = toZonedDateTime(unlockCompletionTimestamp);
public Builder setUnlockCompletionTime(DateTime unlockCompletionTime) {
getInstance().unlockCompletionTime = toZonedDateTime(unlockCompletionTime);
return this;
}

View file

@ -103,7 +103,7 @@ public final class DomainLockUtils {
RegistryLock lock = getByVerificationCode(verificationCode);
checkArgument(
!lock.getLockCompletionTimestamp().isPresent(),
!lock.getLockCompletionTime().isPresent(),
"Domain %s is already locked",
lock.getDomainName());
@ -115,7 +115,7 @@ public final class DomainLockUtils {
!lock.isSuperuser() || isAdmin, "Non-admin user cannot complete admin lock");
RegistryLock newLock =
RegistryLockDao.save(lock.asBuilder().setLockCompletionTimestamp(now).build());
RegistryLockDao.save(lock.asBuilder().setLockCompletionTime(now).build());
setAsRelock(newLock);
tm().transact(() -> applyLockStatuses(newLock, now, isAdmin));
return newLock;
@ -131,7 +131,7 @@ public final class DomainLockUtils {
DateTime now = jpaTm().getTransactionTime();
RegistryLock previousLock = getByVerificationCode(verificationCode);
checkArgument(
!previousLock.getUnlockCompletionTimestamp().isPresent(),
!previousLock.getUnlockCompletionTime().isPresent(),
"Domain %s is already unlocked",
previousLock.getDomainName());
@ -145,7 +145,7 @@ public final class DomainLockUtils {
RegistryLock newLock =
RegistryLockDao.save(
previousLock.asBuilder().setUnlockCompletionTimestamp(now).build());
previousLock.asBuilder().setUnlockCompletionTime(now).build());
tm().transact(() -> removeLockStatuses(newLock, isAdmin, now));
return newLock;
});
@ -169,7 +169,7 @@ public final class DomainLockUtils {
RegistryLock newLock =
RegistryLockDao.save(
createLockBuilder(domainName, registrarId, registrarPocId, isAdmin)
.setLockCompletionTimestamp(now)
.setLockCompletionTime(now)
.build());
tm().transact(() -> applyLockStatuses(newLock, now, isAdmin));
setAsRelock(newLock);
@ -192,7 +192,7 @@ public final class DomainLockUtils {
RegistryLock result =
RegistryLockDao.save(
createUnlockBuilder(domainName, registrarId, isAdmin, relockDuration)
.setUnlockCompletionTimestamp(now)
.setUnlockCompletionTime(now)
.build());
tm().transact(() -> removeLockStatuses(result, isAdmin, now));
return result;
@ -230,7 +230,7 @@ public final class DomainLockUtils {
previousLock ->
checkArgument(
previousLock.isLockRequestExpired(now)
|| previousLock.getUnlockCompletionTimestamp().isPresent()
|| previousLock.getUnlockCompletionTime().isPresent()
|| isAdmin,
"A pending or completed lock action already exists for %s",
previousLock.getDomainName()));
@ -264,7 +264,7 @@ public final class DomainLockUtils {
new RegistryLock.Builder()
.setRepoId(domainBase.getRepoId())
.setDomainName(domainName)
.setLockCompletionTimestamp(now)
.setLockCompletionTime(now)
.setRegistrarId(registrarId));
} else {
RegistryLock lock =
@ -275,7 +275,7 @@ public final class DomainLockUtils {
checkArgument(
lock.isLocked(), "Lock object for domain %s is not currently locked", domainName);
checkArgument(
!lock.getUnlockRequestTimestamp().isPresent() || lock.isUnlockRequestExpired(now),
!lock.getUnlockRequestTime().isPresent() || lock.isUnlockRequestExpired(now),
"A pending unlock action already exists for %s",
domainName);
checkArgument(
@ -290,7 +290,7 @@ public final class DomainLockUtils {
return newLockBuilder
.setVerificationCode(stringGenerator.createString(VERIFICATION_CODE_LENGTH))
.isSuperuser(isAdmin)
.setUnlockRequestTimestamp(now)
.setUnlockRequestTime(now)
.setRegistrarId(registrarId);
}

View file

@ -107,7 +107,7 @@ public class BackfillRegistryLocksCommand extends ConfirmingCommand
.setRegistrarId(registryAdminClientId)
.setRepoId(domainBase.getRepoId())
.setDomainName(domainBase.getDomainName())
.setLockCompletionTimestamp(
.setLockCompletionTime(
getLockCompletionTimestamp(domainBase, jpaTm().getTransactionTime()))
.setVerificationCode(
stringGenerator.createString(VERIFICATION_CODE_LENGTH))

View file

@ -191,14 +191,13 @@ public final class RegistryLockGetAction implements JsonGetAction {
DateTime now = jpaTm().getTransactionTime();
return new ImmutableMap.Builder<String, Object>()
.put(DOMAIN_NAME_PARAM, lock.getDomainName())
.put(
LOCKED_TIME_PARAM, lock.getLockCompletionTimestamp().map(DateTime::toString).orElse(""))
.put(LOCKED_TIME_PARAM, lock.getLockCompletionTime().map(DateTime::toString).orElse(""))
.put(LOCKED_BY_PARAM, lock.isSuperuser() ? "admin" : lock.getRegistrarPocId())
.put(IS_LOCK_PENDING_PARAM, !lock.getLockCompletionTimestamp().isPresent())
.put(IS_LOCK_PENDING_PARAM, !lock.getLockCompletionTime().isPresent())
.put(
IS_UNLOCK_PENDING_PARAM,
lock.getUnlockRequestTimestamp().isPresent()
&& !lock.getUnlockCompletionTimestamp().isPresent()
lock.getUnlockRequestTime().isPresent()
&& !lock.getUnlockCompletionTime().isPresent()
&& !lock.isUnlockRequestExpired(now))
.put(USER_CAN_UNLOCK_PARAM, isAdmin || !lock.isSuperuser())
.build();

View file

@ -98,7 +98,6 @@
<class>google.registry.persistence.converter.StringSetConverter</class>
<class>google.registry.persistence.converter.TldStateTransitionConverter</class>
<class>google.registry.persistence.converter.TransferServerApproveEntitySetConverter</class>
<class>google.registry.persistence.converter.UpdateAutoTimestampConverter</class>
<class>google.registry.persistence.converter.ZonedDateTimeConverter</class>
<!-- Generated converters for VKey -->

View file

@ -148,9 +148,9 @@ public class AsyncTaskEnqueuerTest {
RegistryLock lock =
saveRegistryLock(
new RegistryLock.Builder()
.setLockCompletionTimestamp(clock.nowUtc())
.setUnlockRequestTimestamp(clock.nowUtc())
.setUnlockCompletionTimestamp(clock.nowUtc())
.setLockCompletionTime(clock.nowUtc())
.setUnlockRequestTime(clock.nowUtc())
.setUnlockCompletionTime(clock.nowUtc())
.isSuperuser(false)
.setDomainName("example.tld")
.setRepoId("repoId")

View file

@ -22,13 +22,16 @@ import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Ignore;
import google.registry.model.common.CrossTldSingleton;
import google.registry.model.ofy.Ofy;
import google.registry.persistence.VKey;
import google.registry.schema.replay.EntityTest.EntityForTesting;
import google.registry.testing.AppEngineExtension;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.FakeClock;
import google.registry.testing.InjectExtension;
import google.registry.testing.TestOfyAndSql;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link UpdateAutoTimestamp}. */
@ -46,6 +49,13 @@ public class UpdateAutoTimestampTest {
.withClock(clock)
.build();
@RegisterExtension public final InjectExtension inject = new InjectExtension();
@BeforeEach
void beforeEach() {
inject.setStaticField(Ofy.class, "clock", clock);
}
/** Timestamped class. */
@Entity(name = "UatTestEntity")
@javax.persistence.Entity
@ -70,6 +80,7 @@ public class UpdateAutoTimestampTest {
DateTime transactionTime =
tm().transact(
() -> {
clock.advanceOneMilli();
UpdateAutoTimestampTestObject object = new UpdateAutoTimestampTestObject();
assertThat(object.updateTime.timestamp).isNull();
tm().insert(object);
@ -84,6 +95,7 @@ public class UpdateAutoTimestampTest {
DateTime initialTime =
tm().transact(
() -> {
clock.advanceOneMilli();
tm().insert(new UpdateAutoTimestampTestObject());
return tm().getTransactionTime();
});
@ -109,6 +121,7 @@ public class UpdateAutoTimestampTest {
DateTime transactionTime =
tm().transact(
() -> {
clock.advanceOneMilli();
UpdateAutoTimestampTestObject object = new UpdateAutoTimestampTestObject();
object.updateTime = UpdateAutoTimestamp.create(DateTime.now(UTC).minusDays(1));
tm().insert(object);
@ -117,4 +130,17 @@ public class UpdateAutoTimestampTest {
tm().clearSessionCache();
assertThat(reload().updateTime.timestamp).isEqualTo(transactionTime);
}
@TestOfyAndSql
void testReadingTwiceDoesNotModify() {
DateTime originalTime = DateTime.parse("1999-01-01T00:00:00Z");
clock.setTo(originalTime);
tm().transact(() -> tm().insert(new UpdateAutoTimestampTestObject()));
clock.advanceOneMilli();
UpdateAutoTimestampTestObject firstRead = reload();
assertThat(firstRead.updateTime.getTimestamp()).isEqualTo(originalTime);
clock.advanceOneMilli();
UpdateAutoTimestampTestObject secondRead = reload();
assertThat(secondRead.updateTime.getTimestamp()).isEqualTo(originalTime);
}
}

View file

@ -129,8 +129,11 @@ public class LegacyHistoryObjectTest extends EntityTestCase {
// Next, save that from-Datastore object in SQL and verify we can load it back in
jpaTm().transact(() -> jpaTm().insert(legacyDomainHistory));
jpaTm()
.transact(
() -> {
DomainHistory legacyHistoryFromSql =
jpaTm().transact(() -> jpaTm().loadByKey(legacyDomainHistory.createVKey()));
jpaTm().loadByKey(legacyDomainHistory.createVKey());
// Don't compare nsHosts directly because one is null and the other is empty
assertAboutImmutableObjects()
.that(legacyDomainHistory)
@ -145,6 +148,7 @@ public class LegacyHistoryObjectTest extends EntityTestCase {
"gracePeriodHistories");
assertThat(nullToEmpty(legacyDomainHistory.getNsHosts()))
.isEqualTo(nullToEmpty(legacyHistoryFromSql.getNsHosts()));
});
}
@TestSqlOnly

View file

@ -46,7 +46,7 @@ public final class RegistryLockDaoTest extends EntityTestCase {
RegistryLock fromDatabase = getRegistryLockByVerificationCode(lock.getVerificationCode()).get();
assertThat(fromDatabase.getDomainName()).isEqualTo(lock.getDomainName());
assertThat(fromDatabase.getVerificationCode()).isEqualTo(lock.getVerificationCode());
assertThat(fromDatabase.getLastUpdateTimestamp()).isEqualTo(fakeClock.nowUtc());
assertThat(fromDatabase.getLastUpdateTime()).isEqualTo(fakeClock.nowUtc());
}
@Test
@ -60,16 +60,15 @@ public final class RegistryLockDaoTest extends EntityTestCase {
RegistryLock updatedLock =
RegistryLockDao.getByVerificationCode(lock.getVerificationCode()).get();
RegistryLockDao.save(
updatedLock.asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build());
updatedLock.asBuilder().setLockCompletionTime(fakeClock.nowUtc()).build());
});
jpaTm()
.transact(
() -> {
RegistryLock fromDatabase =
RegistryLockDao.getByVerificationCode(lock.getVerificationCode()).get();
assertThat(fromDatabase.getLockCompletionTimestamp().get())
.isEqualTo(fakeClock.nowUtc());
assertThat(fromDatabase.getLastUpdateTimestamp()).isEqualTo(fakeClock.nowUtc());
assertThat(fromDatabase.getLockCompletionTime().get()).isEqualTo(fakeClock.nowUtc());
assertThat(fromDatabase.getLastUpdateTime()).isEqualTo(fakeClock.nowUtc());
});
}
@ -79,15 +78,14 @@ public final class RegistryLockDaoTest extends EntityTestCase {
saveRegistryLock(
createLock()
.asBuilder()
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setUnlockCompletionTimestamp(fakeClock.nowUtc())
.setLockCompletionTime(fakeClock.nowUtc())
.setUnlockRequestTime(fakeClock.nowUtc())
.setUnlockCompletionTime(fakeClock.nowUtc())
.setRelockDuration(Duration.standardHours(6))
.build());
RegistryLock fromDatabase = getRegistryLockByVerificationCode(lock.getVerificationCode()).get();
assertThat(fromDatabase.getUnlockRequestTimestamp()).isEqualTo(Optional.of(fakeClock.nowUtc()));
assertThat(fromDatabase.getUnlockCompletionTimestamp())
.isEqualTo(Optional.of(fakeClock.nowUtc()));
assertThat(fromDatabase.getUnlockRequestTime()).isEqualTo(Optional.of(fakeClock.nowUtc()));
assertThat(fromDatabase.getUnlockCompletionTime()).isEqualTo(Optional.of(fakeClock.nowUtc()));
assertThat(fromDatabase.isLocked()).isFalse();
assertThat(fromDatabase.getRelockDuration().get()).isEqualTo(Duration.standardHours(6));
}
@ -96,15 +94,14 @@ public final class RegistryLockDaoTest extends EntityTestCase {
void testUpdateLock_usingSamePrimaryKey() {
RegistryLock lock = saveRegistryLock(createLock());
fakeClock.advanceOneMilli();
RegistryLock updatedLock =
lock.asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build();
RegistryLock updatedLock = lock.asBuilder().setLockCompletionTime(fakeClock.nowUtc()).build();
saveRegistryLock(updatedLock);
jpaTm()
.transact(
() -> {
RegistryLock fromDatabase =
RegistryLockDao.getByVerificationCode(lock.getVerificationCode()).get();
assertThat(fromDatabase.getLockCompletionTimestamp())
assertThat(fromDatabase.getLockCompletionTime())
.isEqualTo(Optional.of(fakeClock.nowUtc()));
});
}
@ -140,15 +137,15 @@ public final class RegistryLockDaoTest extends EntityTestCase {
createLock()
.asBuilder()
.setDomainName("otherexample.test")
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setLockCompletionTime(fakeClock.nowUtc())
.build();
RegistryLock unlockedLock =
createLock()
.asBuilder()
.setDomainName("unlocked.test")
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setUnlockCompletionTimestamp(fakeClock.nowUtc())
.setLockCompletionTime(fakeClock.nowUtc())
.setUnlockRequestTime(fakeClock.nowUtc())
.setUnlockCompletionTime(fakeClock.nowUtc())
.build();
saveRegistryLock(lock);
saveRegistryLock(secondLock);
@ -165,7 +162,7 @@ public final class RegistryLockDaoTest extends EntityTestCase {
@Test
void testLoad_byRepoId() {
RegistryLock completedLock =
createLock().asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build();
createLock().asBuilder().setLockCompletionTime(fakeClock.nowUtc()).build();
saveRegistryLock(completedLock);
fakeClock.advanceOneMilli();
@ -185,7 +182,7 @@ public final class RegistryLockDaoTest extends EntityTestCase {
@Test
void testLoad_verified_byRepoId() {
RegistryLock completedLock =
createLock().asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build();
createLock().asBuilder().setLockCompletionTime(fakeClock.nowUtc()).build();
saveRegistryLock(completedLock);
fakeClock.advanceOneMilli();
@ -210,9 +207,9 @@ public final class RegistryLockDaoTest extends EntityTestCase {
saveRegistryLock(
createLock()
.asBuilder()
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setUnlockCompletionTimestamp(fakeClock.nowUtc())
.setLockCompletionTime(fakeClock.nowUtc())
.setUnlockRequestTime(fakeClock.nowUtc())
.setUnlockCompletionTime(fakeClock.nowUtc())
.build());
Optional<RegistryLock> mostRecent = getMostRecentUnlockedRegistryLockByRepoId(lock.getRepoId());
@ -222,7 +219,7 @@ public final class RegistryLockDaoTest extends EntityTestCase {
@Test
void testLoad_verifiedUnlock_empty() {
RegistryLock completedLock =
createLock().asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build();
createLock().asBuilder().setLockCompletionTime(fakeClock.nowUtc()).build();
saveRegistryLock(completedLock);
assertThat(getMostRecentUnlockedRegistryLockByRepoId(completedLock.getRepoId()).isPresent())
.isFalse();

View file

@ -142,6 +142,7 @@ class EntityCallbacksListenerTest {
assertThat(testEntity.entityEmbedded.entityEmbeddedParentPostLoad).isEqualTo(expectedLoad);
assertThat(testEntity.parentPostLoad).isEqualTo(expectedLoad);
assertThat(testEntity.parentPrePersist).isEqualTo(expectedPersist);
assertThat(testEntity.parentEmbedded.parentEmbeddedPostLoad).isEqualTo(expectedLoad);
assertThat(testEntity.parentEmbedded.parentEmbeddedNested.parentEmbeddedNestedPostLoad)
.isEqualTo(expectedLoad);
@ -241,6 +242,7 @@ class EntityCallbacksListenerTest {
private static class ParentEntity {
@Embedded ParentEmbedded parentEmbedded = new ParentEmbedded();
@Transient int parentPostLoad = 0;
@Transient int parentPrePersist = 0;
String parentEntity = "placeholder";
@ -248,6 +250,11 @@ class EntityCallbacksListenerTest {
void parentPostLoad() {
parentPostLoad++;
}
@PrePersist
void parentPrePersist() {
parentPrePersist++;
}
}
@Embeddable

View file

@ -1,92 +0,0 @@
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.persistence.converter;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import google.registry.model.ImmutableObject;
import google.registry.model.UpdateAutoTimestamp;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestExtension;
import google.registry.schema.replay.EntityTest.EntityForTesting;
import google.registry.testing.FakeClock;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link UpdateAutoTimestampConverter}. */
public class UpdateAutoTimestampConverterTest {
private final FakeClock fakeClock = new FakeClock();
@RegisterExtension
public final JpaUnitTestExtension jpaExtension =
new JpaTestRules.Builder()
.withClock(fakeClock)
.withEntityClass(TestEntity.class)
.buildUnitTestRule();
@Test
void testTypeConversion() {
TestEntity ent = new TestEntity("myinst", null);
jpaTm().transact(() -> jpaTm().insert(ent));
TestEntity result =
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "myinst"));
assertThat(result.name).isEqualTo("myinst");
assertThat(result.uat.getTimestamp()).isEqualTo(fakeClock.nowUtc());
}
@Test
void testTimeChangesOnSubsequentTransactions() {
TestEntity ent1 = new TestEntity("myinst1", null);
jpaTm().transact(() -> jpaTm().insert(ent1));
TestEntity result1 =
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "myinst1"));
fakeClock.advanceOneMilli();
TestEntity ent2 = new TestEntity("myinst2", result1.uat);
jpaTm().transact(() -> jpaTm().insert(ent2));
TestEntity result2 =
jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "myinst2"));
assertThat(result1.uat.getTimestamp()).isNotEqualTo(result2.uat.getTimestamp());
assertThat(result2.uat.getTimestamp()).isEqualTo(fakeClock.nowUtc());
}
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
@EntityForTesting
public static class TestEntity extends ImmutableObject {
@Id String name;
UpdateAutoTimestamp uat;
public TestEntity() {}
TestEntity(String name, UpdateAutoTimestamp uat) {
this.name = name;
this.uat = uat;
}
}
}

View file

@ -110,7 +110,10 @@ public class ReplayExtension implements BeforeEachCallback, AfterEachCallback {
// have to compare the current value in SQL (which we just mutated) against the value that
// we originally would have persisted (that being the object in the entry).
VKey<?> vkey = VKey.from(entry.getKey());
Optional<?> jpaValue = jpaTm().transact(() -> jpaTm().loadByKeyIfPresent(vkey));
jpaTm()
.transact(
() -> {
Optional<?> jpaValue = jpaTm().loadByKeyIfPresent(vkey);
if (entry.getValue().equals(TransactionInfo.Delete.SENTINEL)) {
assertThat(jpaValue.isPresent()).isFalse();
} else {
@ -119,8 +122,10 @@ public class ReplayExtension implements BeforeEachCallback, AfterEachCallback {
assertAboutImmutableObjects()
.that(immutJpaObject)
.isEqualAcrossDatabases(
(ImmutableObject) ((DatastoreEntity) entry.getValue()).toSqlEntity().get());
(ImmutableObject)
((DatastoreEntity) entry.getValue()).toSqlEntity().get());
}
});
}
}
}

View file

@ -104,7 +104,7 @@ public final class DomainLockUtilsTest {
RegistryLock lock =
domainLockUtils.saveNewRegistryLockRequest(DOMAIN_NAME, "TheRegistrar", POC_ID, false);
assertNoDomainChanges();
assertThat(lock.getLockCompletionTimestamp().isPresent()).isFalse();
assertThat(lock.getLockCompletionTime().isPresent()).isFalse();
}
@Test
@ -113,7 +113,7 @@ public final class DomainLockUtilsTest {
RegistryLock lock =
domainLockUtils.saveNewRegistryUnlockRequest(
DOMAIN_NAME, "TheRegistrar", false, Optional.empty());
assertThat(lock.getUnlockCompletionTimestamp().isPresent()).isFalse();
assertThat(lock.getUnlockCompletionTime().isPresent()).isFalse();
}
@Test
@ -122,7 +122,7 @@ public final class DomainLockUtilsTest {
RegistryLock lock =
domainLockUtils.saveNewRegistryUnlockRequest(
DOMAIN_NAME, "TheRegistrar", true, Optional.empty());
assertThat(lock.getUnlockCompletionTimestamp().isPresent()).isFalse();
assertThat(lock.getUnlockCompletionTime().isPresent()).isFalse();
}
@Test
@ -285,7 +285,7 @@ public final class DomainLockUtilsTest {
RegistryLock resultLock =
domainLockUtils.administrativelyApplyLock(DOMAIN_NAME, "TheRegistrar", POC_ID, true);
verifyProperlyLockedDomain(true);
assertThat(resultLock.getLockCompletionTimestamp()).isEqualTo(Optional.of(clock.nowUtc()));
assertThat(resultLock.getLockCompletionTime()).isEqualTo(Optional.of(clock.nowUtc()));
}
@Test
@ -294,7 +294,7 @@ public final class DomainLockUtilsTest {
// what the RegistryLock table says
SqlHelper.saveRegistryLock(
new RegistryLock.Builder()
.setLockCompletionTimestamp(clock.nowUtc())
.setLockCompletionTime(clock.nowUtc())
.setDomainName(DOMAIN_NAME)
.setVerificationCode("hi")
.setRegistrarId("TheRegistrar")
@ -306,7 +306,7 @@ public final class DomainLockUtilsTest {
RegistryLock resultLock =
domainLockUtils.administrativelyApplyLock(DOMAIN_NAME, "TheRegistrar", POC_ID, true);
verifyProperlyLockedDomain(true);
assertThat(resultLock.getLockCompletionTimestamp()).isEqualTo(Optional.of(clock.nowUtc()));
assertThat(resultLock.getLockCompletionTime()).isEqualTo(Optional.of(clock.nowUtc()));
}
@Test

View file

@ -68,7 +68,7 @@ class BackfillRegistryLocksCommandTest extends CommandTestCase<BackfillRegistryL
Optional<RegistryLock> lockOptional = getMostRecentRegistryLockByRepoId(domain.getRepoId());
Truth8.assertThat(lockOptional).isPresent();
Truth8.assertThat(lockOptional.get().getLockCompletionTimestamp()).isPresent();
Truth8.assertThat(lockOptional.get().getLockCompletionTime()).isPresent();
}
@TestOfyAndSql
@ -111,18 +111,15 @@ class BackfillRegistryLocksCommandTest extends CommandTestCase<BackfillRegistryL
.setRegistrarId("adminreg")
.setRepoId(domain.getRepoId())
.setDomainName(domain.getDomainName())
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setLockCompletionTime(fakeClock.nowUtc())
.setVerificationCode(command.stringGenerator.createString(32))
.build());
fakeClock.advanceBy(Duration.standardDays(1));
runCommandForced("--domain_roids", domain.getRepoId());
assertThat(
getMostRecentRegistryLockByRepoId(domain.getRepoId())
.get()
.getLockCompletionTimestamp())
.isEqualTo(previousLock.getLockCompletionTimestamp());
assertThat(getMostRecentRegistryLockByRepoId(domain.getRepoId()).get().getLockCompletionTime())
.isEqualTo(previousLock.getLockCompletionTime());
}
@TestOfyAndSql
@ -147,10 +144,10 @@ class BackfillRegistryLocksCommandTest extends CommandTestCase<BackfillRegistryL
"--domain_roids", String.format("%s,%s", ursDomain.getRepoId(), nonUrsDomain.getRepoId()));
RegistryLock ursLock = getMostRecentVerifiedRegistryLockByRepoId(ursDomain.getRepoId()).get();
assertThat(ursLock.getLockCompletionTimestamp()).hasValue(ursTime);
assertThat(ursLock.getLockCompletionTime()).hasValue(ursTime);
RegistryLock nonUrsLock =
getMostRecentVerifiedRegistryLockByRepoId(nonUrsDomain.getRepoId()).get();
assertThat(nonUrsLock.getLockCompletionTimestamp()).hasValue(fakeClock.nowUtc());
assertThat(nonUrsLock.getLockCompletionTime()).hasValue(fakeClock.nowUtc());
}
@TestOfyAndSql

View file

@ -101,8 +101,8 @@ final class RegistryLockGetActionTest {
.setRegistrarId("TheRegistrar")
.setVerificationCode("123456789ABCDEFGHJKLMNPQRSTUVWXY")
.setRegistrarPocId("johndoe@theregistrar.com")
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setLockCompletionTime(fakeClock.nowUtc())
.setUnlockRequestTime(fakeClock.nowUtc())
.build();
saveRegistryLock(expiredUnlock);
fakeClock.advanceBy(Duration.standardDays(1));
@ -114,7 +114,7 @@ final class RegistryLockGetActionTest {
.setRegistrarId("TheRegistrar")
.setVerificationCode("123456789ABCDEFGHJKLMNPQRSTUVWXY")
.setRegistrarPocId("johndoe@theregistrar.com")
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setLockCompletionTime(fakeClock.nowUtc())
.build();
fakeClock.advanceOneMilli();
RegistryLock adminLock =
@ -124,7 +124,7 @@ final class RegistryLockGetActionTest {
.setRegistrarId("TheRegistrar")
.setVerificationCode("122222222ABCDEFGHJKLMNPQRSTUVWXY")
.isSuperuser(true)
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setLockCompletionTime(fakeClock.nowUtc())
.build();
RegistryLock incompleteLock =
new RegistryLock.Builder()
@ -142,8 +142,8 @@ final class RegistryLockGetActionTest {
.setRegistrarId("TheRegistrar")
.setVerificationCode("123456789ABCDEFGHJKLMNPQRSTUVWXY")
.setRegistrarPocId("johndoe@theregistrar.com")
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setLockCompletionTime(fakeClock.nowUtc())
.setUnlockRequestTime(fakeClock.nowUtc())
.build();
RegistryLock unlockedLock =
@ -153,9 +153,9 @@ final class RegistryLockGetActionTest {
.setRegistrarId("TheRegistrar")
.setRegistrarPocId("johndoe@theregistrar.com")
.setVerificationCode("123456789ABCDEFGHJKLMNPQRSTUUUUU")
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setUnlockCompletionTimestamp(fakeClock.nowUtc())
.setLockCompletionTime(fakeClock.nowUtc())
.setUnlockRequestTime(fakeClock.nowUtc())
.setUnlockCompletionTime(fakeClock.nowUtc())
.build();
saveRegistryLock(regularLock);

View file

@ -123,7 +123,7 @@ final class RegistryLockPostActionTest {
@Test
void testSuccess_unlock() throws Exception {
saveRegistryLock(createLock().asBuilder().setLockCompletionTimestamp(clock.nowUtc()).build());
saveRegistryLock(createLock().asBuilder().setLockCompletionTime(clock.nowUtc()).build());
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
Map<String, ?> response = action.handleJsonRequest(unlockRequest());
assertSuccess(response, "unlock", "Marla.Singer.RegistryLock@crr.com");
@ -131,7 +131,7 @@ final class RegistryLockPostActionTest {
@Test
void testSuccess_unlock_relockDurationSet() throws Exception {
saveRegistryLock(createLock().asBuilder().setLockCompletionTimestamp(clock.nowUtc()).build());
saveRegistryLock(createLock().asBuilder().setLockCompletionTime(clock.nowUtc()).build());
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
ImmutableMap<String, Object> request =
new ImmutableMap.Builder<String, Object>()
@ -148,11 +148,7 @@ final class RegistryLockPostActionTest {
@Test
void testSuccess_unlock_adminUnlockingAdmin() throws Exception {
saveRegistryLock(
createLock()
.asBuilder()
.isSuperuser(true)
.setLockCompletionTimestamp(clock.nowUtc())
.build());
createLock().asBuilder().isSuperuser(true).setLockCompletionTime(clock.nowUtc()).build());
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
action =
createAction(
@ -187,8 +183,8 @@ final class RegistryLockPostActionTest {
saveRegistryLock(
createLock()
.asBuilder()
.setLockCompletionTimestamp(clock.nowUtc())
.setUnlockRequestTimestamp(clock.nowUtc())
.setLockCompletionTime(clock.nowUtc())
.setUnlockRequestTime(clock.nowUtc())
.build());
Map<String, ?> response = action.handleJsonRequest(unlockRequest());
assertFailureWithMessage(response, "A pending unlock action already exists for example.tld");
@ -197,11 +193,7 @@ final class RegistryLockPostActionTest {
@Test
void testFailure_unlock_nonAdminUnlockingAdmin() {
saveRegistryLock(
createLock()
.asBuilder()
.isSuperuser(true)
.setLockCompletionTimestamp(clock.nowUtc())
.build());
createLock().asBuilder().isSuperuser(true).setLockCompletionTime(clock.nowUtc()).build());
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
Map<String, ?> response = action.handleJsonRequest(unlockRequest());
assertFailureWithMessage(
@ -366,9 +358,9 @@ final class RegistryLockPostActionTest {
saveRegistryLock(
createLock()
.asBuilder()
.setLockCompletionTimestamp(clock.nowUtc().minusMinutes(1))
.setUnlockRequestTimestamp(clock.nowUtc().minusMinutes(1))
.setUnlockCompletionTimestamp(clock.nowUtc().minusMinutes(1))
.setLockCompletionTime(clock.nowUtc().minusMinutes(1))
.setUnlockRequestTime(clock.nowUtc().minusMinutes(1))
.setUnlockCompletionTime(clock.nowUtc().minusMinutes(1))
.build());
Map<String, ?> response = action.handleJsonRequest(lockRequest());
@ -380,7 +372,7 @@ final class RegistryLockPostActionTest {
RegistryLock previousLock = saveRegistryLock(createLock());
String verificationCode = previousLock.getVerificationCode();
previousLock = getRegistryLockByVerificationCode(verificationCode).get();
clock.setTo(previousLock.getLockRequestTimestamp().plusHours(2));
clock.setTo(previousLock.getLockRequestTime().plusHours(2));
Map<String, ?> response = action.handleJsonRequest(lockRequest());
assertSuccess(response, "lock", "Marla.Singer.RegistryLock@crr.com");
}

View file

@ -114,8 +114,7 @@ final class RegistryLockVerifyActionTest {
void testSuccess_unlockDomain() {
action = createAction(lockId, false);
domain = persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
saveRegistryLock(
createLock().asBuilder().setUnlockRequestTimestamp(fakeClock.nowUtc()).build());
saveRegistryLock(createLock().asBuilder().setUnlockRequestTime(fakeClock.nowUtc()).build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(response.getPayload()).contains("Success: unlock has been applied to example.tld");
@ -151,8 +150,7 @@ final class RegistryLockVerifyActionTest {
@Test
void testFailure_alreadyVerified() {
saveRegistryLock(
createLock().asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build());
saveRegistryLock(createLock().asBuilder().setLockCompletionTime(fakeClock.nowUtc()).build());
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already locked");
assertNoDomainChanges();
@ -182,9 +180,9 @@ final class RegistryLockVerifyActionTest {
saveRegistryLock(
createLock()
.asBuilder()
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setUnlockCompletionTimestamp(fakeClock.nowUtc())
.setLockCompletionTime(fakeClock.nowUtc())
.setUnlockRequestTime(fakeClock.nowUtc())
.setUnlockCompletionTime(fakeClock.nowUtc())
.build());
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already unlocked");
@ -234,8 +232,8 @@ final class RegistryLockVerifyActionTest {
saveRegistryLock(
createLock()
.asBuilder()
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setLockCompletionTime(fakeClock.nowUtc())
.setUnlockRequestTime(fakeClock.nowUtc())
.build());
action.run();
assertThat(response.getPayload()).contains("Failed: Domain example.tld is already locked");
@ -258,7 +256,7 @@ final class RegistryLockVerifyActionTest {
saveRegistryLock(
lock.asBuilder()
.setVerificationCode(unlockVerificationCode)
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setUnlockRequestTime(fakeClock.nowUtc())
.build());
action = createAction(unlockVerificationCode, false);
action.run();
@ -282,8 +280,7 @@ final class RegistryLockVerifyActionTest {
void testFailure_unlock_unlockAgain() {
action = createAction(lockId, false);
domain = persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
saveRegistryLock(
createLock().asBuilder().setUnlockRequestTimestamp(fakeClock.nowUtc()).build());
saveRegistryLock(createLock().asBuilder().setUnlockRequestTime(fakeClock.nowUtc()).build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(response.getPayload()).contains("Success: unlock has been applied to example.tld");

View file

@ -465,8 +465,8 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
saveRegistryLock(
createRegistryLock(expiredUnlockRequestDomain)
.asBuilder()
.setLockCompletionTimestamp(START_OF_TIME.minusDays(1))
.setUnlockRequestTimestamp(START_OF_TIME.minusDays(1))
.setLockCompletionTime(START_OF_TIME.minusDays(1))
.setUnlockRequestTime(START_OF_TIME.minusDays(1))
.build());
DomainBase domain = persistActiveDomain("example.tld");
saveRegistryLock(createRegistryLock(domain).asBuilder().isSuperuser(true).build());
@ -498,8 +498,8 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
.setRegistrarPocId("Marla.Singer@crr.com")
.setDomainName(pendingUnlockDomain.getDomainName())
.setRepoId(pendingUnlockDomain.getRepoId())
.setLockCompletionTimestamp(START_OF_TIME)
.setUnlockRequestTimestamp(START_OF_TIME)
.setLockCompletionTime(START_OF_TIME)
.setUnlockRequestTime(START_OF_TIME)
.build());
return null;
});
@ -568,7 +568,7 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
.isSuperuser(false)
.setRegistrarId("TheRegistrar")
.setRegistrarPocId("Marla.Singer@crr.com")
.setLockCompletionTimestamp(START_OF_TIME)
.setLockCompletionTime(START_OF_TIME)
.setDomainName(domainBase.getDomainName())
.setRepoId(domainBase.getRepoId())
.build();

View file

@ -261,11 +261,11 @@ td.section {
</tr>
<tr>
<td class="property_name">generated on</td>
<td class="property_value">2021-03-19 12:31:33.396532</td>
<td class="property_value">2021-03-24 01:27:00.824998</td>
</tr>
<tr>
<td class="property_name">last flyway file</td>
<td id="lastFlywayFile" class="property_value">V89__host_history_host_deferred.sql</td>
<td id="lastFlywayFile" class="property_value">V90__update_timestamp.sql</td>
</tr>
</tbody>
</table>
@ -284,7 +284,7 @@ td.section {
generated on
</text>
<text text-anchor="start" x="4027.94" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">
2021-03-19 12:31:33.396532
2021-03-24 01:27:00.824998
</text>
<polygon fill="none" stroke="#888888" points="3940.44,-4 3940.44,-44 4205.44,-44 4205.44,-4 3940.44,-4" /> <!-- allocationtoken_a08ccbef -->
<g id="node1" class="node">

File diff suppressed because it is too large Load diff

View file

@ -87,3 +87,4 @@ V86__third_poll_message.sql
V87__fix_super_domain_fk.sql
V88__transfer_billing_cancellation_history_id.sql
V89__host_history_host_deferred.sql
V90__update_timestamp.sql

View file

@ -0,0 +1,23 @@
-- Copyright 2021 The Nomulus Authors. All Rights Reserved.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
ALTER TABLE "Registrar" ALTER COLUMN "last_update_time" SET NOT NULL;
ALTER TABLE "RegistryLock" RENAME "last_update_timestamp" TO "last_update_time";
ALTER TABLE "RegistryLock" ALTER COLUMN "last_update_time" SET NOT NULL;
-- While we're at it, rename some registry-lock fields to follow the same naming pattern
ALTER TABLE "RegistryLock" RENAME "lock_completion_timestamp" TO "lock_completion_time";
ALTER TABLE "RegistryLock" RENAME "lock_request_timestamp" TO "lock_request_time";
ALTER TABLE "RegistryLock" RENAME "unlock_completion_timestamp" TO "unlock_completion_time";
ALTER TABLE "RegistryLock" RENAME "unlock_request_timestamp" TO "unlock_request_time";

View file

@ -589,7 +589,7 @@
i18n_address_zip text,
ip_address_allow_list text[],
last_certificate_update_time timestamptz,
last_update_time timestamptz,
last_update_time timestamptz not null,
localized_address_city text,
localized_address_country_code text,
localized_address_state text,
@ -634,15 +634,15 @@
revision_id bigserial not null,
domain_name text not null,
is_superuser boolean not null,
last_update_timestamp timestamptz,
lock_completion_timestamp timestamptz,
lock_request_timestamp timestamptz not null,
last_update_time timestamptz not null,
lock_completion_time timestamptz,
lock_request_time timestamptz not null,
registrar_id text not null,
registrar_poc_id text,
relock_duration interval,
repo_id text not null,
unlock_completion_timestamp timestamptz,
unlock_request_timestamp timestamptz,
unlock_completion_time timestamptz,
unlock_request_time timestamptz,
verification_code text not null,
relock_revision_id int8,
primary key (revision_id)

View file

@ -780,7 +780,7 @@ CREATE TABLE public."Registrar" (
i18n_address_zip text,
ip_address_allow_list text[],
last_certificate_update_time timestamp with time zone,
last_update_time timestamp with time zone,
last_update_time timestamp with time zone NOT NULL,
localized_address_city text,
localized_address_country_code text,
localized_address_state text,
@ -831,17 +831,17 @@ CREATE TABLE public."RegistrarPoc" (
CREATE TABLE public."RegistryLock" (
revision_id bigint NOT NULL,
lock_completion_timestamp timestamp with time zone,
lock_request_timestamp timestamp with time zone NOT NULL,
lock_completion_time timestamp with time zone,
lock_request_time timestamp with time zone NOT NULL,
domain_name text NOT NULL,
is_superuser boolean NOT NULL,
registrar_id text NOT NULL,
registrar_poc_id text,
repo_id text NOT NULL,
verification_code text NOT NULL,
unlock_request_timestamp timestamp with time zone,
unlock_completion_timestamp timestamp with time zone,
last_update_timestamp timestamp with time zone,
unlock_request_time timestamp with time zone,
unlock_completion_time timestamp with time zone,
last_update_time timestamp with time zone NOT NULL,
relock_revision_id bigint,
relock_duration interval
);