Collapse conditional UPDATES as well in JPA transactions
This commit is contained in:
parent
43c07077be
commit
820a3d2296
|
@ -508,36 +508,60 @@ public class TransactionProcessor<BUNDLE extends IBaseBundle, BUNDLEENTRY> {
|
|||
/*
|
||||
* Look for duplicate conditional creates and consolidate them
|
||||
*/
|
||||
Map<String, String> ifNoneExistToUuid = new HashMap<>();
|
||||
Map<String, String> keyToUuid = new HashMap<>();
|
||||
for (int index = 0, originalIndex = 0; index < theEntries.size(); index++, originalIndex++) {
|
||||
BUNDLEENTRY nextReqEntry = theEntries.get(index);
|
||||
|
||||
// String encoded = myContext.newJsonParser().encodeResourceToString(myVersionAdapter.getResource(nextReqEntry));
|
||||
// if (encoded.contains("00000011111")) {
|
||||
// ourLog.info("Resource contains 00000011111");
|
||||
// }
|
||||
|
||||
String verb = myVersionAdapter.getEntryRequestVerb(nextReqEntry);
|
||||
String entryUrl = myVersionAdapter.getFullUrl(nextReqEntry);
|
||||
String requestUrl = myVersionAdapter.getEntryRequestUrl(nextReqEntry);
|
||||
String ifNoneExist = myVersionAdapter.getEntryRequestIfNoneExist(nextReqEntry);
|
||||
String key = verb + "|"+ requestUrl + "|" + ifNoneExist;
|
||||
|
||||
// Conditional UPDATE
|
||||
boolean consolidateEntry = false;
|
||||
if ("PUT".equals(verb)) {
|
||||
if (isNotBlank(entryUrl) && isNotBlank(requestUrl)) {
|
||||
int questionMarkIndex = requestUrl.indexOf('?');
|
||||
if (questionMarkIndex >= 0 && requestUrl.length() > (questionMarkIndex+1)) {
|
||||
consolidateEntry = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Conditional CREATE
|
||||
if ("POST".equals(verb)) {
|
||||
if (isNotBlank(entryUrl) && isNotBlank(requestUrl) && isNotBlank(ifNoneExist)) {
|
||||
if (!entryUrl.equals(requestUrl)) {
|
||||
String key = requestUrl + "|" + ifNoneExist; // just in case the ifNoneExist doesn't include the resource type
|
||||
if (!ifNoneExistToUuid.containsKey(key)) {
|
||||
ifNoneExistToUuid.put(key, entryUrl);
|
||||
} else {
|
||||
ourLog.info("Discarding transaction bundle entry {} as it contained a duplicate conditional create: {}", originalIndex, ifNoneExist);
|
||||
theEntries.remove(index);
|
||||
index--;
|
||||
String existingUuid = ifNoneExistToUuid.get(key);
|
||||
for (BUNDLEENTRY nextEntry : theEntries) {
|
||||
IBaseResource nextResource = myVersionAdapter.getResource(nextEntry);
|
||||
for (ResourceReferenceInfo nextReference : myContext.newTerser().getAllResourceReferences(nextResource)) {
|
||||
if (entryUrl.equals(nextReference.getResourceReference().getReferenceElement().getValue())) {
|
||||
nextReference.getResourceReference().setReference(existingUuid);
|
||||
}
|
||||
}
|
||||
consolidateEntry = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (consolidateEntry) {
|
||||
if (!keyToUuid.containsKey(key)) {
|
||||
keyToUuid.put(key, entryUrl);
|
||||
} else {
|
||||
ourLog.info("Discarding transaction bundle entry {} as it contained a duplicate conditional {}", originalIndex, verb);
|
||||
theEntries.remove(index);
|
||||
index--;
|
||||
String existingUuid = keyToUuid.get(key);
|
||||
for (BUNDLEENTRY nextEntry : theEntries) {
|
||||
IBaseResource nextResource = myVersionAdapter.getResource(nextEntry);
|
||||
for (ResourceReferenceInfo nextReference : myContext.newTerser().getAllResourceReferences(nextResource)) {
|
||||
if (entryUrl.equals(nextReference.getResourceReference().getReferenceElement().getValue())) {
|
||||
nextReference.getResourceReference().setReference(existingUuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
|||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.GZipUtil;
|
||||
import ca.uhn.fhir.jpa.dao.r4.FhirSystemDaoR4;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTag;
|
||||
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
|
||||
|
@ -39,6 +40,7 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
@ -176,6 +178,22 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
|||
return myFhirCtx.newXmlParser().parseResource(Bundle.class, req);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionWithDuplicateConditionalCreates2() throws IOException {
|
||||
Bundle request = myFhirCtx.newJsonParser().parseResource(Bundle.class, IOUtils.toString(FhirSystemDaoR4.class.getResourceAsStream("/dstu3/duplicate-conditional-create.json"), Constants.CHARSET_UTF8));
|
||||
|
||||
Bundle response = mySystemDao.transaction(null, request);
|
||||
|
||||
ourLog.info("Response:\n{}", myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(response));
|
||||
|
||||
List<String> responseTypes = response
|
||||
.getEntry()
|
||||
.stream()
|
||||
.map(t -> new org.hl7.fhir.r4.model.IdType(t.getResponse().getLocation()).getResourceType())
|
||||
.collect(Collectors.toList());
|
||||
assertThat(responseTypes.toString(), responseTypes, contains("Patient", "Encounter", "Location", "Location", "Practitioner", "ProcedureRequest", "DiagnosticReport", "Specimen", "Practitioner", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBatchCreateWithBadRead() {
|
||||
Bundle request = new Bundle();
|
||||
|
|
|
@ -1105,6 +1105,64 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionWithDuplicateConditionalUpdates() {
|
||||
Bundle request = new Bundle();
|
||||
request.setType(BundleType.TRANSACTION);
|
||||
|
||||
Practitioner p = new Practitioner();
|
||||
p.setId(IdType.newRandomUuid());
|
||||
p.addIdentifier().setSystem("http://foo").setValue("bar");
|
||||
request.addEntry()
|
||||
.setFullUrl(p.getId())
|
||||
.setResource(p)
|
||||
.getRequest()
|
||||
.setMethod(HTTPVerb.PUT)
|
||||
.setUrl("Practitioner?identifier=http://foo|bar");
|
||||
|
||||
Observation o = new Observation();
|
||||
o.setId(IdType.newRandomUuid());
|
||||
o.getPerformerFirstRep().setReference(p.getId());
|
||||
request.addEntry()
|
||||
.setFullUrl(o.getId())
|
||||
.setResource(o)
|
||||
.getRequest()
|
||||
.setMethod(HTTPVerb.POST)
|
||||
.setUrl("Observation/");
|
||||
|
||||
p = new Practitioner();
|
||||
p.setId(IdType.newRandomUuid());
|
||||
p.addIdentifier().setSystem("http://foo").setValue("bar");
|
||||
request.addEntry()
|
||||
.setFullUrl(p.getId())
|
||||
.setResource(p)
|
||||
.getRequest()
|
||||
.setMethod(HTTPVerb.PUT)
|
||||
.setUrl("Practitioner?identifier=http://foo|bar");
|
||||
|
||||
o = new Observation();
|
||||
o.setId(IdType.newRandomUuid());
|
||||
o.getPerformerFirstRep().setReference(p.getId());
|
||||
request.addEntry()
|
||||
.setFullUrl(o.getId())
|
||||
.setResource(o)
|
||||
.getRequest()
|
||||
.setMethod(HTTPVerb.POST)
|
||||
.setUrl("Observation/");
|
||||
|
||||
Bundle response = mySystemDao.transaction(null, request);
|
||||
|
||||
ourLog.info("Response:\n{}", myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(response));
|
||||
|
||||
List<String> responseTypes = response
|
||||
.getEntry()
|
||||
.stream()
|
||||
.map(t -> new IdType(t.getResponse().getLocation()).getResourceType())
|
||||
.collect(Collectors.toList());
|
||||
assertThat(responseTypes.toString(), responseTypes, contains("Practitioner", "Observation", "Observation"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionCreateInlineMatchUrlWithTwoMatches() {
|
||||
String methodName = "testTransactionCreateInlineMatchUrlWithTwoMatches";
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue