diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml
index 8fb97f3a25b..47494c203c2 100644
--- a/hapi-deployable-pom/pom.xml
+++ b/hapi-deployable-pom/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
@@ -129,8 +129,11 @@
check
- true
true
+ true
+ ${maven.multiModuleProjectDirectory}/src/checkstyle/checkstyle_suppressions.xml
+ true
+ true
true
${maven.multiModuleProjectDirectory}/src/checkstyle/checkstyle.xml
diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml
index 2e056223602..4a78ea60bf1 100644
--- a/hapi-fhir-android/pom.xml
+++ b/hapi-fhir-android/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml
index a54df006844..cce36d7979e 100644
--- a/hapi-fhir-base/pom.xml
+++ b/hapi-fhir-base/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/Constants.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/Constants.java
index b66f1b4438d..c157847e894 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/Constants.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/Constants.java
@@ -145,6 +145,9 @@ public class Constants {
public static final String HEADER_SUFFIX_CT_UTF_8 = "; charset=UTF-8";
public static final String HEADERVALUE_CORS_ALLOW_METHODS_ALL = "GET, POST, PUT, DELETE, OPTIONS";
public static final String HEADER_REWRITE_HISTORY = "X-Rewrite-History";
+ public static final String HEADER_RETRY_ON_VERSION_CONFLICT = "X-Retry-On-Version-Conflict";
+ public static final String HEADER_MAX_RETRIES = "max-retries";
+ public static final String HEADER_RETRY = "retry";
public static final Map HTTP_STATUS_NAMES;
public static final String LINK_FHIR_BASE = "fhir-base";
public static final String LINK_FIRST = "first";
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/system/HapiSystemProperties.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/system/HapiSystemProperties.java
index 6f50600d54d..8817045a20a 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/system/HapiSystemProperties.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/system/HapiSystemProperties.java
@@ -1,5 +1,25 @@
package ca.uhn.fhir.system;
+/*-
+ * #%L
+ * HAPI FHIR - Core Library
+ * %%
+ * Copyright (C) 2014 - 2022 Smile CDR, Inc.
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
import org.apache.commons.lang3.time.DateUtils;
public final class HapiSystemProperties {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionEnum.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionEnum.java
index 9bf12999bf2..90afa7d8603 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionEnum.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionEnum.java
@@ -106,6 +106,7 @@ public enum VersionEnum {
V6_1_3,
V6_1_4,
V6_2_0,
+ V6_2_1,
V6_3_0
;
diff --git a/hapi-fhir-bom/pom.xml b/hapi-fhir-bom/pom.xml
index 78cab5db542..26dece1bad3 100644
--- a/hapi-fhir-bom/pom.xml
+++ b/hapi-fhir-bom/pom.xml
@@ -3,14 +3,14 @@
4.0.0
ca.uhn.hapi.fhir
hapi-fhir-bom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
pom
HAPI FHIR BOM
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-checkstyle/pom.xml b/hapi-fhir-checkstyle/pom.xml
index d5c61832f60..102c8d05f98 100644
--- a/hapi-fhir-checkstyle/pom.xml
+++ b/hapi-fhir-checkstyle/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml
index bd262c3d80e..4438b06e2a5 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml
+++ b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/ValidationSupportChainCreator.java b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/ValidationSupportChainCreator.java
index cd49f9db28f..52dd02172e1 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/ValidationSupportChainCreator.java
+++ b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/ValidationSupportChainCreator.java
@@ -48,7 +48,7 @@ public class ValidationSupportChainCreator {
chain.addValidationSupport(localFileValidationSupport);
chain.addValidationSupport(new SnapshotGeneratingValidationSupport(ctx));
} catch (IOException e) {
- throw new RuntimeException(Msg.code(2141) + "Failed to load local profile.", e);
+ throw new RuntimeException(Msg.code(2207) + "Failed to load local profile.", e);
}
}
if (commandLine.hasOption("r")) {
diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml
index 3bb5ed16fa6..c06f3c80624 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml
+++ b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-fhir-cli
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml
index 2faba268a5e..ce2ded17b1c 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml
+++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../../hapi-deployable-pom
diff --git a/hapi-fhir-cli/pom.xml b/hapi-fhir-cli/pom.xml
index 68cc1f434ca..70082a0bfb5 100644
--- a/hapi-fhir-cli/pom.xml
+++ b/hapi-fhir-cli/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-client-okhttp/pom.xml b/hapi-fhir-client-okhttp/pom.xml
index 3b4ff982dc9..acacb532a70 100644
--- a/hapi-fhir-client-okhttp/pom.xml
+++ b/hapi-fhir-client-okhttp/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml
index 53d739dfb25..e782b4908bf 100644
--- a/hapi-fhir-client/pom.xml
+++ b/hapi-fhir-client/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-converter/pom.xml b/hapi-fhir-converter/pom.xml
index bd6b3a626cc..578544de925 100644
--- a/hapi-fhir-converter/pom.xml
+++ b/hapi-fhir-converter/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-dist/pom.xml b/hapi-fhir-dist/pom.xml
index bc11c967b57..72205e3c27d 100644
--- a/hapi-fhir-dist/pom.xml
+++ b/hapi-fhir-dist/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-docs/pom.xml b/hapi-fhir-docs/pom.xml
index c9c200d12f8..6f79396cb4e 100644
--- a/hapi-fhir-docs/pom.xml
+++ b/hapi-fhir-docs/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4240-document-reference-with-long-attachment-url.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4240-document-reference-with-long-attachment-url.yaml
new file mode 100644
index 00000000000..84fa052936d
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4240-document-reference-with-long-attachment-url.yaml
@@ -0,0 +1,6 @@
+---
+type: fix
+issue: 4240
+jira: SMILE-4892
+title: "Previously, when creating a `DocumentReference` with an `Attachment` containing a URL over 254 characters
+an error was thrown. This has been corrected and now an `Attachment` URL can be up to 500 characters."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4250-overlapping-searchparameter-with-the-same-code-and-base-are-undetected.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4250-overlapping-searchparameter-with-the-same-code-and-base-are-undetected.yaml
new file mode 100644
index 00000000000..1582202b68c
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4250-overlapping-searchparameter-with-the-same-code-and-base-are-undetected.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 4250
+title: "Previously, SearchParameters with identical codes and bases could be created. This has been corrected. If a SearchParameter is submitted which is a duplicate, it will be rejected."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4267-reindex-behaviour-issues.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4267-reindex-behaviour-issues.yaml
new file mode 100644
index 00000000000..7e5a33a92f4
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4267-reindex-behaviour-issues.yaml
@@ -0,0 +1,8 @@
+---
+type: fix
+issue: 4267
+title: "Previously, if the `$reindex` operation failed with a `ResourceVersionConflictException` the related
+batch job would fail. This has been corrected by adding 10 retry attempts for transactions that have
+failed with a `ResourceVersionConflictException` during the `$reindex` operation. In addition, the `ResourceIdListStep`
+was submitting one more resource than expected (i.e. 1001 records processed during a `$reindex` operation if only 1000
+`Resources` were in the database). This has been corrected."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4271-migration-failure-with-oracle-19c-as-database-support.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4271-migration-failure-with-oracle-19c-as-database-support.yaml
new file mode 100644
index 00000000000..cf693a6bd5d
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4271-migration-failure-with-oracle-19c-as-database-support.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 4271
+title: "Database migration steps were failing with Oracle 19C. This has been fixed by allowing the database engine to skip dropping non-existent indexes."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/version.yaml
index 92d154bf813..7ffb32a7262 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/version.yaml
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/version.yaml
@@ -1,3 +1,3 @@
---
-release-date: "2022-11-18"
+release-date: "2022-11-17"
codename: "Vishwa"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_1/upgrade.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_1/upgrade.md
new file mode 100644
index 00000000000..76f1edbad3f
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_1/upgrade.md
@@ -0,0 +1 @@
+This version fixes a bug with 6.2.0 and previous releases wherein batch jobs that created very large chunk counts could occasionally fail to submit a small proportion of chunks.
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_1/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_1/version.yaml
new file mode 100644
index 00000000000..7ffb32a7262
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_1/version.yaml
@@ -0,0 +1,3 @@
+---
+release-date: "2022-11-17"
+codename: "Vishwa"
diff --git a/hapi-fhir-jacoco/pom.xml b/hapi-fhir-jacoco/pom.xml
index 4951bb88153..5c6003337ae 100644
--- a/hapi-fhir-jacoco/pom.xml
+++ b/hapi-fhir-jacoco/pom.xml
@@ -11,7 +11,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jaxrsserver-base/pom.xml b/hapi-fhir-jaxrsserver-base/pom.xml
index 3dc58871804..b7c7b774506 100644
--- a/hapi-fhir-jaxrsserver-base/pom.xml
+++ b/hapi-fhir-jaxrsserver-base/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpa/pom.xml b/hapi-fhir-jpa/pom.xml
index ca0c2c5829f..08d16f554dc 100644
--- a/hapi-fhir-jpa/pom.xml
+++ b/hapi-fhir-jpa/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
4.0.0
diff --git a/hapi-fhir-jpa/src/main/java/ca/uhn/fhir/jpa/sched/BaseHapiScheduler.java b/hapi-fhir-jpa/src/main/java/ca/uhn/fhir/jpa/sched/BaseHapiScheduler.java
index 10c199956c9..ccc60fec412 100644
--- a/hapi-fhir-jpa/src/main/java/ca/uhn/fhir/jpa/sched/BaseHapiScheduler.java
+++ b/hapi-fhir-jpa/src/main/java/ca/uhn/fhir/jpa/sched/BaseHapiScheduler.java
@@ -184,6 +184,7 @@ public abstract class BaseHapiScheduler implements IHapiScheduler {
ScheduleBuilder extends Trigger> schedule = SimpleScheduleBuilder
.simpleSchedule()
.withIntervalInMilliseconds(theIntervalMillis)
+ .withMisfireHandlingInstructionIgnoreMisfires()//We ignore misfires in cases of multiple JVMs each trying to fire.
.repeatForever();
Trigger trigger = TriggerBuilder.newTrigger()
diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml
index 352c4783a36..8b5babed5aa 100644
--- a/hapi-fhir-jpaserver-base/pom.xml
+++ b/hapi-fhir-jpaserver-base/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java
index 4b856422e97..79b331e20e9 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java
@@ -270,6 +270,14 @@ public class JpaJobPersistenceImpl implements IJobPersistence {
myWorkChunkRepository.incrementWorkChunkErrorCount(theChunkId, theIncrementBy);
}
+ @Override
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public boolean canAdvanceInstanceToNextStep(String theInstanceId, String theCurrentStepId) {
+ List statusesForStep = myWorkChunkRepository.getDistinctStatusesForStep(theInstanceId, theCurrentStepId);
+ ourLog.debug("Checking whether gated job can advanced to next step. [instanceId={}, currentStepId={}, statusesForStep={}]", theInstanceId, theCurrentStepId, statusesForStep);
+ return statusesForStep.stream().noneMatch(StatusEnum::isIncomplete) && statusesForStep.stream().anyMatch(status -> status == StatusEnum.COMPLETED);
+ }
+
/**
* Note: Not @Transactional because {@link #fetchChunks(String, boolean, int, int, Consumer)} starts a transaction
*/
@@ -289,6 +297,11 @@ public class JpaJobPersistenceImpl implements IJobPersistence {
});
}
+ @Override
+ public List fetchallchunkidsforstepWithStatus(String theInstanceId, String theStepId, StatusEnum theStatusEnum) {
+ return myTxTemplate.execute(tx -> myWorkChunkRepository.fetchAllChunkIdsForStepWithStatus(theInstanceId, theStepId, theStatusEnum));
+ }
+
private void fetchChunksForStep(String theInstanceId, String theStepId, int thePageSize, int thePageIndex, Consumer theConsumer) {
myTxTemplate.executeWithoutResult(tx -> {
List chunks = myWorkChunkRepository.fetchChunksForStep(PageRequest.of(thePageIndex, thePageSize), theInstanceId, theStepId);
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBatch2WorkChunkRepository.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBatch2WorkChunkRepository.java
index dc2cda61f1c..d060e57c70e 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBatch2WorkChunkRepository.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IBatch2WorkChunkRepository.java
@@ -36,6 +36,9 @@ public interface IBatch2WorkChunkRepository extends JpaRepository fetchChunks(Pageable thePageRequest, @Param("instanceId") String theInstanceId);
+ @Query("SELECT DISTINCT e.myStatus from Batch2WorkChunkEntity e where e.myInstanceId = :instanceId AND e.myTargetStepId = :stepId")
+ List getDistinctStatusesForStep(@Param("instanceId") String theInstanceId, @Param("stepId") String theStepId);
+
@Query("SELECT e FROM Batch2WorkChunkEntity e WHERE e.myInstanceId = :instanceId AND e.myTargetStepId = :targetStepId ORDER BY e.mySequence ASC")
List fetchChunksForStep(Pageable thePageRequest, @Param("instanceId") String theInstanceId, @Param("targetStepId") String theTargetStepId);
@@ -62,4 +65,10 @@ public interface IBatch2WorkChunkRepository extends JpaRepository fetchAllChunkIdsForStep(@Param("instanceId") String theInstanceId, @Param("stepId") String theStepId);
+
+ @Query("SELECT e.myId from Batch2WorkChunkEntity e where e.myInstanceId = :instanceId AND e.myTargetStepId = :stepId AND e.myStatus = :status")
+ List fetchAllChunkIdsForStepWithStatus(@Param("instanceId")String theInstanceId, @Param("stepId")String theStepId, @Param("status")StatusEnum theStatus);
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java
index 2d20af3d426..fe1a490281e 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java
@@ -117,6 +117,11 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks {
.modifyColumn("20221017.1", "BLOB_SIZE")
.nullable()
.withType(ColumnTypeEnum.LONG);
+
+ version.onTable("HFJ_SPIDX_URI")
+ .modifyColumn("20221103.1", "SP_URI")
+ .nullable()
+ .withType(ColumnTypeEnum.STRING, 500);
}
private void init610() {
@@ -942,7 +947,7 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks {
//ConceptMap add version for search
Builder.BuilderWithTableName trmConceptMap = version.onTable("TRM_CONCEPT_MAP");
trmConceptMap.addColumn("20200910.1", "VER").nullable().type(ColumnTypeEnum.STRING, 200);
- trmConceptMap.dropIndex("20200910.2", "IDX_CONCEPT_MAP_URL");
+ trmConceptMap.dropIndex("20200910.2", "IDX_CONCEPT_MAP_URL").failureAllowed();
trmConceptMap.addIndex("20200910.3", "IDX_CONCEPT_MAP_URL").unique(true).withColumns("URL", "VER");
//Term CodeSystem Version and Term ValueSet Version
@@ -950,13 +955,13 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks {
trmCodeSystemVer.addIndex("20200923.1", "IDX_CODESYSTEM_AND_VER").unique(true).withColumns("CODESYSTEM_PID", "CS_VERSION_ID");
Builder.BuilderWithTableName trmValueSet = version.onTable("TRM_VALUESET");
trmValueSet.addColumn("20200923.2", "VER").nullable().type(ColumnTypeEnum.STRING, 200);
- trmValueSet.dropIndex("20200923.3", "IDX_VALUESET_URL");
+ trmValueSet.dropIndex("20200923.3", "IDX_VALUESET_URL").failureAllowed();
trmValueSet.addIndex("20200923.4", "IDX_VALUESET_URL").unique(true).withColumns("URL", "VER");
//Term ValueSet Component add system version
Builder.BuilderWithTableName trmValueSetComp = version.onTable("TRM_VALUESET_CONCEPT");
trmValueSetComp.addColumn("20201028.1", "SYSTEM_VER").nullable().type(ColumnTypeEnum.STRING, 200);
- trmValueSetComp.dropIndex("20201028.2", "IDX_VS_CONCEPT_CS_CD");
+ trmValueSetComp.dropIndex("20201028.2", "IDX_VS_CONCEPT_CS_CD").failureAllowed();
trmValueSetComp.addIndex("20201028.3", "IDX_VS_CONCEPT_CS_CODE").unique(true).withColumns("VALUESET_PID", "SYSTEM_URL", "SYSTEM_VER", "CODEVAL").doNothing();
}
diff --git a/hapi-fhir-jpaserver-cql/pom.xml b/hapi-fhir-jpaserver-cql/pom.xml
index 2de9692219c..b104e7f84a4 100644
--- a/hapi-fhir-jpaserver-cql/pom.xml
+++ b/hapi-fhir-jpaserver-cql/pom.xml
@@ -7,7 +7,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml b/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml
index 24e1fecdb5f..d301eadd9c1 100644
--- a/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml
+++ b/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-mdm/pom.xml b/hapi-fhir-jpaserver-mdm/pom.xml
index bcf125a1203..0155cdfef91 100644
--- a/hapi-fhir-jpaserver-mdm/pom.xml
+++ b/hapi-fhir-jpaserver-mdm/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmSearchExpandingInterceptorIT.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmSearchExpandingInterceptorIT.java
index c23b6fabf01..c71e6017814 100644
--- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmSearchExpandingInterceptorIT.java
+++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/interceptor/MdmSearchExpandingInterceptorIT.java
@@ -93,6 +93,72 @@ public class MdmSearchExpandingInterceptorIT extends BaseMdmR4Test {
return createdResourceIds;
}
+ private List updateAndLinkNewResources(int theResourceCount) throws InterruptedException {
+ boolean expansion = myDaoConfig.isAllowMdmExpansion();
+ myDaoConfig.setAllowMdmExpansion(false);
+ List createdResourceIds = new ArrayList<>();
+
+ List observationIds = new ArrayList<>();
+ for (int i = 0; i < theResourceCount; i++) {
+ // create patient
+ Patient patient = buildJanePatient();
+ patient.setId("jane-" + i);
+ MdmHelperR4.OutcomeAndLogMessageWrapper withLatch = myMdmHelper.updateWithLatch(addExternalEID(patient, "123"));
+ createdResourceIds.add(withLatch.getDaoMethodOutcome().getId().getIdPart());
+
+ // create observation with patient
+ Observation observation = createObservationWithSubject(createdResourceIds.get(i));
+ // we put the observation ids in a separate list so we can
+ // ensure our returned list is
+ // patient ids, followed by observation ids
+ observationIds.add(observation.getIdElement().getIdPart());
+ }
+
+ assertLinkCount(theResourceCount);
+
+ // add in our observationIds
+ createdResourceIds.addAll(observationIds);
+
+ myDaoConfig.setAllowMdmExpansion(expansion);
+ return createdResourceIds;
+ }
+
+
+ @Test
+ public void testReferenceExpansionWorksWithForcedIds() throws InterruptedException {
+ int resourceCount = 4;
+ List ids = updateAndLinkNewResources(resourceCount);
+ String id = ids.get(0);
+
+ SearchParameterMap searchParameterMap = new SearchParameterMap();
+ searchParameterMap.setLoadSynchronous(true);
+ ReferenceOrListParam referenceOrListParam = new ReferenceOrListParam();
+ referenceOrListParam.addOr(new ReferenceParam("Patient/" + id).setMdmExpand(true));
+ searchParameterMap.add(Observation.SP_SUBJECT, referenceOrListParam);
+
+ //With MDM Expansion disabled, this should return 1 result.
+ myDaoConfig.setAllowMdmExpansion(false);
+ IBundleProvider search = myObservationDao.search(searchParameterMap);
+ assertThat(search.size(), is(equalTo(1)));
+
+ //Once MDM Expansion is allowed, this should now return 4 resourecs.
+ myDaoConfig.setAllowMdmExpansion(true);
+ search = myObservationDao.search(searchParameterMap);
+ assertThat(search.size(), is(equalTo(4)));
+ List all = myMdmLinkDao.findAll();
+ Long goldenPid = all.get(0).getGoldenResourcePid();
+ IIdType goldenId = myIdHelperService.translatePidIdToForcedId(myFhirContext, "Patient", new ResourcePersistentId(goldenPid));
+ //Verify that expansion by the golden resource id resolves down to everything its links have.
+
+ SearchParameterMap goldenSpMap = new SearchParameterMap();
+ goldenSpMap.setLoadSynchronous(true);
+ ReferenceOrListParam goldenReferenceOrListParam = new ReferenceOrListParam();
+ goldenReferenceOrListParam.addOr(new ReferenceParam(goldenId).setMdmExpand(true));
+ goldenSpMap.add(Observation.SP_SUBJECT, goldenReferenceOrListParam);
+
+ search = myObservationDao.search(goldenSpMap);
+ assertThat(search.size(), is(equalTo(resourceCount)));
+ }
@Test
public void testReferenceExpansionWorks() throws InterruptedException {
int resourceCount = 4;
diff --git a/hapi-fhir-jpaserver-model/pom.xml b/hapi-fhir-jpaserver-model/pom.xml
index 294e118ae06..81b2a142592 100644
--- a/hapi-fhir-jpaserver-model/pom.xml
+++ b/hapi-fhir-jpaserver-model/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamUri.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamUri.java
index 6ef437cdb2a..94055f832ef 100644
--- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamUri.java
+++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamUri.java
@@ -59,9 +59,11 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
public class ResourceIndexedSearchParamUri extends BaseResourceIndexedSearchParam {
/*
- * Note that MYSQL chokes on unique indexes for lengths > 255 so be careful here
+ * Be careful when modifying this value
+ * MySQL chokes on indexes with combined column length greater than 3052 bytes (768 chars)
+ * https://dev.mysql.com/doc/refman/8.0/en/innodb-limits.html
*/
- public static final int MAX_LENGTH = 254;
+ public static final int MAX_LENGTH = 500;
private static final long serialVersionUID = 1L;
@Column(name = "SP_URI", nullable = true, length = MAX_LENGTH)
diff --git a/hapi-fhir-jpaserver-searchparam/pom.xml b/hapi-fhir-jpaserver-searchparam/pom.xml
index 15ad0732352..08ee6fb1b56 100755
--- a/hapi-fhir-jpaserver-searchparam/pom.xml
+++ b/hapi-fhir-jpaserver-searchparam/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-subscription/pom.xml b/hapi-fhir-jpaserver-subscription/pom.xml
index 3f94dfd0326..2210b8808f3 100644
--- a/hapi-fhir-jpaserver-subscription/pom.xml
+++ b/hapi-fhir-jpaserver-subscription/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-test-dstu2/pom.xml b/hapi-fhir-jpaserver-test-dstu2/pom.xml
index 1f6ee6345f1..4cbf912c4a2 100644
--- a/hapi-fhir-jpaserver-test-dstu2/pom.xml
+++ b/hapi-fhir-jpaserver-test-dstu2/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java
index d2f176c97e3..8fc23513cf7 100644
--- a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java
+++ b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java
@@ -37,6 +37,7 @@ import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
+import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
diff --git a/hapi-fhir-jpaserver-test-dstu3/pom.xml b/hapi-fhir-jpaserver-test-dstu3/pom.xml
index 5fb3680bda7..434f88fa1d5 100644
--- a/hapi-fhir-jpaserver-test-dstu3/pom.xml
+++ b/hapi-fhir-jpaserver-test-dstu3/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java
index 58e6d2b0428..41e0eb898fc 100644
--- a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java
+++ b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java
@@ -130,6 +130,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
import org.springframework.test.util.AopTestUtils;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
@@ -4823,6 +4824,33 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
}
+ @Test
+ public void testDocumentReferenceWith500CharAttachmentUrl() throws IOException {
+ final DocumentReference.ReferredDocumentStatus docStatus = DocumentReference.ReferredDocumentStatus.FINAL;
+ final String longUrl = StringUtils.repeat("a", 500);
+
+ DocumentReference submittedDocumentReference = new DocumentReference();
+ submittedDocumentReference.setDocStatus(docStatus);
+
+ Attachment attachment = new Attachment();
+ attachment.setUrl(longUrl);
+ submittedDocumentReference.getContentFirstRep().setAttachment(attachment);
+
+ String json = myFhirContext.newJsonParser().encodeResourceToString(submittedDocumentReference);
+ HttpPost post = new HttpPost(myServerBase + "/DocumentReference");
+ post.setEntity(new StringEntity(json, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
+
+ try (CloseableHttpResponse response = ourHttpClient.execute(post)) {
+ String resp = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
+ ourLog.info(resp);
+ assertEquals(HttpStatus.CREATED.value(), response.getStatusLine().getStatusCode());
+
+ DocumentReference createdDocumentReferenced = myFhirContext.newJsonParser().parseResource(DocumentReference.class, resp);
+ assertEquals(docStatus, createdDocumentReferenced.getDocStatus());
+ assertEquals(longUrl, createdDocumentReferenced.getContentFirstRep().getAttachment().getUrl());
+ }
+ }
+
private String toStr(Date theDate) {
return new InstantDt(theDate).getValueAsString();
}
diff --git a/hapi-fhir-jpaserver-test-r4/pom.xml b/hapi-fhir-jpaserver-test-r4/pom.xml
index d68da53a525..6bd5d059b23 100644
--- a/hapi-fhir-jpaserver-test-r4/pom.xml
+++ b/hapi-fhir-jpaserver-test-r4/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImplTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImplTest.java
index f6d2ddb4867..c64293160a7 100644
--- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImplTest.java
+++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImplTest.java
@@ -305,6 +305,39 @@ public class JpaJobPersistenceImplTest extends BaseJpaR4Test {
assertEquals(1, chunks.size());
assertEquals(5, chunks.get(0).getErrorCount());
}
+ @Test
+ public void testGatedAdvancementByStatus() {
+ // Setup
+ JobInstance instance = createInstance();
+ String instanceId = mySvc.storeNewInstance(instance);
+ String chunkId = storeWorkChunk(DEF_CHUNK_ID, STEP_CHUNK_ID, instanceId, SEQUENCE_NUMBER, null);
+ mySvc.markWorkChunkAsCompletedAndClearData(chunkId, 0);
+
+ boolean canAdvance = mySvc.canAdvanceInstanceToNextStep(instanceId, STEP_CHUNK_ID);
+ assertTrue(canAdvance);
+
+ //Storing a new chunk with QUEUED should prevent advancement.
+ String newChunkId = storeWorkChunk(DEF_CHUNK_ID, STEP_CHUNK_ID, instanceId, SEQUENCE_NUMBER, null);
+
+ canAdvance = mySvc.canAdvanceInstanceToNextStep(instanceId, STEP_CHUNK_ID);
+ assertFalse(canAdvance);
+
+ //Toggle it to complete
+ mySvc.markWorkChunkAsCompletedAndClearData(newChunkId, 0);
+ canAdvance = mySvc.canAdvanceInstanceToNextStep(instanceId, STEP_CHUNK_ID);
+ assertTrue(canAdvance);
+
+ //Create a new chunk and set it in progress.
+ String newerChunkId= storeWorkChunk(DEF_CHUNK_ID, STEP_CHUNK_ID, instanceId, SEQUENCE_NUMBER, null);
+ mySvc.fetchWorkChunkSetStartTimeAndMarkInProgress(newerChunkId);
+ canAdvance = mySvc.canAdvanceInstanceToNextStep(instanceId, STEP_CHUNK_ID);
+ assertFalse(canAdvance);
+
+ //Toggle IN_PROGRESS to complete
+ mySvc.markWorkChunkAsCompletedAndClearData(newerChunkId, 0);
+ canAdvance = mySvc.canAdvanceInstanceToNextStep(instanceId, STEP_CHUNK_ID);
+ assertTrue(canAdvance);
+ }
@Test
public void testMarkChunkAsCompleted_Error() {
diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTest.java
index 2097c6d1f2c..6bca18c08b5 100644
--- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTest.java
+++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/BulkExportUseCaseTest.java
@@ -43,6 +43,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -59,6 +60,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDaoTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDaoTest.java
index 64681ca6ef2..ef3646d3543 100644
--- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDaoTest.java
+++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDaoTest.java
@@ -40,6 +40,11 @@ import org.mockito.junit.jupiter.MockitoExtension;
import javax.persistence.EntityManager;
import java.util.List;
+
+import java.util.List;
+
+import java.util.List;
+
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.fail;
diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ConcurrentWriteTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ConcurrentWriteTest.java
index 29b9a00472a..e436bfe9dab 100644
--- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ConcurrentWriteTest.java
+++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ConcurrentWriteTest.java
@@ -332,8 +332,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
@Test
public void testCreateWithClientAssignedId() {
myInterceptorRegistry.registerInterceptor(myRetryInterceptor);
- String value = UserRequestRetryVersionConflictsInterceptor.RETRY + "; " + UserRequestRetryVersionConflictsInterceptor.MAX_RETRIES + "=10";
- when(mySrd.getHeaders(eq(UserRequestRetryVersionConflictsInterceptor.HEADER_NAME))).thenReturn(Collections.singletonList(value));
+ setupRetryBehaviour(mySrd);
List> futures = new ArrayList<>();
for (int i = 0; i < 5; i++) {
@@ -502,8 +501,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
@Test
public void testDelete() {
myInterceptorRegistry.registerInterceptor(myRetryInterceptor);
- String value = UserRequestRetryVersionConflictsInterceptor.RETRY + "; " + UserRequestRetryVersionConflictsInterceptor.MAX_RETRIES + "=100";
- when(mySrd.getHeaders(eq(UserRequestRetryVersionConflictsInterceptor.HEADER_NAME))).thenReturn(Collections.singletonList(value));
+ setupRetryBehaviour(mySrd);
IIdType patientId = runInTransaction(() -> {
Patient p = new Patient();
@@ -664,8 +662,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
@Test
public void testPatch() {
myInterceptorRegistry.registerInterceptor(myRetryInterceptor);
- String value = UserRequestRetryVersionConflictsInterceptor.RETRY + "; " + UserRequestRetryVersionConflictsInterceptor.MAX_RETRIES + "=10";
- when(mySrd.getHeaders(eq(UserRequestRetryVersionConflictsInterceptor.HEADER_NAME))).thenReturn(Collections.singletonList(value));
+ setupRetryBehaviour(mySrd);
Patient p = new Patient();
p.addName().setFamily("FAMILY");
@@ -719,8 +716,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
myInterceptorRegistry.registerInterceptor(myRetryInterceptor);
ServletRequestDetails srd = mock(ServletRequestDetails.class);
- String value = UserRequestRetryVersionConflictsInterceptor.RETRY + "; " + UserRequestRetryVersionConflictsInterceptor.MAX_RETRIES + "=10";
- when(srd.getHeaders(eq(UserRequestRetryVersionConflictsInterceptor.HEADER_NAME))).thenReturn(Collections.singletonList(value));
+ setupRetryBehaviour(srd);
when(srd.getUserData()).thenReturn(new HashMap<>());
when(srd.getServer()).thenReturn(new RestfulServer(myFhirContext));
when(srd.getInterceptorBroadcaster()).thenReturn(new InterceptorService());
@@ -772,8 +768,7 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
myDaoConfig.setDeleteEnabled(false);
ServletRequestDetails srd = mock(ServletRequestDetails.class);
- String value = UserRequestRetryVersionConflictsInterceptor.RETRY + "; " + UserRequestRetryVersionConflictsInterceptor.MAX_RETRIES + "=10";
- when(srd.getHeaders(eq(UserRequestRetryVersionConflictsInterceptor.HEADER_NAME))).thenReturn(Collections.singletonList(value));
+ setupRetryBehaviour(srd);
when(srd.getUserData()).thenReturn(new HashMap<>());
when(srd.getServer()).thenReturn(new RestfulServer(myFhirContext));
when(srd.getInterceptorBroadcaster()).thenReturn(new InterceptorService());
@@ -824,4 +819,9 @@ public class FhirResourceDaoR4ConcurrentWriteTest extends BaseJpaR4Test {
}
+ private void setupRetryBehaviour(ServletRequestDetails theServletRequestDetails) {
+ when(theServletRequestDetails.isRetry()).thenReturn(true);
+ when(theServletRequestDetails.getMaxRetries()).thenReturn(10);
+ }
+
}
diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/delete/job/ReindexJobTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/delete/job/ReindexJobTest.java
index 60f997893f4..50c405bbba8 100644
--- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/delete/job/ReindexJobTest.java
+++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/delete/job/ReindexJobTest.java
@@ -11,14 +11,20 @@ import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.batch.models.Batch2JobStartResponse;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
+import ca.uhn.fhir.jpa.test.PatientReindexTestHelper;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.Observation;
import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import java.util.List;
+import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
@@ -30,10 +36,13 @@ public class ReindexJobTest extends BaseJpaR4Test {
private IJobCoordinator myJobCoordinator;
private ReindexTestHelper myReindexTestHelper;
+ private PatientReindexTestHelper myPatientReindexTestHelper;
@PostConstruct
public void postConstruct() {
myReindexTestHelper = new ReindexTestHelper(myFhirContext, myDaoRegistry, mySearchParamRegistry);
+ boolean incrementVersionAfterReindex = false;
+ myPatientReindexTestHelper = new PatientReindexTestHelper(myJobCoordinator, myBatch2JobHelper, myPatientDao, incrementVersionAfterReindex);
}
@AfterEach
@@ -167,4 +176,29 @@ public class ReindexJobTest extends BaseJpaR4Test {
assertEquals("java.lang.Error: foo message", outcome.getErrorMessage());
}
+ private static Stream numResourcesParams(){
+ return PatientReindexTestHelper.numResourcesParams();
+ }
+
+ @ParameterizedTest
+ @MethodSource("numResourcesParams")
+ @Disabled//TODO Nathan, this is failing intermittently in CI.
+ public void testReindex(int theNumResources){
+ myPatientReindexTestHelper.testReindex(theNumResources);
+ }
+
+ @ParameterizedTest
+ @MethodSource("numResourcesParams")
+ @Disabled//TODO Nathan, this is failing intermittently in CI.
+ public void testSequentialReindexOperation(int theNumResources){
+ myPatientReindexTestHelper.testSequentialReindexOperation(theNumResources);
+ }
+
+ @ParameterizedTest
+ @MethodSource("numResourcesParams")
+ @Disabled//TODO Nathan, this is failing intermittently in CI.
+ public void testParallelReindexOperation(int theNumResources){
+ myPatientReindexTestHelper.testParallelReindexOperation(theNumResources);
+ }
+
}
diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java
index c54d612fb25..98355bd7caa 100644
--- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java
+++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java
@@ -165,6 +165,7 @@ import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Nonnull;
+import javax.sql.DataSource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
diff --git a/hapi-fhir-jpaserver-test-r4b/pom.xml b/hapi-fhir-jpaserver-test-r4b/pom.xml
index f63968fa685..f6aa32ae643 100644
--- a/hapi-fhir-jpaserver-test-r4b/pom.xml
+++ b/hapi-fhir-jpaserver-test-r4b/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-test-r5/pom.xml b/hapi-fhir-jpaserver-test-r5/pom.xml
index d68ae1de3ab..3d965df565e 100644
--- a/hapi-fhir-jpaserver-test-r5/pom.xml
+++ b/hapi-fhir-jpaserver-test-r5/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-test-utilities/pom.xml b/hapi-fhir-jpaserver-test-utilities/pom.xml
index 47af00475ab..24fe721cc6b 100644
--- a/hapi-fhir-jpaserver-test-utilities/pom.xml
+++ b/hapi-fhir-jpaserver-test-utilities/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
@@ -144,6 +144,11 @@
junit-jupiter-engine
compile
+
+ org.junit.jupiter
+ junit-jupiter-params
+ compile
+
org.hamcrest
hamcrest
diff --git a/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/PatientReindexTestHelper.java b/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/PatientReindexTestHelper.java
new file mode 100644
index 00000000000..a0385253d91
--- /dev/null
+++ b/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/PatientReindexTestHelper.java
@@ -0,0 +1,185 @@
+package ca.uhn.fhir.jpa.test;
+
+/*-
+ * #%L
+ * HAPI FHIR JPA Server Test Utilities
+ * %%
+ * Copyright (C) 2014 - 2022 Smile CDR, Inc.
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import ca.uhn.fhir.batch2.api.IJobCoordinator;
+import ca.uhn.fhir.batch2.jobs.reindex.ReindexAppCtx;
+import ca.uhn.fhir.batch2.jobs.reindex.ReindexJobParameters;
+import ca.uhn.fhir.batch2.model.JobInstance;
+import ca.uhn.fhir.batch2.model.JobInstanceStartRequest;
+import ca.uhn.fhir.batch2.model.StatusEnum;
+import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
+import ca.uhn.fhir.jpa.batch.models.Batch2JobStartResponse;
+import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
+import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
+import ca.uhn.fhir.jpa.util.TestUtil;
+import ca.uhn.fhir.rest.api.server.RequestDetails;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.r4.model.Patient;
+import org.junit.jupiter.params.provider.Arguments;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class PatientReindexTestHelper {
+
+ private static final int VERSION_1 = 1;
+ private static final int VERSION_2 = 2;
+ private static final int VERSION_3 = 3;
+ public static final int JOB_WAIT_TIME = 60;
+
+ private final IJobCoordinator myJobCoordinator;
+ private final Batch2JobHelper myBatch2JobHelper;
+ private final IFhirResourceDao myPatientDao;
+ private final boolean myIncrementVersionOnReindex;
+
+ public static Stream numResourcesParams(){
+ return Stream.of(
+ Arguments.of(0),
+ Arguments.of(1),
+ Arguments.of(499),
+ Arguments.of(500),
+ Arguments.of(750),
+ Arguments.of(1000),
+ Arguments.of(1001)
+ );
+ }
+
+ public PatientReindexTestHelper(IJobCoordinator theJobCoordinator, Batch2JobHelper theBatch2JobHelper, IFhirResourceDao thePatientDao, boolean theIncrementVersionOnReindex) {
+ myJobCoordinator = theJobCoordinator;
+ myBatch2JobHelper = theBatch2JobHelper;
+ myPatientDao = thePatientDao;
+ myIncrementVersionOnReindex = theIncrementVersionOnReindex;
+ }
+
+ public void testReindex(int theNumResources){
+ createPatients(theNumResources);
+
+ validatePersistedPatients(theNumResources, VERSION_1);
+
+ // Reindex 1
+ JobInstanceStartRequest reindexRequest1 = createPatientReindexRequest(theNumResources);
+ Batch2JobStartResponse reindexResponse1 = myJobCoordinator.startInstance(reindexRequest1);
+ JobInstance instance1 = myBatch2JobHelper.awaitJobHasStatus(reindexResponse1.getJobId(), JOB_WAIT_TIME, StatusEnum.COMPLETED);
+
+ validateReindexJob(instance1, theNumResources);
+
+ int expectedVersion = myIncrementVersionOnReindex ? VERSION_2 : VERSION_1;
+ validatePersistedPatients(theNumResources, expectedVersion);
+ }
+
+ public void testSequentialReindexOperation(int theNumResources){
+ createPatients(theNumResources);
+
+ validatePersistedPatients(theNumResources, VERSION_1);
+
+ // Reindex 1
+ JobInstanceStartRequest reindexRequest1 = createPatientReindexRequest(theNumResources);
+ Batch2JobStartResponse reindexResponse1 = myJobCoordinator.startInstance(reindexRequest1);
+ JobInstance instance1 = myBatch2JobHelper.awaitJobHasStatus(reindexResponse1.getJobId(), JOB_WAIT_TIME, StatusEnum.COMPLETED);
+
+ validateReindexJob(instance1, theNumResources);
+ int expectedVersion = myIncrementVersionOnReindex ? VERSION_2 : VERSION_1;
+ validatePersistedPatients(theNumResources, expectedVersion);
+
+ // Reindex 2
+ JobInstanceStartRequest reindexRequest2 = createPatientReindexRequest(theNumResources);
+ Batch2JobStartResponse reindexResponse2 = myJobCoordinator.startInstance(reindexRequest2);
+ JobInstance instance2 = myBatch2JobHelper.awaitJobHasStatus(reindexResponse2.getJobId(), JOB_WAIT_TIME, StatusEnum.COMPLETED);
+
+ validateReindexJob(instance2, theNumResources);
+ expectedVersion = myIncrementVersionOnReindex ? VERSION_3 : VERSION_1;
+ validatePersistedPatients(theNumResources, expectedVersion);
+ }
+
+ public void testParallelReindexOperation(int theNumResources){
+ createPatients(theNumResources);
+
+ validatePersistedPatients(theNumResources, VERSION_1);
+
+ // Reindex 1
+ JobInstanceStartRequest reindexRequest1 = createPatientReindexRequest(theNumResources);
+ Batch2JobStartResponse reindexResponse1 = myJobCoordinator.startInstance(reindexRequest1);
+
+ // Reindex 2
+ JobInstanceStartRequest reindexRequest2 = createPatientReindexRequest(theNumResources);
+ Batch2JobStartResponse reindexResponse2 = myJobCoordinator.startInstance(reindexRequest2);
+
+ // Wait for jobs to finish
+ JobInstance instance1 = myBatch2JobHelper.awaitJobHasStatus(reindexResponse1.getJobId(), JOB_WAIT_TIME, StatusEnum.COMPLETED);
+ JobInstance instance2 = myBatch2JobHelper.awaitJobHasStatus(reindexResponse2.getJobId(), JOB_WAIT_TIME, StatusEnum.COMPLETED);
+
+ validateReindexJob(instance1, theNumResources);
+
+ validateReindexJob(instance2, theNumResources);
+
+ int expectedVersion = myIncrementVersionOnReindex ? VERSION_3 : VERSION_1;
+ validatePersistedPatients(theNumResources, expectedVersion);
+ }
+
+
+ private void createPatients(int theNumPatients) {
+ RequestDetails requestDetails = new SystemRequestDetails();
+ for(int i = 0; i < theNumPatients; i++){
+ Patient patient = new Patient();
+ patient.getNameFirstRep().setFamily("Family-"+i).addGiven("Given-"+i);
+ patient.getIdentifierFirstRep().setValue("Id-"+i);
+ myPatientDao.create(patient, requestDetails);
+ }
+ TestUtil.sleepOneClick();
+ }
+
+ private void validatePersistedPatients(int theExpectedNumPatients, long theExpectedVersion) {
+ RequestDetails requestDetails = new SystemRequestDetails();
+ List resources = myPatientDao.search(SearchParameterMap.newSynchronous(), requestDetails).getAllResources();
+ assertEquals(theExpectedNumPatients, resources.size());
+ for(IBaseResource resource : resources){
+ assertEquals(Patient.class, resource.getClass());
+ Patient patient = (Patient) resource;
+ Long actualVersion = patient.getIdElement().getVersionIdPartAsLong();
+ if(theExpectedVersion != actualVersion){
+ String failureMessage = String.format("Failure for Resource [%s] with index [%s]. Expected version: %s, Actual version: %s",
+ patient.getId(), resources.indexOf(resource), theExpectedVersion, actualVersion);
+ fail(failureMessage);
+ }
+ }
+ }
+
+ private JobInstanceStartRequest createPatientReindexRequest(int theBatchSize) {
+ JobInstanceStartRequest startRequest = new JobInstanceStartRequest();
+ startRequest.setJobDefinitionId(ReindexAppCtx.JOB_REINDEX);
+
+ ReindexJobParameters reindexJobParameters = new ReindexJobParameters();
+ reindexJobParameters.setBatchSize(theBatchSize);
+ reindexJobParameters.addUrl("Patient?");
+
+ startRequest.setParameters(reindexJobParameters);
+ return startRequest;
+ }
+
+ private void validateReindexJob(JobInstance theJobInstance, int theRecordsProcessed) {
+ assertEquals(0, theJobInstance.getErrorCount());
+ assertEquals(theRecordsProcessed, theJobInstance.getCombinedRecordsProcessed());
+ }
+}
diff --git a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml
index 3eab5a19cd1..983d182a888 100644
--- a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml
+++ b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-server-mdm/pom.xml b/hapi-fhir-server-mdm/pom.xml
index 2d5ef95aba1..74406036383 100644
--- a/hapi-fhir-server-mdm/pom.xml
+++ b/hapi-fhir-server-mdm/pom.xml
@@ -7,7 +7,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/interceptor/MdmSearchExpandingInterceptor.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/interceptor/MdmSearchExpandingInterceptor.java
index 28ada0df2e7..f2a9149579f 100644
--- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/interceptor/MdmSearchExpandingInterceptor.java
+++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/interceptor/MdmSearchExpandingInterceptor.java
@@ -25,7 +25,6 @@ import ca.uhn.fhir.interceptor.api.Interceptor;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.mdm.api.IMdmLinkExpandSvc;
-import ca.uhn.fhir.mdm.svc.MdmLinkExpandSvc;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.mdm.log.Logs;
import ca.uhn.fhir.model.api.IQueryParameterType;
@@ -99,7 +98,8 @@ public class MdmSearchExpandingInterceptor {
ourLog.debug("Parameter has been expanded to: {}", String.join(", ", expandedResourceIds));
toRemove.add(refParam);
expandedResourceIds.stream()
- .map(resourceId -> new ReferenceParam(refParam.getResourceType() + "/" + resourceId))
+ .map(resourceId -> addResourceTypeIfNecessary(refParam.getResourceType(), resourceId))
+ .map(ReferenceParam::new)
.forEach(toAdd::add);
}
}
@@ -112,6 +112,14 @@ public class MdmSearchExpandingInterceptor {
orList.addAll(toAdd);
}
+ private String addResourceTypeIfNecessary(String theResourceType, String theResourceId) {
+ if (theResourceId.contains("/")) {
+ return theResourceId;
+ } else {
+ return theResourceType + "/" + theResourceId;
+ }
+ }
+
/**
* Expands out the provided _id parameter into all the various
* ids of linked resources.
diff --git a/hapi-fhir-server-openapi/pom.xml b/hapi-fhir-server-openapi/pom.xml
index 5b2cdbcd4fe..d14c31a24fc 100644
--- a/hapi-fhir-server-openapi/pom.xml
+++ b/hapi-fhir-server-openapi/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-server/pom.xml b/hapi-fhir-server/pom.xml
index 84184071283..a05ff319863 100644
--- a/hapi-fhir-server/pom.xml
+++ b/hapi-fhir-server/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/api/server/RequestDetails.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/api/server/RequestDetails.java
index 0878b8f4cef..305bf943974 100644
--- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/api/server/RequestDetails.java
+++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/api/server/RequestDetails.java
@@ -77,6 +77,8 @@ public abstract class RequestDetails {
private String myTransactionGuid;
private String myFixedConditionalUrl;
private boolean myRewriteHistory;
+ private int myMaxRetries;
+ private boolean myRetry;
/**
* Constructor
@@ -542,4 +544,21 @@ public abstract class RequestDetails {
public void setRewriteHistory(boolean theRewriteHistory) {
myRewriteHistory = theRewriteHistory;
}
+
+
+ public int getMaxRetries() {
+ return myMaxRetries;
+ }
+
+ public void setMaxRetries(int theMaxRetries) {
+ myMaxRetries = theMaxRetries;
+ }
+
+ public boolean isRetry() {
+ return myRetry;
+ }
+
+ public void setRetry(boolean theRetry) {
+ myRetry = theRetry;
+ }
}
diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/servlet/ServletRequestDetails.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/servlet/ServletRequestDetails.java
index 9cf18c6bfa1..f166f5902a4 100644
--- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/servlet/ServletRequestDetails.java
+++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/servlet/ServletRequestDetails.java
@@ -44,11 +44,14 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.StringTokenizer;
import java.util.zip.GZIPInputStream;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
+import static org.apache.commons.lang3.StringUtils.trim;
public class ServletRequestDetails extends RequestDetails {
@@ -186,9 +189,36 @@ public class ServletRequestDetails extends RequestDetails {
if ("true".equals(myServletRequest.getHeader(Constants.HEADER_REWRITE_HISTORY))) {
setRewriteHistory(true);
}
+ setRetryFields(myServletRequest);
return this;
}
+ private void setRetryFields(HttpServletRequest theRequest){
+ if (theRequest == null){
+ return;
+ }
+ Enumeration headers = theRequest.getHeaders(Constants.HEADER_RETRY_ON_VERSION_CONFLICT);
+ if (headers != null) {
+ Iterator headerIterator = headers.asIterator();
+ while(headerIterator.hasNext()){
+ String headerValue = headerIterator.next();
+ if (isNotBlank(headerValue)) {
+ StringTokenizer tok = new StringTokenizer(headerValue, ";");
+ while (tok.hasMoreTokens()) {
+ String next = trim(tok.nextToken());
+ if (next.equals(Constants.HEADER_RETRY)) {
+ setRetry(true);
+ } else if (next.startsWith(Constants.HEADER_MAX_RETRIES + "=")) {
+ String val = trim(next.substring((Constants.HEADER_MAX_RETRIES + "=").length()));
+ int maxRetries = Integer.parseInt(val);
+ setMaxRetries(maxRetries);
+ }
+ }
+ }
+ }
+ }
+ }
+
public void setServletResponse(HttpServletResponse myServletResponse) {
this.myServletResponse = myServletResponse;
}
diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml
index 861da0a89e3..c59d014ba2b 100644
--- a/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml
+++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml
@@ -7,7 +7,7 @@
hapi-fhir-serviceloaders
ca.uhn.hapi.fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml
index cbbc0ff57df..a77c67dfda3 100644
--- a/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml
+++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml
@@ -7,7 +7,7 @@
hapi-fhir-serviceloaders
ca.uhn.hapi.fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
@@ -20,7 +20,7 @@
ca.uhn.hapi.fhir
hapi-fhir-caching-api
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
com.github.ben-manes.caffeine
diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml
index f25381f3871..ea8eda5e404 100644
--- a/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml
+++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml
@@ -7,7 +7,7 @@
hapi-fhir-serviceloaders
ca.uhn.hapi.fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml
index 7d4c63504ff..910d572cc66 100644
--- a/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml
+++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml
@@ -7,7 +7,7 @@
hapi-fhir
ca.uhn.hapi.fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../../pom.xml
diff --git a/hapi-fhir-serviceloaders/pom.xml b/hapi-fhir-serviceloaders/pom.xml
index 0f77474def6..47996d5d96b 100644
--- a/hapi-fhir-serviceloaders/pom.xml
+++ b/hapi-fhir-serviceloaders/pom.xml
@@ -5,7 +5,7 @@
hapi-fhir
ca.uhn.hapi.fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml
index 53c965b9d7b..9c3e9aef6cd 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml
index 87ce61a0215..e5b689b27db 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir-spring-boot-samples
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
hapi-fhir-spring-boot-sample-client-apache
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml
index 857645f328e..34c3d8a4547 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir-spring-boot-samples
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
hapi-fhir-spring-boot-sample-client-okhttp
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml
index be76fd51a3f..9def3808e97 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir-spring-boot-samples
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
hapi-fhir-spring-boot-sample-server-jersey
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml
index e8ee2fb2a6c..1ac037d7169 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir-spring-boot
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
hapi-fhir-spring-boot-samples
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml
index 83426433ac8..e693fd2ebb4 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-spring-boot/pom.xml b/hapi-fhir-spring-boot/pom.xml
index 001e7a15878..de87a1bebc2 100644
--- a/hapi-fhir-spring-boot/pom.xml
+++ b/hapi-fhir-spring-boot/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-sql-migrate/pom.xml b/hapi-fhir-sql-migrate/pom.xml
index 7ef25346890..8e6d8683d1c 100644
--- a/hapi-fhir-sql-migrate/pom.xml
+++ b/hapi-fhir-sql-migrate/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-storage-batch2-jobs/pom.xml b/hapi-fhir-storage-batch2-jobs/pom.xml
index 482eaf6cca2..1cb4a3c4b81 100644
--- a/hapi-fhir-storage-batch2-jobs/pom.xml
+++ b/hapi-fhir-storage-batch2-jobs/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
4.0.0
diff --git a/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/export/FetchResourceIdsStep.java b/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/export/FetchResourceIdsStep.java
index bcb7bf0682a..a76b0b77987 100644
--- a/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/export/FetchResourceIdsStep.java
+++ b/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/export/FetchResourceIdsStep.java
@@ -31,6 +31,7 @@ import ca.uhn.fhir.batch2.jobs.export.models.ResourceIdList;
import ca.uhn.fhir.batch2.jobs.models.Id;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
+import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.bulk.export.api.IBulkExportProcessor;
import ca.uhn.fhir.jpa.bulk.export.model.ExportPIDIteratorParameters;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
diff --git a/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/reindex/ReindexStep.java b/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/reindex/ReindexStep.java
index 0f2a378cf57..9d950e0ab82 100644
--- a/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/reindex/ReindexStep.java
+++ b/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/reindex/ReindexStep.java
@@ -51,6 +51,8 @@ import java.util.concurrent.TimeUnit;
public class ReindexStep implements IJobStepWorker {
+ public static final int REINDEX_MAX_RETRIES = 10;
+
private static final Logger ourLog = LoggerFactory.getLogger(ReindexStep.class);
@Autowired
private HapiTransactionService myHapiTransactionService;
@@ -73,6 +75,8 @@ public class ReindexStep implements IJobStepWorker theDataSink, String theInstanceId, String theChunkId) {
RequestDetails requestDetails = new SystemRequestDetails();
+ requestDetails.setRetry(true);
+ requestDetails.setMaxRetries(REINDEX_MAX_RETRIES);
TransactionDetails transactionDetails = new TransactionDetails();
myHapiTransactionService.execute(requestDetails, transactionDetails, new ReindexJob(data, requestDetails, transactionDetails, theDataSink, theInstanceId, theChunkId));
diff --git a/hapi-fhir-storage-batch2/pom.xml b/hapi-fhir-storage-batch2/pom.xml
index 23373392c8c..7368d5d7fee 100644
--- a/hapi-fhir-storage-batch2/pom.xml
+++ b/hapi-fhir-storage-batch2/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/api/IJobPersistence.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/api/IJobPersistence.java
index 4705dfafc90..a0114138883 100644
--- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/api/IJobPersistence.java
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/api/IJobPersistence.java
@@ -28,6 +28,8 @@ import ca.uhn.fhir.batch2.model.StatusEnum;
import ca.uhn.fhir.batch2.model.WorkChunk;
import ca.uhn.fhir.batch2.models.JobInstanceFetchRequest;
import org.springframework.data.domain.Page;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
import java.util.Iterator;
import java.util.List;
@@ -163,6 +165,9 @@ public interface IJobPersistence {
*/
void incrementWorkChunkErrorCount(String theChunkId, int theIncrementBy);
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ boolean canAdvanceInstanceToNextStep(String theInstanceId, String theCurrentStepId);
+
/**
* Fetches all chunks for a given instance, without loading the data
*
@@ -172,12 +177,14 @@ public interface IJobPersistence {
*/
List fetchWorkChunksWithoutData(String theInstanceId, int thePageSize, int thePageIndex);
- /**
- * Fetch all chunks for a given instance.
- * @param theInstanceId - instance id
- * @param theWithData - whether or not to include the data
- * @return - an iterator for fetching work chunks
- */
+
+
+ /**
+ * Fetch all chunks for a given instance.
+ * @param theInstanceId - instance id
+ * @param theWithData - whether or not to include the data
+ * @return - an iterator for fetching work chunks
+ */
Iterator fetchAllWorkChunksIterator(String theInstanceId, boolean theWithData);
/**
@@ -226,4 +233,6 @@ public interface IJobPersistence {
* @param theInstanceId The instance ID
*/
JobOperationResultJson cancelInstance(String theInstanceId);
+
+ List fetchallchunkidsforstepWithStatus(String theInstanceId, String theStepId, StatusEnum theStatusEnum);
}
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/SynchronizedJobPersistenceWrapper.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/SynchronizedJobPersistenceWrapper.java
index ba9595f14b2..992dc989960 100644
--- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/SynchronizedJobPersistenceWrapper.java
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/SynchronizedJobPersistenceWrapper.java
@@ -126,6 +126,11 @@ public class SynchronizedJobPersistenceWrapper implements IJobPersistence {
myWrap.incrementWorkChunkErrorCount(theChunkId, theIncrementBy);
}
+ @Override
+ public boolean canAdvanceInstanceToNextStep(String theInstanceId, String theCurrentStepId) {
+ return myWrap.canAdvanceInstanceToNextStep(theInstanceId, theCurrentStepId);
+ }
+
@Override
public synchronized List fetchWorkChunksWithoutData(String theInstanceId, int thePageSize, int thePageIndex) {
return myWrap.fetchWorkChunksWithoutData(theInstanceId, thePageSize, thePageIndex);
@@ -141,7 +146,6 @@ public class SynchronizedJobPersistenceWrapper implements IJobPersistence {
return myWrap.fetchAllWorkChunksForStepIterator(theInstanceId, theStepId);
}
-
@Override
public synchronized boolean updateInstance(JobInstance theInstance) {
return myWrap.updateInstance(theInstance);
@@ -166,4 +170,9 @@ public class SynchronizedJobPersistenceWrapper implements IJobPersistence {
public JobOperationResultJson cancelInstance(String theInstanceId) {
return myWrap.cancelInstance(theInstanceId);
}
+
+ @Override
+ public List fetchallchunkidsforstepWithStatus(String theInstanceId, String theStepId, StatusEnum theStatusEnum) {
+ return myWrap.fetchallchunkidsforstepWithStatus(theInstanceId, theStepId, theStatusEnum);
+ }
}
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/WorkChannelMessageHandler.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/WorkChannelMessageHandler.java
index a814b6c8b2e..4056df8901c 100644
--- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/WorkChannelMessageHandler.java
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/WorkChannelMessageHandler.java
@@ -81,6 +81,7 @@ class WorkChannelMessageHandler implements MessageHandler {
return;
}
WorkChunk workChunk = chunkOpt.get();
+ ourLog.debug("Worker picked up chunk. [chunkId={}, stepId={}, startTime={}]", chunkId, workChunk.getTargetStepId(), workChunk.getStartTime());
JobWorkCursor, ?, ?> cursor = buildCursorFromNotification(workNotification);
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/jobs/step/ResourceIdListStep.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/jobs/step/ResourceIdListStep.java
index 0b4963c9f96..2eb9d99ec2b 100644
--- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/jobs/step/ResourceIdListStep.java
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/jobs/step/ResourceIdListStep.java
@@ -100,12 +100,12 @@ public class ResourceIdListStep= MAX_BATCH_OF_IDS) {
+ while (idBuffer.size() > MAX_BATCH_OF_IDS) {
List submissionIds = new ArrayList<>();
for (Iterator iter = idBuffer.iterator(); iter.hasNext(); ) {
submissionIds.add(iter.next());
iter.remove();
- if (submissionIds.size() >= MAX_BATCH_OF_IDS) {
+ if (submissionIds.size() == MAX_BATCH_OF_IDS) {
break;
}
}
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/maintenance/JobChunkProgressAccumulator.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/maintenance/JobChunkProgressAccumulator.java
index 1b51c1f213e..78b22f996d4 100644
--- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/maintenance/JobChunkProgressAccumulator.java
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/maintenance/JobChunkProgressAccumulator.java
@@ -23,9 +23,11 @@ package ca.uhn.fhir.batch2.maintenance;
import ca.uhn.fhir.batch2.model.StatusEnum;
import ca.uhn.fhir.batch2.model.WorkChunk;
+import ca.uhn.fhir.jpa.batch.log.Logs;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.apache.commons.lang3.ArrayUtils;
+import org.slf4j.Logger;
import javax.annotation.Nonnull;
import java.util.Collection;
@@ -36,6 +38,7 @@ import java.util.stream.Collectors;
import static java.util.Collections.emptyList;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
+import static org.slf4j.LoggerFactory.getLogger;
/**
* While performing cleanup, the cleanup job loads all of the known
@@ -44,6 +47,7 @@ import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
* needing to hit the database a second time.
*/
public class JobChunkProgressAccumulator {
+ private static final Logger ourLog = Logs.getBatchTroubleshootingLog();
private final Set myConsumedInstanceAndChunkIds = new HashSet<>();
private final Multimap myInstanceIdToChunkStatuses = ArrayListMultimap.create();
@@ -52,6 +56,10 @@ public class JobChunkProgressAccumulator {
return getChunkIdsWithStatus(theInstanceId, theStepId, theStatuses).size();
}
+ int getTotalChunkCountForInstanceAndStep(String theInstanceId, String theStepId) {
+ return myInstanceIdToChunkStatuses.get(theInstanceId).stream().filter(chunkCount -> chunkCount.myStepId.equals(theStepId)).collect(Collectors.toList()).size();
+ }
+
public List getChunkIdsWithStatus(String theInstanceId, String theStepId, StatusEnum... theStatuses) {
return getChunkStatuses(theInstanceId).stream()
.filter(t -> t.myStepId.equals(theStepId))
@@ -73,6 +81,7 @@ public class JobChunkProgressAccumulator {
// Note: If chunks are being written while we're executing, we may see the same chunk twice. This
// check avoids adding it twice.
if (myConsumedInstanceAndChunkIds.add(instanceId + " " + chunkId)) {
+ ourLog.debug("Adding chunk to accumulator. [chunkId={}, instanceId={}, status={}]", chunkId, instanceId, theChunk.getStatus());
myInstanceIdToChunkStatuses.put(instanceId, new ChunkStatusCountValue(chunkId, theChunk.getTargetStepId(), theChunk.getStatus()));
}
}
@@ -88,6 +97,4 @@ public class JobChunkProgressAccumulator {
myStatus = theStatus;
}
}
-
-
}
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/maintenance/JobInstanceProcessor.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/maintenance/JobInstanceProcessor.java
index af8a278de62..0d803e9944a 100644
--- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/maintenance/JobInstanceProcessor.java
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/maintenance/JobInstanceProcessor.java
@@ -140,11 +140,9 @@ public class JobInstanceProcessor {
String instanceId = myInstance.getInstanceId();
String currentStepId = jobWorkCursor.getCurrentStepId();
- int incompleteChunks = myProgressAccumulator.countChunksWithStatus(instanceId, currentStepId, StatusEnum.getIncompleteStatuses());
-
- if (incompleteChunks == 0) {
+ boolean shouldAdvance = myJobPersistence.canAdvanceInstanceToNextStep(instanceId, currentStepId);
+ if (shouldAdvance) {
String nextStepId = jobWorkCursor.nextStep.getStepId();
-
ourLog.info("All processing is complete for gated execution of instance {} step {}. Proceeding to step {}", instanceId, currentStepId, nextStepId);
if (jobWorkCursor.nextStep.isReductionStep()) {
@@ -154,18 +152,23 @@ public class JobInstanceProcessor {
processChunksForNextSteps(instanceId, nextStepId);
}
} else {
- ourLog.debug("Not ready to advance gated execution of instance {} from step {} to {} because there are {} incomplete work chunks",
- instanceId, currentStepId, jobWorkCursor.nextStep.getStepId(), incompleteChunks);
+ ourLog.debug("Not ready to advance gated execution of instance {} from step {} to {}.",
+ instanceId, currentStepId, jobWorkCursor.nextStep.getStepId());
}
}
private void processChunksForNextSteps(String instanceId, String nextStepId) {
- List chunksForNextStep = myProgressAccumulator.getChunkIdsWithStatus(instanceId, nextStepId, StatusEnum.QUEUED);
- for (String nextChunkId : chunksForNextStep) {
+ List queuedChunksForNextStep = myProgressAccumulator.getChunkIdsWithStatus(instanceId, nextStepId, StatusEnum.QUEUED);
+ int totalChunksForNextStep = myProgressAccumulator.getTotalChunkCountForInstanceAndStep(instanceId, nextStepId);
+ if (totalChunksForNextStep != queuedChunksForNextStep.size()) {
+ ourLog.debug("Total ProgressAccumulator QUEUED chunk count does not match QUEUED chunk size! [instanceId={}, stepId={}, totalChunks={}, queuedChunks={}]", instanceId, nextStepId, totalChunksForNextStep, queuedChunksForNextStep.size());
+ }
+ List chunksToSubmit = myJobPersistence.fetchallchunkidsforstepWithStatus(instanceId, nextStepId, StatusEnum.QUEUED);
+ for (String nextChunkId : chunksToSubmit) {
JobWorkNotification workNotification = new JobWorkNotification(myInstance, nextStepId, nextChunkId);
myBatchJobSender.sendWorkChannelMessage(workNotification);
}
-
+ ourLog.debug("Submitted a batch of chunks for processing. [chunkCount={}, instanceId={}, stepId={}]", chunksToSubmit.size(), instanceId, nextStepId);
myInstance.setCurrentGatedStepId(nextStepId);
myJobPersistence.updateInstance(myInstance);
}
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/model/StatusEnum.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/model/StatusEnum.java
index 40be01e160a..94564129063 100644
--- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/model/StatusEnum.java
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/model/StatusEnum.java
@@ -21,6 +21,9 @@ package ca.uhn.fhir.batch2.model;
*/
import ca.uhn.fhir.i18n.Msg;
+import ca.uhn.fhir.jpa.batch.log.Logs;
+import net.bytebuddy.dynamic.ClassFileLocator;
+import org.slf4j.Logger;
import javax.annotation.Nonnull;
import java.util.Collections;
@@ -61,6 +64,8 @@ public enum StatusEnum {
*/
CANCELLED(true, true);
+ private static final Logger ourLog = Logs.getBatchTroubleshootingLog();
+
private final boolean myIncomplete;
private final boolean myEnded;
private static StatusEnum[] ourIncompleteStatuses;
@@ -138,23 +143,37 @@ public enum StatusEnum {
if (theOrigStatus == theNewStatus) {
return true;
}
-
+ Boolean canTransition;
switch (theOrigStatus) {
case QUEUED:
// initial state can transition to anything
- return true;
+ canTransition = true;
+ break;
case IN_PROGRESS:
- return theNewStatus != QUEUED;
+ canTransition = theNewStatus != QUEUED;
+ break;
case ERRORED:
- return theNewStatus == FAILED || theNewStatus == COMPLETED || theNewStatus == CANCELLED;
+ canTransition = theNewStatus == FAILED || theNewStatus == COMPLETED || theNewStatus == CANCELLED;
+ break;
case COMPLETED:
case CANCELLED:
case FAILED:
// terminal state cannot transition
- return false;
+ canTransition = false;
+ break;
+ default:
+ canTransition = null;
+ break;
}
- throw new IllegalStateException(Msg.code(2131) + "Unknown batch state " + theOrigStatus);
+ if (canTransition == null){
+ throw new IllegalStateException(Msg.code(2131) + "Unknown batch state " + theOrigStatus);
+ } else {
+ if (!canTransition) {
+ ourLog.trace("Tried to execute an illegal state transition. [origStatus={}, newStatus={}]", theOrigStatus, theNewStatus);
+ }
+ return canTransition;
+ }
}
public boolean isIncomplete() {
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/progress/InstanceProgress.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/progress/InstanceProgress.java
index 8b1bb64b859..e7d9edaa9fd 100644
--- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/progress/InstanceProgress.java
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/progress/InstanceProgress.java
@@ -29,6 +29,8 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
import org.slf4j.Logger;
import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.TimeUnit;
class InstanceProgress {
@@ -36,6 +38,7 @@ class InstanceProgress {
private int myRecordsProcessed = 0;
private int myIncompleteChunkCount = 0;
+ private int myQueuedCount = 0;
private int myCompleteChunkCount = 0;
private int myErroredChunkCount = 0;
private int myFailedChunkCount = 0;
@@ -44,6 +47,7 @@ class InstanceProgress {
private Long myLatestEndTime = null;
private String myErrormessage = null;
private StatusEnum myNewStatus = null;
+ private Map> myStepToStatusCountMap = new HashMap<>();
public void addChunk(WorkChunk theChunk) {
myErrorCountForAllStatuses += theChunk.getErrorCount();
@@ -55,6 +59,10 @@ class InstanceProgress {
}
private void updateCompletionStatus(WorkChunk theChunk) {
+ //Update the status map first.
+ Map statusToCountMap = myStepToStatusCountMap.getOrDefault(theChunk.getTargetStepId(), new HashMap<>());
+ statusToCountMap.put(theChunk.getStatus(), statusToCountMap.getOrDefault(theChunk.getStatus(), 0) + 1);
+
switch (theChunk.getStatus()) {
case QUEUED:
case IN_PROGRESS:
@@ -166,14 +174,19 @@ class InstanceProgress {
@Override
public String toString() {
- return new ToStringBuilder(this)
+ ToStringBuilder builder = new ToStringBuilder(this)
.append("myIncompleteChunkCount", myIncompleteChunkCount)
.append("myCompleteChunkCount", myCompleteChunkCount)
.append("myErroredChunkCount", myErroredChunkCount)
.append("myFailedChunkCount", myFailedChunkCount)
.append("myErrormessage", myErrormessage)
- .append("myRecordsProcessed", myRecordsProcessed)
- .toString();
+ .append("myRecordsProcessed", myRecordsProcessed);
+
+ builder.append("myStepToStatusCountMap", myStepToStatusCountMap);
+
+ return builder.toString();
+
+
}
public StatusEnum getNewStatus() {
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/progress/JobInstanceStatusUpdater.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/progress/JobInstanceStatusUpdater.java
index 400587c7dcf..66317f3b27f 100644
--- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/progress/JobInstanceStatusUpdater.java
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/progress/JobInstanceStatusUpdater.java
@@ -50,6 +50,7 @@ public class JobInstanceStatusUpdater {
return false;
}
theJobInstance.setStatus(theNewStatus);
+ ourLog.debug("Updating job instance {} of type {} from {} to {}", theJobInstance.getInstanceId(), theJobInstance.getJobDefinitionId(), origStatus, theNewStatus);
return updateInstance(theJobInstance);
}
diff --git a/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImplTest.java b/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImplTest.java
index 79da318bcb2..75c1e922609 100644
--- a/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImplTest.java
+++ b/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImplTest.java
@@ -43,6 +43,7 @@ import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
diff --git a/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/jobs/step/LoadIdsStepTest.java b/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/jobs/step/LoadIdsStepTest.java
index 699cbfcd54d..1e510b578ba 100644
--- a/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/jobs/step/LoadIdsStepTest.java
+++ b/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/jobs/step/LoadIdsStepTest.java
@@ -6,6 +6,7 @@ import ca.uhn.fhir.batch2.jobs.chunk.PartitionedUrlChunkRangeJson;
import ca.uhn.fhir.batch2.jobs.chunk.ResourceIdListWorkChunkJson;
import ca.uhn.fhir.batch2.jobs.parameters.PartitionedUrlListJobParameters;
import ca.uhn.fhir.batch2.model.JobInstance;
+import ca.uhn.fhir.jpa.api.pid.EmptyResourcePidList;
import ca.uhn.fhir.jpa.api.pid.HomogeneousResourcePidList;
import ca.uhn.fhir.jpa.api.pid.IResourcePidList;
import ca.uhn.fhir.jpa.api.svc.IBatch2DaoSvc;
@@ -74,7 +75,9 @@ public class LoadIdsStepTest {
when(myBatch2DaoSvc.fetchResourceIdsPage(eq(DATE_2), eq(DATE_END), eq(DEFAULT_PAGE_SIZE), isNull(), isNull()))
.thenReturn(createIdChunk(20000L, 40000L, DATE_3));
when(myBatch2DaoSvc.fetchResourceIdsPage(eq(DATE_3), eq(DATE_END), eq(DEFAULT_PAGE_SIZE), isNull(), isNull()))
- .thenReturn(createIdChunk(40000L, 40040L, DATE_3));
+ .thenReturn(createIdChunk(40000L, 40040L, DATE_4));
+ when(myBatch2DaoSvc.fetchResourceIdsPage(eq(DATE_4), eq(DATE_END), eq(DEFAULT_PAGE_SIZE), isNull(), isNull()))
+ .thenReturn(new EmptyResourcePidList());
mySvc.run(details, mySink);
diff --git a/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/maintenance/JobMaintenanceServiceImplTest.java b/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/maintenance/JobMaintenanceServiceImplTest.java
index 8b3fcb05eb6..3768bb52267 100644
--- a/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/maintenance/JobMaintenanceServiceImplTest.java
+++ b/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/maintenance/JobMaintenanceServiceImplTest.java
@@ -38,6 +38,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import java.util.stream.Collectors;
import static ca.uhn.fhir.batch2.coordinator.JobCoordinatorImplTest.createWorkChunkStep1;
import static org.awaitility.Awaitility.await;
@@ -180,9 +181,12 @@ public class JobMaintenanceServiceImplTest extends BaseBatch2Test {
JobCoordinatorImplTest.createWorkChunkStep2().setStatus(StatusEnum.QUEUED).setId(CHUNK_ID),
JobCoordinatorImplTest.createWorkChunkStep2().setStatus(StatusEnum.QUEUED).setId(CHUNK_ID_2)
);
+ when (myJobPersistence.canAdvanceInstanceToNextStep(any(), any())).thenReturn(true);
myJobDefinitionRegistry.addJobDefinition(createJobDefinition(JobDefinition.Builder::gatedExecution));
when(myJobPersistence.fetchAllWorkChunksIterator(eq(INSTANCE_ID), eq(false)))
.thenReturn(chunks.iterator());
+ when(myJobPersistence.fetchallchunkidsforstepWithStatus(eq(INSTANCE_ID), eq(STEP_2), eq(StatusEnum.QUEUED)))
+ .thenReturn(chunks.stream().map(chunk -> chunk.getId()).collect(Collectors.toList()));
JobInstance instance1 = createInstance();
instance1.setCurrentGatedStepId(STEP_1);
when(myJobPersistence.fetchInstances(anyInt(), eq(0))).thenReturn(Lists.newArrayList(instance1));
diff --git a/hapi-fhir-storage-mdm/pom.xml b/hapi-fhir-storage-mdm/pom.xml
index bf69f2b48ba..07ed13bd630 100644
--- a/hapi-fhir-storage-mdm/pom.xml
+++ b/hapi-fhir-storage-mdm/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
4.0.0
diff --git a/hapi-fhir-storage-test-utilities/pom.xml b/hapi-fhir-storage-test-utilities/pom.xml
index a9961d594b8..d7fb772809d 100644
--- a/hapi-fhir-storage-test-utilities/pom.xml
+++ b/hapi-fhir-storage-test-utilities/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
4.0.0
diff --git a/hapi-fhir-storage/pom.xml b/hapi-fhir-storage/pom.xml
index dacdee5290b..10f4772125a 100644
--- a/hapi-fhir-storage/pom.xml
+++ b/hapi-fhir-storage/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/interceptor/UserRequestRetryVersionConflictsInterceptor.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/interceptor/UserRequestRetryVersionConflictsInterceptor.java
index ac0381d2ffc..9ad14b49d95 100644
--- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/interceptor/UserRequestRetryVersionConflictsInterceptor.java
+++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/interceptor/UserRequestRetryVersionConflictsInterceptor.java
@@ -25,6 +25,7 @@ import ca.uhn.fhir.interceptor.api.Interceptor;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.api.model.ResourceVersionConflictResolutionStrategy;
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
+import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.apache.commons.lang3.Validate;
@@ -46,39 +47,26 @@ import static org.apache.commons.lang3.StringUtils.trim;
@Interceptor
public class UserRequestRetryVersionConflictsInterceptor {
+ /** Deprecated and moved to {@link ca.uhn.fhir.rest.api.Constants#HEADER_RETRY_ON_VERSION_CONFLICT} */
+ @Deprecated
public static final String HEADER_NAME = "X-Retry-On-Version-Conflict";
+
+ /** Deprecated and moved to {@link ca.uhn.fhir.rest.api.Constants#HEADER_MAX_RETRIES} */
+ @Deprecated
public static final String MAX_RETRIES = "max-retries";
+
+ /** Deprecated and moved to {@link ca.uhn.fhir.rest.api.Constants#HEADER_RETRY} */
+ @Deprecated
public static final String RETRY = "retry";
@Hook(value = Pointcut.STORAGE_VERSION_CONFLICT, order = 100)
public ResourceVersionConflictResolutionStrategy check(RequestDetails theRequestDetails) {
ResourceVersionConflictResolutionStrategy retVal = new ResourceVersionConflictResolutionStrategy();
-
- if (theRequestDetails != null) {
- List headers = theRequestDetails.getHeaders(HEADER_NAME);
- if (headers != null) {
- for (String headerValue : headers) {
- if (isNotBlank(headerValue)) {
-
- StringTokenizer tok = new StringTokenizer(headerValue, ";");
- while (tok.hasMoreTokens()) {
- String next = trim(tok.nextToken());
- if (next.equals(RETRY)) {
- retVal.setRetry(true);
- } else if (next.startsWith(MAX_RETRIES + "=")) {
-
- String val = trim(next.substring((MAX_RETRIES + "=").length()));
- int maxRetries = Integer.parseInt(val);
- maxRetries = Math.min(100, maxRetries);
- retVal.setMaxRetries(maxRetries);
-
- }
-
- }
-
- }
- }
- }
+ boolean shouldSetRetries = theRequestDetails != null && theRequestDetails.isRetry();
+ if (shouldSetRetries) {
+ retVal.setRetry(true);
+ int maxRetries = Math.min(100, theRequestDetails.getMaxRetries());
+ retVal.setMaxRetries(maxRetries);
}
return retVal;
@@ -90,7 +78,7 @@ public class UserRequestRetryVersionConflictsInterceptor {
*/
public static void addRetryHeader(SystemRequestDetails theRequestDetails, int theMaxRetries) {
Validate.inclusiveBetween(1, Integer.MAX_VALUE, theMaxRetries, "Max retries must be > 0");
- String value = RETRY + "; " + MAX_RETRIES + "=" + theMaxRetries;
- theRequestDetails.addHeader(HEADER_NAME, value);
+ theRequestDetails.setRetry(true);
+ theRequestDetails.setMaxRetries(theMaxRetries);
}
}
diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/searchparam/submit/interceptor/SearchParamValidatingInterceptor.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/searchparam/submit/interceptor/SearchParamValidatingInterceptor.java
index 6903ff010cf..74bd16c5657 100644
--- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/searchparam/submit/interceptor/SearchParamValidatingInterceptor.java
+++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/searchparam/submit/interceptor/SearchParamValidatingInterceptor.java
@@ -92,11 +92,7 @@ public class SearchParamValidatingInterceptor {
SearchParameterMap searchParameterMap = extractSearchParameterMap(runtimeSearchParam);
if (searchParameterMap != null) {
- if (isUpliftSearchParam(theResource)) {
- validateUpliftSp(theRequestDetails, runtimeSearchParam, searchParameterMap);
- } else {
- validateStandardSpOnCreate(theRequestDetails, searchParameterMap);
- }
+ validateStandardSpOnCreate(theRequestDetails, searchParameterMap);
}
}
@@ -118,58 +114,10 @@ public class SearchParamValidatingInterceptor {
SearchParameterMap searchParameterMap = extractSearchParameterMap(runtimeSearchParam);
if (searchParameterMap != null) {
- if (isUpliftSearchParam(theResource)) {
- validateUpliftSp(theRequestDetails, runtimeSearchParam, searchParameterMap);
- } else {
- validateStandardSpOnUpdate(theRequestDetails, runtimeSearchParam, searchParameterMap);
- }
+ validateStandardSpOnUpdate(theRequestDetails, runtimeSearchParam, searchParameterMap);
}
}
- private void validateUpliftSp(RequestDetails theRequestDetails, @Nonnull RuntimeSearchParam theRuntimeSearchParam, SearchParameterMap theSearchParameterMap) {
- Validate.notEmpty(getUpliftExtensions(), "You are attempting to validate an Uplift Search Parameter, but have not defined which URLs correspond to uplifted search parameter extensions.");
-
- IBundleProvider bundleProvider = getDao().search(theSearchParameterMap, theRequestDetails);
- List allResources = bundleProvider.getAllResources();
- if(isNotEmpty(allResources)) {
- Set existingIds = allResources.stream().map(resource -> resource.getIdElement().getIdPart()).collect(Collectors.toSet());
- if (isNewSearchParam(theRuntimeSearchParam, existingIds)) {
- for (String upliftExtensionUrl: getUpliftExtensions()) {
- boolean matchesExistingUplift = allResources.stream()
- .map(sp -> mySearchParameterCanonicalizer.canonicalizeSearchParameter(sp))
- .filter(sp -> !sp.getExtensions(upliftExtensionUrl).isEmpty())
- .anyMatch(sp -> isDuplicateUpliftParameter(theRuntimeSearchParam, sp, upliftExtensionUrl));
-
- if (matchesExistingUplift) {
- throwDuplicateError();
- }
- }
- }
- }
- }
-
- private boolean isDuplicateUpliftParameter(RuntimeSearchParam theRuntimeSearchParam, RuntimeSearchParam theSp, String theUpliftUrl) {
- String firstCode = getUpliftChildExtensionValueByUrl(theRuntimeSearchParam, "code", theUpliftUrl);
- String secondCode = getUpliftChildExtensionValueByUrl(theSp, "code", theUpliftUrl);
- String firstElementName = getUpliftChildExtensionValueByUrl(theRuntimeSearchParam, "element-name", theUpliftUrl);
- String secondElementName = getUpliftChildExtensionValueByUrl(theSp, "element-name", theUpliftUrl);
- return firstCode.equals(secondCode) && firstElementName.equals(secondElementName);
- }
-
-
- private String getUpliftChildExtensionValueByUrl(RuntimeSearchParam theSp, String theUrl, String theUpliftUrl) {
- List> extensions = theSp.getExtensions(theUpliftUrl);
- Validate.isTrue(extensions.size() == 1);
- IBaseExtension, ?> topLevelExtension = extensions.get(0);
- List extension = (List) topLevelExtension.getExtension();
- String subExtensionValue = extension.stream().filter(ext -> ext.getUrl().equals(theUrl)).map(IBaseExtension::getValue)
- .map(IPrimitiveType.class::cast)
- .map(IPrimitiveType::getValueAsString)
- .findFirst()
- .orElseThrow(() -> new UnprocessableEntityException(Msg.code(2198), "Unable to process Uplift SP addition as the SearchParameter is malformed."));
- return subExtensionValue;
- }
-
private boolean isNewSearchParam(RuntimeSearchParam theSearchParam, Set theExistingIds) {
return theExistingIds
.stream()
@@ -190,17 +138,6 @@ public class SearchParamValidatingInterceptor {
throw new UnprocessableEntityException(Msg.code(2125) + "Can't process submitted SearchParameter as it is overlapping an existing one.");
}
- private boolean isUpliftSearchParam(IBaseResource theResource) {
- if (theResource instanceof IBaseHasExtensions) {
- IBaseHasExtensions resource = (IBaseHasExtensions) theResource;
- return resource.getExtension()
- .stream()
- .anyMatch(ext -> getUpliftExtensions().contains(ext.getUrl()));
- } else {
- return false;
- }
- }
-
private boolean isNotSearchParameterResource(IBaseResource theResource){
return ! SEARCH_PARAM.equalsIgnoreCase(myFhirContext.getResourceType(theResource));
}
diff --git a/hapi-fhir-storage/src/test/java/ca/uhn/fhir/jpa/interceptor/validation/SearchParameterValidatingInterceptorTest.java b/hapi-fhir-storage/src/test/java/ca/uhn/fhir/jpa/interceptor/validation/SearchParameterValidatingInterceptorTest.java
index fd29849fb30..8fbfe3c99d4 100644
--- a/hapi-fhir-storage/src/test/java/ca/uhn/fhir/jpa/interceptor/validation/SearchParameterValidatingInterceptorTest.java
+++ b/hapi-fhir-storage/src/test/java/ca/uhn/fhir/jpa/interceptor/validation/SearchParameterValidatingInterceptorTest.java
@@ -146,54 +146,6 @@ public class SearchParameterValidatingInterceptorTest {
}
- @Test
- public void whenUpliftSearchParameter_thenMoreGranularComparisonSucceeds() {
- when(myDaoRegistry.getResourceDao(eq(SearchParamValidatingInterceptor.SEARCH_PARAM))).thenReturn(myIFhirResourceDao);
-
- setPersistedSearchParameters(asList(myExistingSearchParameter));
-
- SearchParameter newSearchParam = buildSearchParameterWithUpliftExtension(ID2);
-
- mySearchParamValidatingInterceptor.resourcePreUpdate(null, newSearchParam, myRequestDetails);
- }
-
- @Test
- public void whenUpliftSearchParameter_thenMoreGranularComparisonFails() {
- when(myDaoRegistry.getResourceDao(eq(SearchParamValidatingInterceptor.SEARCH_PARAM))).thenReturn(myIFhirResourceDao);
- SearchParameter existingUpliftSp = buildSearchParameterWithUpliftExtension(ID1);
- setPersistedSearchParameters(asList(existingUpliftSp));
-
- SearchParameter newSearchParam = buildSearchParameterWithUpliftExtension(ID2);
-
- try {
- mySearchParamValidatingInterceptor.resourcePreUpdate(null, newSearchParam, myRequestDetails);
- fail();
- } catch (UnprocessableEntityException e) {
- assertTrue(e.getMessage().contains("2125"));
- }
- }
-
- @Nonnull
- private SearchParameter buildSearchParameterWithUpliftExtension(String theID) {
- SearchParameter newSearchParam = buildSearchParameterWithId(theID);
-
- Extension topLevelExtension = new Extension();
- topLevelExtension.setUrl(UPLIFT_URL);
-
- Extension codeExtension = new Extension();
- codeExtension.setUrl("code");
- codeExtension.setValue(new CodeType("identifier"));
-
- Extension elementExtension = new Extension();
- elementExtension.setUrl("element-name");
- elementExtension.setValue(new CodeType("patient-identifier"));
-
- topLevelExtension.addExtension(codeExtension);
- topLevelExtension.addExtension(elementExtension);
- newSearchParam.addExtension(topLevelExtension);
- return newSearchParam;
- }
-
private void setPersistedSearchParameterIds(List theSearchParams) {
List resourcePersistentIds = theSearchParams
.stream()
@@ -203,9 +155,6 @@ public class SearchParameterValidatingInterceptorTest {
when(myIFhirResourceDao.searchForIds(any(), any())).thenReturn(resourcePersistentIds);
}
- private void setPersistedSearchParameters(List theSearchParams) {
- when(myIFhirResourceDao.search(any(), any())).thenReturn(new SimpleBundleProvider(theSearchParams));
- }
private SearchParameter buildSearchParameterWithId(String id) {
SearchParameter retVal = new SearchParameter();
diff --git a/hapi-fhir-structures-dstu2.1/pom.xml b/hapi-fhir-structures-dstu2.1/pom.xml
index 082d48fd675..c8d3e773720 100644
--- a/hapi-fhir-structures-dstu2.1/pom.xml
+++ b/hapi-fhir-structures-dstu2.1/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-dstu2/pom.xml b/hapi-fhir-structures-dstu2/pom.xml
index 987b2345f44..ead0e7a428e 100644
--- a/hapi-fhir-structures-dstu2/pom.xml
+++ b/hapi-fhir-structures-dstu2/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-dstu3/pom.xml b/hapi-fhir-structures-dstu3/pom.xml
index a22c13c8c50..7c58d7360c3 100644
--- a/hapi-fhir-structures-dstu3/pom.xml
+++ b/hapi-fhir-structures-dstu3/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml
index 5138d1de44c..a741082fe19 100644
--- a/hapi-fhir-structures-hl7org-dstu2/pom.xml
+++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-r4/pom.xml b/hapi-fhir-structures-r4/pom.xml
index 387c63d5552..cdc42d9eb54 100644
--- a/hapi-fhir-structures-r4/pom.xml
+++ b/hapi-fhir-structures-r4/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-r4b/pom.xml b/hapi-fhir-structures-r4b/pom.xml
index 630dbdbb8d1..3791b658748 100644
--- a/hapi-fhir-structures-r4b/pom.xml
+++ b/hapi-fhir-structures-r4b/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-r5/pom.xml b/hapi-fhir-structures-r5/pom.xml
index dece4553872..edcf552eef2 100644
--- a/hapi-fhir-structures-r5/pom.xml
+++ b/hapi-fhir-structures-r5/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-test-utilities/pom.xml b/hapi-fhir-test-utilities/pom.xml
index b1c0a4d97b8..5c8559ec5db 100644
--- a/hapi-fhir-test-utilities/pom.xml
+++ b/hapi-fhir-test-utilities/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/system/HapiTestSystemProperties.java b/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/system/HapiTestSystemProperties.java
index afbc174c4f8..efd19f7e73c 100644
--- a/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/system/HapiTestSystemProperties.java
+++ b/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/system/HapiTestSystemProperties.java
@@ -1,5 +1,25 @@
package ca.uhn.fhir.system;
+/*-
+ * #%L
+ * HAPI FHIR Test Utilities
+ * %%
+ * Copyright (C) 2014 - 2022 Smile CDR, Inc.
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
public final class HapiTestSystemProperties {
private static final String MASS_INGESTION_MODE = "mass_ingestion_mode";
private static final String SINGLE_DB_CONNECTION = "single_db_connection";
diff --git a/hapi-fhir-testpage-overlay/pom.xml b/hapi-fhir-testpage-overlay/pom.xml
index 56cc8d5c6f5..e35f60e3bfb 100644
--- a/hapi-fhir-testpage-overlay/pom.xml
+++ b/hapi-fhir-testpage-overlay/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-validation-resources-dstu2.1/pom.xml b/hapi-fhir-validation-resources-dstu2.1/pom.xml
index 0f4fe66a88f..3165748424a 100644
--- a/hapi-fhir-validation-resources-dstu2.1/pom.xml
+++ b/hapi-fhir-validation-resources-dstu2.1/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation-resources-dstu2/pom.xml b/hapi-fhir-validation-resources-dstu2/pom.xml
index 6701f2e7d4d..f942c0487f8 100644
--- a/hapi-fhir-validation-resources-dstu2/pom.xml
+++ b/hapi-fhir-validation-resources-dstu2/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation-resources-dstu3/pom.xml b/hapi-fhir-validation-resources-dstu3/pom.xml
index 5cab58201cf..12a2a9d62d8 100644
--- a/hapi-fhir-validation-resources-dstu3/pom.xml
+++ b/hapi-fhir-validation-resources-dstu3/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation-resources-r4/pom.xml b/hapi-fhir-validation-resources-r4/pom.xml
index 20bd4e14c3e..b6ca945f0f4 100644
--- a/hapi-fhir-validation-resources-r4/pom.xml
+++ b/hapi-fhir-validation-resources-r4/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation-resources-r5/pom.xml b/hapi-fhir-validation-resources-r5/pom.xml
index 9c7518dcc24..ae52667cf94 100644
--- a/hapi-fhir-validation-resources-r5/pom.xml
+++ b/hapi-fhir-validation-resources-r5/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation/pom.xml b/hapi-fhir-validation/pom.xml
index 2833dc64474..cbe0e7f6cac 100644
--- a/hapi-fhir-validation/pom.xml
+++ b/hapi-fhir-validation/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-tinder-plugin/pom.xml b/hapi-tinder-plugin/pom.xml
index 06445471bc3..13c0527c46e 100644
--- a/hapi-tinder-plugin/pom.xml
+++ b/hapi-tinder-plugin/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
diff --git a/hapi-tinder-test/pom.xml b/hapi-tinder-test/pom.xml
index 01850262332..11c48358944 100644
--- a/hapi-tinder-test/pom.xml
+++ b/hapi-tinder-test/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../pom.xml
diff --git a/pom.xml b/pom.xml
index cbc4979eadc..737d0de5cbe 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-fhir
pom
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
HAPI-FHIR
An open-source implementation of the FHIR specification in Java.
https://hapifhir.io
@@ -2102,7 +2102,7 @@
ca.uhn.hapi.fhir
hapi-fhir-checkstyle
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
diff --git a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml
index 083ea4078fb..afa2b2bbf9e 100644
--- a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml
+++ b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../../pom.xml
diff --git a/tests/hapi-fhir-base-test-mindeps-client/pom.xml b/tests/hapi-fhir-base-test-mindeps-client/pom.xml
index ddb24aca1a0..afa380d3ce3 100644
--- a/tests/hapi-fhir-base-test-mindeps-client/pom.xml
+++ b/tests/hapi-fhir-base-test-mindeps-client/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../../pom.xml
diff --git a/tests/hapi-fhir-base-test-mindeps-server/pom.xml b/tests/hapi-fhir-base-test-mindeps-server/pom.xml
index 9745bf1c374..45b78c07508 100644
--- a/tests/hapi-fhir-base-test-mindeps-server/pom.xml
+++ b/tests/hapi-fhir-base-test-mindeps-server/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.3.0-PRE4-SNAPSHOT
+ 6.3.0-PRE5-SNAPSHOT
../../pom.xml