Add schema and DAO for cursors in cloudsql (#370)

* Add schema for Cursor

* Add CursorDao and CursorDaoTest

* Fix comment on getTld

* Change tld column to scope

* Fix cursorTime to be converted to DateTime internally and other small fixes

* Add a CursorType enum and a createGlobal constructor for Cursor

* Rename flyway file

* Use cursorType from common/Cursor.java and add null checks
This commit is contained in:
sarahcaseybot
2019-12-09 17:47:06 -05:00
committed by GitHub
parent bba5aff4b6
commit 2478a4a93b
8 changed files with 370 additions and 0 deletions
@@ -0,0 +1,116 @@
// 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.schema.cursor;
import static com.google.appengine.api.search.checkers.Preconditions.checkNotNull;
import google.registry.model.ImmutableObject;
import google.registry.model.UpdateAutoTimestamp;
import google.registry.model.common.Cursor.CursorType;
import google.registry.schema.cursor.Cursor.CursorId;
import google.registry.util.DateTimeUtils;
import java.io.Serializable;
import java.time.ZonedDateTime;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Table;
import org.joda.time.DateTime;
/**
* Shared entity for date cursors. This uses a compound primary key as defined in {@link CursorId}.
*/
@Entity
@Table
@IdClass(CursorId.class)
public class Cursor {
@Enumerated(EnumType.STRING)
@Column(nullable = false)
@Id
private CursorType type;
@Column @Id private String scope;
@Column(nullable = false)
private ZonedDateTime cursorTime;
@Column(nullable = false)
private UpdateAutoTimestamp lastUpdateTime = UpdateAutoTimestamp.create(null);
/** The scope of a global cursor. A global cursor is a cursor that is not specific to one tld. */
public static final String GLOBAL = "GLOBAL";
private Cursor(CursorType type, String scope, DateTime cursorTime) {
this.type = type;
this.scope = scope;
this.cursorTime = DateTimeUtils.toZonedDateTime(cursorTime);
}
// Hibernate requires a default constructor.
private Cursor() {}
/** Constructs a {@link Cursor} object. */
public static Cursor create(CursorType type, String scope, DateTime cursorTime) {
checkNotNull(
scope, "Scope cannot be null. To create a global cursor, use the createGlobal method");
return new Cursor(type, scope, cursorTime);
}
/** Constructs a {@link Cursor} object with a {@link GLOBAL} scope. */
public static Cursor createGlobal(CursorType type, DateTime cursorTime) {
return new Cursor(type, GLOBAL, cursorTime);
}
/** Returns the type of the cursor. */
public CursorType getType() {
return type;
}
/**
* Returns the scope of the cursor. The scope will typically be the tld the cursor is referring
* to. If the cursor is a global cursor, the scope will be {@link GLOBAL}.
*/
public String getScope() {
return scope;
}
/** Returns the time the cursor is set to. */
public DateTime getCursorTime() {
return DateTimeUtils.toJodaDateTime(cursorTime);
}
/** Returns the last time the cursor was updated. */
public DateTime getLastUpdateTime() {
return lastUpdateTime.getTimestamp();
}
static class CursorId extends ImmutableObject implements Serializable {
public CursorType type;
public String scope;
private CursorId() {}
public CursorId(CursorType type, String scope) {
this.type = type;
this.scope = scope;
}
}
}
@@ -0,0 +1,70 @@
// 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.schema.cursor;
import static com.google.appengine.api.search.checkers.Preconditions.checkNotNull;
import static google.registry.model.transaction.TransactionManagerFactory.jpaTm;
import google.registry.model.common.Cursor.CursorType;
import google.registry.schema.cursor.Cursor.CursorId;
import java.util.List;
/** Data access object class for {@link Cursor}. */
public class CursorDao {
public static void save(Cursor cursor) {
jpaTm()
.transact(
() -> {
jpaTm().getEntityManager().merge(cursor);
});
}
public static Cursor load(CursorType type, String scope) {
checkNotNull(scope, "The scope of the cursor to load cannot be null");
checkNotNull(type, "The type of the cursor to load must be specified");
return jpaTm()
.transact(() -> jpaTm().getEntityManager().find(Cursor.class, new CursorId(type, scope)));
}
/** If no scope is given, use {@link Cursor.GLOBAL} as the scope. */
public static Cursor load(CursorType type) {
checkNotNull(type, "The type of the cursor to load must be specified");
return load(type, Cursor.GLOBAL);
}
public static List<Cursor> loadAll() {
return jpaTm()
.transact(
() ->
jpaTm()
.getEntityManager()
.createQuery("SELECT cursor FROM Cursor cursor", Cursor.class)
.getResultList());
}
public static List<Cursor> loadByType(CursorType type) {
checkNotNull(type, "The type of the cursors to load must be specified");
return jpaTm()
.transact(
() ->
jpaTm()
.getEntityManager()
.createQuery(
"SELECT cursor FROM Cursor cursor WHERE cursor.type = :type", Cursor.class)
.setParameter("type", type)
.getResultList());
}
}
@@ -22,6 +22,7 @@
<class>google.registry.model.domain.DomainBase</class>
<class>google.registry.schema.domain.RegistryLock</class>
<class>google.registry.schema.tmch.ClaimsList</class>
<class>google.registry.schema.cursor.Cursor</class>
<class>google.registry.model.transfer.BaseTransferObject</class>
<class>google.registry.schema.tld.PremiumList</class>
<class>google.registry.schema.tld.ReservedList</class>