Updates to transaction processing
This commit is contained in:
parent
6e41f90bf9
commit
7896887f67
|
@ -508,60 +508,65 @@ public class TransactionProcessor<BUNDLE extends IBaseBundle, BUNDLEENTRY> {
|
|||
/*
|
||||
* Look for duplicate conditional creates and consolidate them
|
||||
*/
|
||||
Map<String, String> keyToUuid = new HashMap<>();
|
||||
final HashMap<String, String> keyToUuid = new HashMap<>();
|
||||
final IdentityHashMap<IBaseResource, String> identityToUuid = new IdentityHashMap<>();
|
||||
for (int index = 0, originalIndex = 0; index < theEntries.size(); index++, originalIndex++) {
|
||||
BUNDLEENTRY nextReqEntry = theEntries.get(index);
|
||||
IBaseResource resource = myVersionAdapter.getResource(nextReqEntry);
|
||||
if (resource != null) {
|
||||
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;
|
||||
|
||||
// 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 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)) {
|
||||
consolidateEntry = true;
|
||||
// Conditional CREATE
|
||||
if ("POST".equals(verb)) {
|
||||
if (isNotBlank(entryUrl) && isNotBlank(requestUrl) && isNotBlank(ifNoneExist)) {
|
||||
if (!entryUrl.equals(requestUrl)) {
|
||||
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);
|
||||
if (consolidateEntry) {
|
||||
if (!keyToUuid.containsKey(key)) {
|
||||
keyToUuid.put(key, entryUrl);
|
||||
identityToUuid.put(resource, 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)) {
|
||||
// We're interested in any references directly to the placeholder ID, but also
|
||||
// references that have a resource target that has the placeholder ID.
|
||||
String nextReferenceId = nextReference.getResourceReference().getReferenceElement().getValue();
|
||||
if (isBlank(nextReferenceId) && nextReference.getResourceReference().getResource() != null) {
|
||||
nextReferenceId = nextReference.getResourceReference().getResource().getIdElement().getValue();
|
||||
}
|
||||
if (entryUrl.equals(nextReferenceId)) {
|
||||
nextReference.getResourceReference().setReference(existingUuid);
|
||||
nextReference.getResourceReference().setResource(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1105,6 +1105,65 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionWithDuplicateConditionalCreatesWithResourceLinkReference() {
|
||||
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.POST)
|
||||
.setUrl("Practitioner/")
|
||||
.setIfNoneExist("Practitioner?identifier=http://foo|bar");
|
||||
|
||||
Observation o = new Observation();
|
||||
o.setId(IdType.newRandomUuid());
|
||||
o.getPerformerFirstRep().setResource(p);
|
||||
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.POST)
|
||||
.setUrl("Practitioner/")
|
||||
.setIfNoneExist("Practitioner?identifier=http://foo|bar");
|
||||
|
||||
o = new Observation();
|
||||
o.setId(IdType.newRandomUuid());
|
||||
o.getPerformerFirstRep().setResource(p);
|
||||
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 testTransactionWithDuplicateConditionalUpdates() {
|
||||
Bundle request = new Bundle();
|
||||
|
|
|
@ -157,34 +157,6 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testManualPagingLinkOffsetDoesntReturnBeyondEnd() {
|
||||
myDaoConfig.setSearchPreFetchThresholds(Lists.newArrayList(10, 1000));
|
||||
|
||||
for (int i = 0; i < 50; i++) {
|
||||
Organization o = new Organization();
|
||||
o.setId("O" + i);
|
||||
o.setName("O" + i);
|
||||
ourClient.update().resource(o).execute().getId().toUnqualifiedVersionless();
|
||||
}
|
||||
|
||||
Bundle output = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.count(3)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(output));
|
||||
|
||||
String linkNext = output.getLink("next").getUrl();
|
||||
linkNext = linkNext.replaceAll("_getpagesoffset=[0-9]+", "_getpagesoffset=3300");
|
||||
assertThat(linkNext, containsString("_getpagesoffset=3300"));
|
||||
|
||||
Bundle nextPageBundle = ourClient.loadPage().byUrl(linkNext).andReturnBundle(Bundle.class).execute();
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(nextPageBundle));
|
||||
assertEquals(null, nextPageBundle.getLink("next"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchLinksWorkWithIncludes() {
|
||||
|
@ -228,6 +200,36 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testManualPagingLinkOffsetDoesntReturnBeyondEnd() {
|
||||
myDaoConfig.setSearchPreFetchThresholds(Lists.newArrayList(10, 1000));
|
||||
|
||||
for (int i = 0; i < 50; i++) {
|
||||
Organization o = new Organization();
|
||||
o.setId("O" + i);
|
||||
o.setName("O" + i);
|
||||
ourClient.update().resource(o).execute().getId().toUnqualifiedVersionless();
|
||||
}
|
||||
|
||||
Bundle output = ourClient
|
||||
.search()
|
||||
.forResource("Organization")
|
||||
.count(3)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(output));
|
||||
|
||||
String linkNext = output.getLink("next").getUrl();
|
||||
linkNext = linkNext.replaceAll("_getpagesoffset=[0-9]+", "_getpagesoffset=3300");
|
||||
assertThat(linkNext, containsString("_getpagesoffset=3300"));
|
||||
|
||||
Bundle nextPageBundle = ourClient.loadPage().byUrl(linkNext).andReturnBundle(Bundle.class).execute();
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(nextPageBundle));
|
||||
assertEquals(null, nextPageBundle.getLink("next"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchFetchPageBeyondEnd() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
|
|
Loading…
Reference in New Issue