Skip to content

Commit

Permalink
Merge pull request #763 from CDCgov/story-672-no_rs_history_api
Browse files Browse the repository at this point in the history
672: Don't Call RS History API for Sent Order on Order Endpoint
  • Loading branch information
halprin authored Jan 10, 2024
2 parents 5cc44a6 + 9daddfc commit 78ee775
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 217 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import gov.hhs.cdc.trustedintermediary.external.slf4j.DeployedLogger;
import gov.hhs.cdc.trustedintermediary.external.slf4j.LocalLogger;
import gov.hhs.cdc.trustedintermediary.organizations.OrganizationsSettings;
import gov.hhs.cdc.trustedintermediary.utils.SyncRetryTask;
import gov.hhs.cdc.trustedintermediary.wrappers.AuthEngine;
import gov.hhs.cdc.trustedintermediary.wrappers.Cache;
import gov.hhs.cdc.trustedintermediary.wrappers.HapiFhir;
Expand Down Expand Up @@ -88,6 +87,5 @@ private static void registerClasses() {
ApplicationContext.register(
OrganizationsSettings.class, OrganizationsSettings.getInstance());
ApplicationContext.register(MetricMetadata.class, LoggingMetricMetadata.getInstance());
ApplicationContext.register(SyncRetryTask.class, SyncRetryTask.getInstance());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,27 +91,13 @@ public void updateMetadataForSentOrder(String receivedSubmissionId, String sentS
}

PartnerMetadata partnerMetadata = optionalPartnerMetadata.get();
if (!sentSubmissionId.equals(partnerMetadata.sentSubmissionId())) {
logger.logInfo("Updating metadata with sentSubmissionId: {}", sentSubmissionId);
partnerMetadata = partnerMetadata.withSentSubmissionId(sentSubmissionId);
partnerMetadataStorage.saveMetadata(partnerMetadata);
}

logger.logInfo(
"Looking up receiver name from RS history API for sentSubmissionId: {}",
sentSubmissionId);
String receiver;
try {
String bearerToken = rsclient.getRsToken();
String responseBody = rsclient.requestHistoryEndpoint(sentSubmissionId, bearerToken);
receiver = getReceiverName(responseBody);
} catch (ReportStreamEndpointClientException | FormatterProcessingException e) {
throw new PartnerMetadataException(
"Unable to retrieve metadata from RS history API", e);
if (sentSubmissionId.equals(partnerMetadata.sentSubmissionId())) {
return;
}

logger.logInfo("Updating metadata with receiver: {}", receiver);
partnerMetadata = partnerMetadata.withReceiver(receiver);
logger.logInfo("Updating metadata with sentSubmissionId: {}", sentSubmissionId);
partnerMetadata = partnerMetadata.withSentSubmissionId(sentSubmissionId);
partnerMetadataStorage.saveMetadata(partnerMetadata);
}

Expand All @@ -125,10 +111,26 @@ public Optional<PartnerMetadata> getMetadata(String receivedSubmissionId)
}

