Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3156 multiple tag race condition #3297

Merged
merged 26 commits into from
Jan 31, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ public Object answer(InvocationOnMock invocationOnMock) throws Throwable {

AtomicInteger counter = new AtomicInteger();
for (int i = 0; i < threads; i++) {
service.submit(() -> {
service.submit(() -> {
try {
TagDefinition retTag = myTestDao.getTagOrNull(transactionDetails, tagType, scheme, term, label);
outcomes.put(retTag.hashCode(), retTag);
Expand Down Expand Up @@ -333,7 +333,7 @@ public void getTagOrNull_failingForever_throwsInternalErrorAndLogsWarnings() {
List<ILoggingEvent> events = appenderCaptor.getAllValues();
assertEquals(10, events.size());
for (int i = 0; i < 10; i++) {
String actualMsg = events.get(0).getMessage();
String actualMsg = events.get(i).getMessage();
assertEquals(
"Tag read/write failed: "
+ exMsg
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.BundleBuilder;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.DateType;
import org.hl7.fhir.r4.model.DecimalType;
import org.hl7.fhir.r4.model.Encounter;
Expand All @@ -44,9 +46,14 @@

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static org.hamcrest.MatcherAssert.assertThat;
Expand Down Expand Up @@ -968,6 +975,57 @@ public void testCreateWithNormalizedQuantityStorageSupported_SmallerThanCanonica
assertEquals(1, ids.size());
}

@Test
public void testResourceWithTagCreationNoFailures() throws ExecutionException, InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(5);
try {
Coding tag = new Coding();
tag.setCode("code123");
tag.setDisplay("Display Name");
tag.setSystem("System123");

Patient p = new Patient();
IIdType id = myPatientDao.create(p).getId();
jamesagnew marked this conversation as resolved.
Show resolved Hide resolved

List<Future<String>> futures = new ArrayList<>();
for (int i = 0; i < 50; i++) {
Patient updatePatient = new Patient();
updatePatient.setId(id.toUnqualifiedVersionless());
updatePatient.addIdentifier().setSystem("" + i);
updatePatient.setActive(true);
updatePatient.getMeta().addTag(tag);

int finalI = i;
Future<String> future = pool.submit(() -> {
ourLog.info("Starting update {}", finalI);
try {
try {
myPatientDao.update(updatePatient);
} catch (ResourceVersionConflictException e) {
assertEquals("The operation has failed with a version constraint failure. This generally means that two clients/threads were trying to update the same resource at the same time, and this request was chosen as the failing request.", e.getMessage());
}
} catch (Exception e) {
ourLog.error("Failure", e);
return e.toString();
}
ourLog.info("Finished update {}", finalI);
return null;
});
futures.add(future);
}

for (Future<String> next : futures) {
String nextError = next.get();
if (StringUtils.isNotBlank(nextError)) {
fail(nextError);
}
}

} finally {
pool.shutdown();
}
}

@Test
public void testCreateWithNormalizedQuantitySearchNotSupported_SmallerThanCanonicalUnit() {

Expand Down