Refactor Guava functional methods to use lambdas

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=177027488
This commit is contained in:
mcilwain 2017-11-27 09:30:15 -08:00 committed by jianglai
parent 2ae496bfce
commit bbe2584da4
47 changed files with 478 additions and 647 deletions

View file

@ -14,9 +14,7 @@
package google.registry.model;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.RegistrarBillingEntry;
import google.registry.model.billing.RegistrarCredit;
@ -113,15 +111,5 @@ public final class EntityClasses {
SignedMarkRevocationList.class,
TmchCrl.class);
/**
* Function that converts an Objectify-registered class to its Datastore kind name.
*
* <p>Note that this mapping is not one-to-one, since polymorphic subclasses of an entity all have
* the same Datastore kind. (In theory, two distinct top-level entities could also map to the same
* kind since it's just {@code class.getSimpleName()}, but we test against that.)
*/
public static final Function<Class<? extends ImmutableObject>, String> CLASS_TO_KIND_FUNCTION =
(Class<? extends ImmutableObject> clazz) -> Key.getKind(clazz);
private EntityClasses() {}
}

View file

@ -15,7 +15,7 @@
package google.registry.model;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.util.DateTimeUtils.isAtOrAfter;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
@ -160,11 +160,15 @@ public final class EppResourceUtils {
*/
public static <T extends EppResource> Iterable<T> queryNotDeleted(
Class<T> clazz, DateTime now, String filterDefinition, Object filterValue) {
return transform(
ofy().load().type(clazz)
.filter(filterDefinition, filterValue)
.filter("deletionTime >", now.toDate()),
EppResourceUtils.transformAtTime(now));
return ofy()
.load()
.type(clazz)
.filter(filterDefinition, filterValue)
.filter("deletionTime >", now.toDate())
.list()
.stream()
.map(EppResourceUtils.transformAtTime(now))
.collect(toImmutableSet());
}
/**
@ -262,15 +266,13 @@ public final class EppResourceUtils {
(isAtOrAfter(timestamp, resource.getUpdateAutoTimestamp().getTimestamp()))
? new ResultNow<>(resource)
: loadMostRecentRevisionAtTime(resource, timestamp);
return new Result<T>() {
@Override
public T now() {
T loadedResource = loadResult.now();
return loadedResource == null ? null
: (isActive(loadedResource, timestamp)
? cloneProjectedAtTime(loadedResource, timestamp)
: null);
}};
return () -> {
T loadedResource = loadResult.now();
return (loadedResource == null) ? null
: (isActive(loadedResource, timestamp)
? cloneProjectedAtTime(loadedResource, timestamp)
: null);
};
}
/**
@ -290,19 +292,16 @@ public final class EppResourceUtils {
}
final Result<CommitLogMutation> mutationResult =
ofy().load().key(CommitLogMutation.createKey(revision, resourceKey));
return new Result<T>() {
@Override
public T now() {
CommitLogMutation mutation = mutationResult.now();
if (mutation != null) {
return ofy().load().fromEntity(mutation.getEntity());
}
logger.severefmt(
"Couldn't load mutation for revision at %s for %s, falling back to resource."
+ " Revision: %s",
timestamp, resourceKey, revision);
return resource;
return () -> {
CommitLogMutation mutation = mutationResult.now();
if (mutation != null) {
return ofy().load().fromEntity(mutation.getEntity());
}
logger.severefmt(
"Couldn't load mutation for revision at %s for %s, falling back to resource."
+ " Revision: %s",
timestamp, resourceKey, revision);
return resource;
};
}

View file

@ -31,7 +31,6 @@ import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Work;
import google.registry.model.EppResource;
import google.registry.model.ImmutableObject;
import google.registry.model.contact.ContactResource;
@ -447,12 +446,8 @@ public class DomainCommand {
private static <T extends EppResource> ImmutableMap<String, Key<T>> loadByForeignKey(
final Set<String> foreignKeys, final Class<T> clazz, final DateTime now)
throws InvalidReferencesException {
Map<String, ForeignKeyIndex<T>> fkis = ofy().doTransactionless(
new Work<Map<String, ForeignKeyIndex<T>>>() {
@Override
public Map<String, ForeignKeyIndex<T>> run() {
return ForeignKeyIndex.load(clazz, foreignKeys, now);
}});
Map<String, ForeignKeyIndex<T>> fkis =
ofy().doTransactionless(() -> ForeignKeyIndex.load(clazz, foreignKeys, now));
if (!fkis.keySet().equals(foreignKeys)) {
throw new InvalidReferencesException(
clazz, ImmutableSet.copyOf(difference(foreignKeys, fkis.keySet())));

View file

@ -21,7 +21,6 @@ import static google.registry.util.CollectionUtils.isNullOrEmpty;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Work;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import google.registry.model.BackupGroupRoot;
@ -100,17 +99,15 @@ public class DomainApplicationIndex extends BackupGroupRoot {
return ImmutableSet.of();
}
// Perform eventually consistent query, to avoid overenlisting cross entity groups
return ofy().doTransactionless(new Work<ImmutableSet<DomainApplication>>() {
@Override
public ImmutableSet<DomainApplication> run() {
ImmutableSet.Builder<DomainApplication> apps = new ImmutableSet.Builder<>();
for (DomainApplication app : ofy().load().keys(index.getKeys()).values()) {
if (app.getDeletionTime().isAfter(now)) {
apps.add(app);
}
}
return apps.build();
}});
return ofy().doTransactionless(() -> {
ImmutableSet.Builder<DomainApplication> apps = new ImmutableSet.Builder<>();
for (DomainApplication app : ofy().load().keys(index.getKeys()).values()) {
if (app.getDeletionTime().isAfter(now)) {
apps.add(app);
}
}
return apps.build();
});
}
/**

View file

@ -274,26 +274,24 @@ public class Ofy {
* its own retryable read-only transaction.
*/
private <R> Boolean checkIfAlreadySucceeded(final CommitLoggedWork<R> work) {
return work.hasRun() && transactNewReadOnly(new Work<Boolean>() {
@Override
public Boolean run() {
CommitLogManifest manifest = work.getManifest();
if (manifest == null) {
// Work ran but no commit log was created. This might mean that the transaction did not
// write anything to Datastore. We can safely retry because it only reads. (Although the
// transaction might have written a task to a queue, we consider that safe to retry too
// since we generally assume that tasks might be doubly executed.) Alternatively it
// might mean that the transaction wrote to Datastore but turned off commit logs by
// exclusively using save/deleteWithoutBackups() rather than save/delete(). Although we
// have no hard proof that retrying is safe, we use these methods judiciously and it is
// reasonable to assume that if the transaction really did succeed that the retry will
// either be idempotent or will fail with a non-transient error.
return false;
}
return Objects.equals(
union(work.getMutations(), manifest),
ImmutableSet.copyOf(load().ancestor(manifest)));
}});
return work.hasRun() && transactNewReadOnly(() -> {
CommitLogManifest manifest = work.getManifest();
if (manifest == null) {
// Work ran but no commit log was created. This might mean that the transaction did not
// write anything to Datastore. We can safely retry because it only reads. (Although the
// transaction might have written a task to a queue, we consider that safe to retry too
// since we generally assume that tasks might be doubly executed.) Alternatively it
// might mean that the transaction wrote to Datastore but turned off commit logs by
// exclusively using save/deleteWithoutBackups() rather than save/delete(). Although we
// have no hard proof that retrying is safe, we use these methods judiciously and it is
// reasonable to assume that if the transaction really did succeed that the retry will
// either be idempotent or will fail with a non-transient error.
return false;
}
return Objects.equals(
union(work.getMutations(), manifest),
ImmutableSet.copyOf(load().ancestor(manifest)));
});
}
/** A read-only transaction is useful to get strongly consistent reads at a shared timestamp. */

View file

@ -193,9 +193,7 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
* Compare two instances of {@link RegistrarContact} by their email addresses lexicographically.
*/
private static final Comparator<RegistrarContact> CONTACT_EMAIL_COMPARATOR =
comparing(
(RegistrarContact arg) -> arg.getEmailAddress(),
(String leftProperty, String rightProperty) -> leftProperty.compareTo(rightProperty));
comparing(RegistrarContact::getEmailAddress, String::compareTo);
/**
* A caching {@link Supplier} of a clientId to {@link Registrar} map.
@ -208,9 +206,7 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
() ->
ofy()
.doTransactionless(
() -> {
return Maps.uniqueIndex(loadAll(), Registrar::getClientId);
}));
() -> Maps.uniqueIndex(loadAll(), Registrar::getClientId)));
@Parent
Key<EntityGroupRoot> parent = getCrossTldKey();

View file

@ -32,7 +32,6 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.google.common.net.InternetDomainName;
import com.googlecode.objectify.Work;
import google.registry.model.registry.Registry.TldType;
import java.util.Optional;
@ -55,17 +54,14 @@ public final class Registries {
() ->
ofy()
.doTransactionless(
new Work<ImmutableMap<String, TldType>>() {
@Override
public ImmutableMap<String, TldType> run() {
ImmutableMap.Builder<String, TldType> builder =
new ImmutableMap.Builder<>();
for (Registry registry :
ofy().load().type(Registry.class).ancestor(getCrossTldKey())) {
builder.put(registry.getTldStr(), registry.getTldType());
}
return builder.build();
() -> {
ImmutableMap.Builder<String, TldType> builder =
new ImmutableMap.Builder<>();
for (Registry registry :
ofy().load().type(Registry.class).ancestor(getCrossTldKey())) {
builder.put(registry.getTldStr(), registry.getTldType());
}
return builder.build();
}));
}

View file

@ -43,7 +43,6 @@ import com.google.common.collect.Ordering;
import com.google.common.collect.Range;
import com.google.common.net.InternetDomainName;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Work;
import com.googlecode.objectify.annotation.Embed;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
@ -245,15 +244,10 @@ public class Registry extends ImmutableObject implements Buildable {
return Optional.ofNullable(
ofy()
.doTransactionless(
new Work<Registry>() {
@Override
public Registry run() {
return ofy()
.load()
.key(Key.create(getCrossTldKey(), Registry.class, tld))
.now();
}
}));
() -> ofy()
.load()
.key(Key.create(getCrossTldKey(), Registry.class, tld))
.now()));
}
});

View file

@ -37,7 +37,6 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.VoidWork;
import com.googlecode.objectify.Work;
import google.registry.model.registry.Registry;
import google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome;
import google.registry.model.registry.label.PremiumList.PremiumListEntry;
@ -162,28 +161,26 @@ public final class PremiumListUtils {
}
// Save the new PremiumList and revision itself.
PremiumList updated = ofy().transactNew(new Work<PremiumList>() {
@Override
public PremiumList run() {
DateTime now = ofy().getTransactionTime();
// Assert that the premium list hasn't been changed since we started this process.
PremiumList existing = ofy().load()
.type(PremiumList.class)
.parent(getCrossTldKey())
.id(premiumList.getName())
.now();
checkState(
Objects.equals(existing, oldPremiumList.orElse(null)),
"PremiumList was concurrently edited");
PremiumList newList = premiumList.asBuilder()
.setLastUpdateTime(now)
.setCreationTime(
oldPremiumList.isPresent() ? oldPremiumList.get().creationTime : now)
.setRevision(newRevisionKey)
.build();
ofy().save().entities(newList, newRevision);
return newList;
}});
PremiumList updated = ofy().transactNew(() -> {
DateTime now = ofy().getTransactionTime();
// Assert that the premium list hasn't been changed since we started this process.
PremiumList existing = ofy().load()
.type(PremiumList.class)
.parent(getCrossTldKey())
.id(premiumList.getName())
.now();
checkState(
Objects.equals(existing, oldPremiumList.orElse(null)),
"PremiumList was concurrently edited");
PremiumList newList = premiumList.asBuilder()
.setLastUpdateTime(now)
.setCreationTime(
oldPremiumList.isPresent() ? oldPremiumList.get().creationTime : now)
.setRevision(newRevisionKey)
.build();
ofy().save().entities(newList, newRevision);
return newList;
});
// Update the cache.
cachePremiumLists.put(premiumList.getName(), updated);
// Delete the entities under the old PremiumList.

View file

@ -22,7 +22,6 @@ import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.googlecode.objectify.VoidWork;
import com.googlecode.objectify.Work;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import google.registry.model.ImmutableObject;
@ -171,39 +170,37 @@ public class Lock extends ImmutableObject {
// It's important to use transactNew rather than transact, because a Lock can be used to control
// access to resources like GCS that can't be transactionally rolled back. Therefore, the lock
// must be definitively acquired before it is used, even when called inside another transaction.
AcquireResult acquireResult = ofy().transactNew(new Work<AcquireResult>() {
@Override
public AcquireResult run() {
DateTime now = ofy().getTransactionTime();
AcquireResult acquireResult = ofy().transactNew(() -> {
DateTime now = ofy().getTransactionTime();
// Checking if an unexpired lock still exists - if so, the lock can't be acquired.
Lock lock = ofy().load().type(Lock.class).id(lockId).now();
if (lock != null) {
logger.infofmt(
"Loaded existing lock: %s for request: %s", lock.lockId, lock.requestLogId);
}
LockState lockState;
if (lock == null) {
lockState = LockState.FREE;
} else if (isAtOrAfter(now, lock.expirationTime)) {
lockState = LockState.TIMED_OUT;
} else if (!requestStatusChecker.isRunning(lock.requestLogId)) {
lockState = LockState.OWNER_DIED;
} else {
lockState = LockState.IN_USE;
return AcquireResult.create(now, lock, null, lockState);
}
// Checking if an unexpired lock still exists - if so, the lock can't be acquired.
Lock lock = ofy().load().type(Lock.class).id(lockId).now();
if (lock != null) {
logger.infofmt(
"Loaded existing lock: %s for request: %s", lock.lockId, lock.requestLogId);
}
LockState lockState;
if (lock == null) {
lockState = LockState.FREE;
} else if (isAtOrAfter(now, lock.expirationTime)) {
lockState = LockState.TIMED_OUT;
} else if (!requestStatusChecker.isRunning(lock.requestLogId)) {
lockState = LockState.OWNER_DIED;
} else {
lockState = LockState.IN_USE;
return AcquireResult.create(now, lock, null, lockState);
}
Lock newLock = create(
resourceName,
tld,
requestStatusChecker.getLogId(),
now.plus(leaseLength));
// Locks are not parented under an EntityGroupRoot (so as to avoid write contention) and
// don't need to be backed up.
ofy().saveWithoutBackup().entity(newLock);
return AcquireResult.create(now, lock, newLock, lockState);
}});
Lock newLock = create(
resourceName,
tld,
requestStatusChecker.getLogId(),
now.plus(leaseLength));
// Locks are not parented under an EntityGroupRoot (so as to avoid write contention) and
// don't need to be backed up.
ofy().saveWithoutBackup().entity(newLock);
return AcquireResult.create(now, lock, newLock, lockState);
});
logAcquireResult(acquireResult);
lockMetrics.record(resourceName, tld, acquireResult.lockState());

View file

@ -21,7 +21,6 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.primitives.Longs;
import com.googlecode.objectify.Work;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Unindex;
import google.registry.model.annotations.NotBackedUp;
@ -55,18 +54,16 @@ public class ServerSecret extends CrossTldSingleton {
return secret;
}
// Slow path - transactionally create a new ServerSecret (once per app setup).
return ofy().transact(new Work<ServerSecret>() {
@Override
public ServerSecret run() {
// Check again for an existing secret within the transaction to avoid races.
ServerSecret secret = ofy().load().entity(new ServerSecret()).now();
if (secret == null) {
UUID uuid = UUID.randomUUID();
secret = create(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits());
ofy().saveWithoutBackup().entity(secret).now();
}
return secret;
}});
return ofy().transact(() -> {
// Check again for an existing secret within the transaction to avoid races.
ServerSecret secret1 = ofy().load().entity(new ServerSecret()).now();
if (secret1 == null) {
UUID uuid = UUID.randomUUID();
secret1 = create(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits());
ofy().saveWithoutBackup().entity(secret1).now();
}
return secret1;
});
}
});

View file

@ -30,7 +30,6 @@ import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Work;
import com.googlecode.objectify.annotation.EmbedMap;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
@ -95,31 +94,28 @@ public class SignedMarkRevocationList extends ImmutableObject {
() ->
ofy()
.transactNewReadOnly(
new Work<SignedMarkRevocationList>() {
@Override
public SignedMarkRevocationList run() {
Iterable<SignedMarkRevocationList> shards =
ofy()
.load()
.type(SignedMarkRevocationList.class)
.ancestor(getCrossTldKey());
DateTime creationTime =
isEmpty(shards)
? START_OF_TIME
: checkNotNull(
Iterables.get(shards, 0).creationTime, "creationTime");
ImmutableMap.Builder<String, DateTime> revokes =
new ImmutableMap.Builder<>();
for (SignedMarkRevocationList shard : shards) {
revokes.putAll(shard.revokes);
checkState(
creationTime.equals(shard.creationTime),
"Inconsistent creation times: %s vs. %s",
creationTime,
shard.creationTime);
}
return create(creationTime, revokes.build());
() -> {
Iterable<SignedMarkRevocationList> shards =
ofy()
.load()
.type(SignedMarkRevocationList.class)
.ancestor(getCrossTldKey());
DateTime creationTime =
isEmpty(shards)
? START_OF_TIME
: checkNotNull(
Iterables.get(shards, 0).creationTime, "creationTime");
ImmutableMap.Builder<String, DateTime> revokes =
new ImmutableMap.Builder<>();
for (SignedMarkRevocationList shard : shards) {
revokes.putAll(shard.revokes);
checkState(
creationTime.equals(shard.creationTime),
"Inconsistent creation times: %s vs. %s",
creationTime,
shard.creationTime);
}
return create(creationTime, revokes.build());
}));
/** Return a single logical instance that combines all Datastore shards. */

View file

@ -26,7 +26,6 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Work;
import com.googlecode.objectify.annotation.EmbedMap;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
@ -112,15 +111,12 @@ public class ClaimsListShard extends ImmutableObject {
(final Key<ClaimsListShard> key) ->
ofy()
.transactNewReadOnly(
new Work<ClaimsListShard>() {
@Override
public ClaimsListShard run() {
ClaimsListShard claimsListShard = ofy().load().key(key).now();
checkState(
claimsListShard != null,
"Key not found when loading claims list shards.");
return claimsListShard;
}
() -> {
ClaimsListShard claimsListShard = ofy().load().key(key).now();
checkState(
claimsListShard != null,
"Key not found when loading claims list shards.");
return claimsListShard;
}));
// Combine the shards together and return the concatenated ClaimsList.