PartnerMetadata partnerMetadata = optionalPartnerMetadata.get();
if (partnerMetadata.receiver() == null && partnerMetadata.sentSubmissionId() != null) {
logger.logInfo("Receiver name not found in metadata, looking up from RS history API");
updateMetadataForSentOrder(receivedSubmissionId, partnerMetadata.sentSubmissionId());
return partnerMetadataStorage.readMetadata(receivedSubmissionId);
var sentSubmissionId = partnerMetadata.sentSubmissionId();
if (partnerMetadata.receiver() == null && sentSubmissionId != null) {
logger.logInfo(
"Receiver name not found in metadata, looking up {} from RS history API",
sentSubmissionId);

String receiver;
try {
String bearerToken = rsclient.getRsToken();
String responseBody =
rsclient.requestHistoryEndpoint(sentSubmissionId, bearerToken);
receiver = getReceiverName(responseBody);
} catch (ReportStreamEndpointClientException | FormatterProcessingException e) {
throw new PartnerMetadataException(
"Unable to retrieve metadata from RS history API", e);
}

logger.logInfo("Updating metadata with receiver: {}", receiver);
partnerMetadata = partnerMetadata.withReceiver(receiver);
partnerMetadataStorage.saveMetadata(partnerMetadata);
}

return Optional.of(partnerMetadata);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@
import gov.hhs.cdc.trustedintermediary.etor.metadata.EtorMetadataStep;
import gov.hhs.cdc.trustedintermediary.etor.metadata.PartnerMetadataException;
import gov.hhs.cdc.trustedintermediary.etor.metadata.PartnerMetadataOrchestrator;
import gov.hhs.cdc.trustedintermediary.utils.RetryFailedException;
import gov.hhs.cdc.trustedintermediary.utils.SyncRetryTask;
import gov.hhs.cdc.trustedintermediary.wrappers.Logger;
import gov.hhs.cdc.trustedintermediary.wrappers.MetricMetadata;
import java.util.concurrent.Callable;
import javax.inject.Inject;

/** The overall logic to receive, convert to OML, and subsequently send a lab order. */
Expand All @@ -18,7 +15,6 @@ public class SendOrderUseCase {
@Inject MetricMetadata metadata;
@Inject PartnerMetadataOrchestrator partnerMetadataOrchestrator;
@Inject Logger logger;
@Inject SyncRetryTask retryTask;

private SendOrderUseCase() {}

Expand Down Expand Up @@ -66,15 +62,11 @@ private void saveSentOrderSubmissionId(String receivedSubmissionId, String sentS
"Received and/or sent submissionId is null so not saving metadata for sent order");
return;
}
Callable<Void> task =
() -> {
partnerMetadataOrchestrator.updateMetadataForSentOrder(
receivedSubmissionId, sentSubmissionId);
return null;
};

try {
retryTask.retry(task, 3, 1000);
} catch (RetryFailedException e) {
partnerMetadataOrchestrator.updateMetadataForSentOrder(
receivedSubmissionId, sentSubmissionId);
} catch (PartnerMetadataException e) {
logger.logError(
"Unable to update metadata for received submissionId "
+ receivedSubmissionId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,22 +147,13 @@ class PartnerMetadataOrchestratorTest extends Specification {
given:
def receivedSubmissionId = "receivedSubmissionId"
def sentSubmissionId = "sentSubmissionId"
def bearerToken = "token"
def receiver = "org.service"
def rsHistoryApiResponse = "{\"destinations\": [{\"organization_id\": \"org\", \"service\": \"service\"}]}"
def partnerMetadata = new PartnerMetadata(receivedSubmissionId, "sender", Instant.now(), "hash")
def updatedPartnerMetadata = partnerMetadata.withSentSubmissionId(sentSubmissionId).withReceiver(receiver)

mockFormatter.convertJsonToObject(rsHistoryApiResponse, _ as TypeReference) >> [destinations: [
[organization_id: "org", service: "service"]
]]
def updatedPartnerMetadata = partnerMetadata.withSentSubmissionId(sentSubmissionId)

when:
PartnerMetadataOrchestrator.getInstance().updateMetadataForSentOrder(receivedSubmissionId, sentSubmissionId)

then:
1 * mockClient.getRsToken() >> bearerToken
1 * mockClient.requestHistoryEndpoint(sentSubmissionId, bearerToken) >> rsHistoryApiResponse
1 * mockPartnerMetadataStorage.readMetadata(receivedSubmissionId) >> Optional.of(partnerMetadata)
1 * mockPartnerMetadataStorage.saveMetadata(updatedPartnerMetadata)
}
Expand All @@ -179,43 +170,43 @@ class PartnerMetadataOrchestratorTest extends Specification {
0 * mockPartnerMetadataStorage.readMetadata(receivedSubmissionId)
}

def "updateMetadataForSentOrder throws PartnerMetadataException on client error"() {
def "getMetadata throws PartnerMetadataException on client error"() {
given:
def receivedSubmissionId = "receivedSubmissionId"
def sentSubmissionId = "sentSubmissionId"
def partnerMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, "sender", "receiver", Instant.now(), "hash")
def partnerMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, "sender", null, Instant.now(), "hash")

mockPartnerMetadataStorage.readMetadata(receivedSubmissionId) >> Optional.of(partnerMetadata)
mockClient.getRsToken() >> "token"
mockClient.requestHistoryEndpoint(_ as String, _ as String) >> { throw new ReportStreamEndpointClientException("Client error", new Exception()) }

when:
PartnerMetadataOrchestrator.getInstance().updateMetadataForSentOrder(receivedSubmissionId, sentSubmissionId)
PartnerMetadataOrchestrator.getInstance().getMetadata(receivedSubmissionId)

then:
thrown(PartnerMetadataException)
}

def "updateMetadataForSentOrder throws PartnerMetadataException on formatter error"() {
def "getMetadata throws PartnerMetadataException on formatter error"() {
given:
def receivedSubmissionId = "receivedSubmissionId"
def sentSubmissionId = "sentSubmissionId"
def rsHistoryApiResponse = "{\"destinations\": [{\"organization_id\": \"org\", \"service\": \"service\"}]}"
def partnerMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, "sender", "receiver", Instant.now(), "hash")
def partnerMetadata = new PartnerMetadata(receivedSubmissionId, sentSubmissionId, "sender", null, Instant.now(), "hash")

mockPartnerMetadataStorage.readMetadata(receivedSubmissionId) >> Optional.of(partnerMetadata)
mockClient.getRsToken() >> "token"
mockClient.requestHistoryEndpoint(_ as String, _ as String) >> rsHistoryApiResponse
mockFormatter.convertJsonToObject(rsHistoryApiResponse, _ as TypeReference) >> { throw new FormatterProcessingException("Formatter error", new Exception()) }

when:
PartnerMetadataOrchestrator.getInstance().updateMetadataForSentOrder(receivedSubmissionId, sentSubmissionId)
PartnerMetadataOrchestrator.getInstance().getMetadata(receivedSubmissionId)

then:
thrown(PartnerMetadataException)
}

def "getMetadata retrieves metadata successfully"() {
def "getMetadata retrieves metadata successfully with the sender already filled"() {
given:
def receivedSubmissionId = "receivedSubmissionId"
def metadata = new PartnerMetadata(receivedSubmissionId, "sentSubmissionId", "sender", "receiver", Instant.now(), "hash")
Expand All @@ -227,6 +218,7 @@ class PartnerMetadataOrchestratorTest extends Specification {
result.isPresent()
result.get() == metadata
1 * mockPartnerMetadataStorage.readMetadata(receivedSubmissionId) >> Optional.of(metadata)
0 * mockClient.requestHistoryEndpoint(_, _)
}

def "getMetadata retrieves metadata successfully when receiver is present and sentSubmissionId is missing"() {
Expand Down Expand Up @@ -267,9 +259,8 @@ class PartnerMetadataOrchestratorTest extends Specification {
then:
result.isPresent()
result.get() == expectedMetadata
2 * mockPartnerMetadataStorage.readMetadata(receivedSubmissionId) >> Optional.of(missingReceiverMetadata)
1 * mockPartnerMetadataStorage.readMetadata(receivedSubmissionId) >> Optional.of(missingReceiverMetadata)
1 * mockPartnerMetadataStorage.saveMetadata(expectedMetadata)
1 * mockPartnerMetadataStorage.readMetadata(receivedSubmissionId) >> Optional.of(expectedMetadata)
}

def "getReceiverName returns correct receiver name from valid JSON response"() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,16 @@ import gov.hhs.cdc.trustedintermediary.context.TestApplicationContext
import gov.hhs.cdc.trustedintermediary.etor.metadata.EtorMetadataStep
import gov.hhs.cdc.trustedintermediary.etor.metadata.PartnerMetadataException
import gov.hhs.cdc.trustedintermediary.etor.metadata.PartnerMetadataOrchestrator
import gov.hhs.cdc.trustedintermediary.utils.RetryFailedException
import gov.hhs.cdc.trustedintermediary.utils.SyncRetryTask
import gov.hhs.cdc.trustedintermediary.wrappers.Logger
import gov.hhs.cdc.trustedintermediary.wrappers.MetricMetadata
import spock.lang.Specification

import java.util.concurrent.Callable

class SendOrderUsecaseTest extends Specification {

def mockOrchestrator = Mock(PartnerMetadataOrchestrator)
def mockConverter = Mock(OrderConverter)
def mockSender = Mock(OrderSender)
def mockLogger = Mock(Logger)
def mockRetryTask = Mock(SyncRetryTask)

def setup() {
TestApplicationContext.reset()
Expand All @@ -30,7 +25,6 @@ class SendOrderUsecaseTest extends Specification {
TestApplicationContext.register(OrderConverter, mockConverter)
TestApplicationContext.register(OrderSender, mockSender)
TestApplicationContext.register(Logger, mockLogger)
TestApplicationContext.register(SyncRetryTask, mockRetryTask)
}

def "send sends successfully"() {
Expand All @@ -42,8 +36,6 @@ class SendOrderUsecaseTest extends Specification {
def mockOrder = new OrderMock(null, null, null)
def mockOmlOrder = Mock(Order)

mockRetryTask.retry({ it.call(); true }, _, _) >> { Callable<Void> task, int retries, int delay -> task.call(); true }

TestApplicationContext.injectRegisteredImplementations()

when:
Expand Down Expand Up @@ -100,14 +92,14 @@ class SendOrderUsecaseTest extends Specification {
1 * mockConverter.convertMetadataToOmlOrder(order) >> omlOrder
1 * mockConverter.addContactSectionToPatientResource(omlOrder) >> omlOrder
1 * mockSender.sendOrder(omlOrder) >> Optional.of("sentId")
1 * mockRetryTask.retry(_, _, _)
noExceptionThrown()
}

def "convertAndSend logs error and continues when retryTask throws exception"() {
def "convertAndSend logs error and continues when updating the metadata for the sent order throws exception"() {
given:
def order = Mock(Order)
def omlOrder = Mock(Order)
def partnerMetadataException = new PartnerMetadataException("Error")
mockOrchestrator.updateMetadataForSentOrder("receivedId", _) >> { throw partnerMetadataException}
TestApplicationContext.injectRegisteredImplementations()

when:
Expand All @@ -117,9 +109,7 @@ class SendOrderUsecaseTest extends Specification {
1 * mockConverter.convertMetadataToOmlOrder(order) >> omlOrder
1 * mockConverter.addContactSectionToPatientResource(omlOrder) >> omlOrder
1 * mockSender.sendOrder(omlOrder) >> Optional.of("sentId")
1 * mockRetryTask.retry(_, _, _) >> { throw new RetryFailedException("Error", new Exception()) }
1 * mockLogger.logError(_, _)
noExceptionThrown()
1 * mockLogger.logError(_, partnerMetadataException)
}

def "convertAndSend logs event when submissionId is null"() {
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit 78ee775

Please sign in to comment.