Add missing transaction for whois lookups (#1614)

* Add missing transaction for whois lookups

Nameserver whois lookups are failing under SQL for hosts with superordinate
domains because the query in this case is not done in a transaction.  We
missed this during testing because a) we didn't have a test for lookups of
hosts with superordinate domains and b) we missed converting
NameserverWhoisResponseTest to a DualDatabaseTest.

This PR fixes the problem and adds the requisite testing.

* Use a single transaction to get host registrars

* Replace streaming with Maps.toMap()
This commit is contained in:
Michael Muller
2022-05-04 07:29:45 -04:00
committed by GitHub
parent e24dba7d2b
commit 05fcf73452
3 changed files with 62 additions and 6 deletions
@@ -16,9 +16,12 @@ package google.registry.whois;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.net.InetAddresses;
import google.registry.model.host.HostResource;
import google.registry.model.registrar.Registrar;
@@ -44,14 +47,27 @@ final class NameserverWhoisResponse extends WhoisResponseImpl {
@Override
public WhoisResponseResults getResponse(boolean preferUnicode, String disclaimer) {
// If we have subordinate hosts, load their registrar ids in a single transaction up-front.
ImmutableList<HostResource> subordinateHosts =
hosts.stream().filter(HostResource::isSubordinate).collect(toImmutableList());
ImmutableMap<HostResource, String> hostRegistrars =
subordinateHosts.isEmpty()
? ImmutableMap.of()
: tm().transact(
() ->
Maps.toMap(
subordinateHosts.iterator(),
host ->
tm().loadByKey(host.getSuperordinateDomain())
.cloneProjectedAtTime(getTimestamp())
.getCurrentSponsorRegistrarId()));
BasicEmitter emitter = new BasicEmitter();
for (int i = 0; i < hosts.size(); i++) {
HostResource host = hosts.get(i);
String registrarId =
host.isSubordinate()
? tm().loadByKey(host.getSuperordinateDomain())
.cloneProjectedAtTime(getTimestamp())
.getCurrentSponsorRegistrarId()
? hostRegistrars.get(host)
: host.getPersistedCurrentSponsorRegistrarId();
Optional<Registrar> registrar = Registrar.loadByRegistrarIdCached(registrarId);
checkState(registrar.isPresent(), "Could not load registrar %s", registrarId);