Use replica db for non-mutating epp flows (#2478)

* Use replica db for non-mutating epp flows

* Add a test
This commit is contained in:
Weimin Yu
2024-06-13 23:18:56 +00:00
committed by GitHub
parent 34694b4aef
commit d000a5dff8
4 changed files with 123 additions and 21 deletions
@@ -15,6 +15,7 @@
package google.registry.flows;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.common.base.Strings;
@@ -37,6 +38,7 @@ import google.registry.model.host.HostHistory;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.IsolationLevel;
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
import google.registry.persistence.transaction.JpaTransactionManager;
import java.lang.annotation.Documented;
import java.util.Optional;
import javax.inject.Qualifier;
@@ -191,6 +193,16 @@ public class FlowModule {
}
}
@Provides
@FlowScope
static JpaTransactionManager provideJpaTm(Class<? extends Flow> flowClass) {
if (MutatingFlow.class.isAssignableFrom(flowClass)) {
return tm();
} else {
return replicaTm();
}
}
@Provides
@FlowScope
static ResourceCommand provideResourceCommand(EppInput eppInput) {
@@ -14,7 +14,6 @@
package google.registry.flows;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.xml.XmlTransformer.prettyPrint;
import com.google.common.flogger.FluentLogger;
@@ -28,6 +27,7 @@ import google.registry.model.eppcommon.Trid;
import google.registry.model.eppoutput.EppOutput;
import google.registry.monitoring.whitebox.EppMetric;
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
import google.registry.persistence.transaction.JpaTransactionManager;
import java.util.Optional;
import javax.inject.Inject;
import javax.inject.Provider;
@@ -52,6 +52,8 @@ public class FlowRunner {
@Inject SessionMetadata sessionMetadata;
@Inject Trid trid;
@Inject FlowReporter flowReporter;
@Inject JpaTransactionManager jpaTransactionManager;
@Inject FlowRunner() {}
/** Runs the EPP flow, and records metrics on the given builder. */
@@ -77,26 +79,24 @@ public class FlowRunner {
return EppOutput.create(flowProvider.get().run());
}
try {
// TODO(mcilwain/weiminyu): Use transactReadOnly() here for TransactionalFlow and transact()
// for MutatingFlow.
return tm().transact(
isolationLevelOverride.orElse(null),
() -> {
try {
EppOutput output = EppOutput.create(flowProvider.get().run());
if (isDryRun) {
throw new DryRunException(output);
}
if (flowClass.equals(LoginFlow.class)) {
// In LoginFlow, registrarId isn't known until after the flow executes, so save
// it then.
eppMetricBuilder.setRegistrarId(sessionMetadata.getRegistrarId());
}
return output;
} catch (EppException e) {
throw new EppRuntimeException(e);
}
});
return jpaTransactionManager.transact(
isolationLevelOverride.orElse(null),
() -> {
try {
EppOutput output = EppOutput.create(flowProvider.get().run());
if (isDryRun) {
throw new DryRunException(output);
}
if (flowClass.equals(LoginFlow.class)) {
// In LoginFlow, registrarId isn't known until after the flow executes, so save
// it then.
eppMetricBuilder.setRegistrarId(sessionMetadata.getRegistrarId());
}
return output;
} catch (EppException e) {
throw new EppRuntimeException(e);
}
});
} catch (DryRunException e) {
return e.output;
} catch (EppRuntimeException e) {