Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 44 additions & 38 deletions .github/workflows/publish-snapshot-vsm-operations.yml
Original file line number Diff line number Diff line change
@@ -1,40 +1,46 @@
name: Publish Snapshot VSM Operations
name: Publish Snapshot VSM
on:
push:
branches:
- vsm_operations
push:
branches:
- hapi-7-5-4

jobs:
maven:
runs-on: ubuntu-latest
steps:
- name: Add SHORT_SHA env property with commit short sha
run: echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" >> $GITHUB_ENV
- uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
server-id: ossrh
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ vars.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Install
run: ./scripts/install.sh
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: alphora/cqf-ruler:cqf-ruler-vsm
build-args: COMMIT_HASH=${{ env.SHORT_SHA }}
cache-from: type=gha
cache-to: type=gha,mode=max
maven:
runs-on: ubuntu-latest
steps:
- name: Add SHORT_SHA env property with commit short sha
run: echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" >> $GITHUB_ENV
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 21
server-id: ossrh
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
- name: Package jars
run: ./mvnw -T 4 --batch-mode -no-transfer-progress --update-snapshots deploy
env:
MAVEN_USERNAME: ${{ vars.OSSRH_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ vars.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: |
contentgroup/cqf-ruler:cqf-ruler-vsm
alphora/cqf-ruler:cqf-ruler-vsm
build-args: COMMIT_HASH=${{ env.SHORT_SHA }}
cache-from: type=gha
cache-to: type=gha,mode=max
8 changes: 6 additions & 2 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>org.opencds.cqf.ruler</groupId>
<artifactId>cqf-ruler</artifactId>
<version>0.15.0-SNAPSHOT</version>
<version>0.15-VSM.0-SNAPSHOT</version>
</parent>

<artifactId>cqf-ruler-core</artifactId>
Expand All @@ -13,7 +13,7 @@
<dependency>
<groupId>org.opencds.cqf.ruler</groupId>
<artifactId>cqf-ruler-external</artifactId>
<version>0.15.0-SNAPSHOT</version>
<version>0.15-VSM.0-SNAPSHOT</version>
</dependency>

<dependency>
Expand Down Expand Up @@ -52,6 +52,10 @@
<groupId>org.opencds.cqf.fhir</groupId>
<artifactId>cqf-fhir-cr</artifactId>
</dependency>
<dependency>
<groupId>org.opencds.cqf.fhir</groupId>
<artifactId>cqf-fhir-cr-hapi</artifactId>
</dependency>
<dependency>
<groupId>org.opencds.cqf.fhir</groupId>
<artifactId>cqf-fhir-jackson</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import org.opencds.cqf.external.common.FhirServerConfigDstu3;
import org.opencds.cqf.external.common.FhirServerConfigR4;
import org.opencds.cqf.external.common.FhirServerConfigR5;
import org.opencds.cqf.external.cr.StarterCrDstu3Config;
import org.opencds.cqf.external.cr.StarterCrR4Config;
import org.opencds.cqf.ruler.ServerConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
Expand Down Expand Up @@ -35,8 +33,8 @@
FhirServerConfigR5.class,
JpaBatch2Config.class,
Batch2JobsConfig.class,
StarterCrDstu3Config.class,
StarterCrR4Config.class
RulerCrDstu3Config.class,
RulerCrR4Config.class
})
public class RulerConfig {
public class DaoConfigCustomizer {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
package org.opencds.cqf.ruler.config;

import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.cache.IResourceChangeListenerRegistry;
import ca.uhn.fhir.jpa.cache.ResourceChangeListenerRegistryInterceptor;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
import org.cqframework.cql.cql2elm.CqlCompilerOptions;
import org.cqframework.cql.cql2elm.model.CompiledLibrary;
import org.cqframework.cql.cql2elm.model.Model;
import org.hl7.cql.model.ModelIdentifier;
import org.hl7.elm.r1.VersionedIdentifier;
import org.opencds.cqf.cql.engine.execution.CqlEngine;
import org.opencds.cqf.cql.engine.runtime.Code;
import org.opencds.cqf.external.cr.CrConfigCondition;
import org.opencds.cqf.external.cr.CrProperties;
import org.opencds.cqf.external.cr.PostInitProviderRegisterer;
import org.opencds.cqf.fhir.cql.EvaluationSettings;
import org.opencds.cqf.fhir.cql.engine.retrieve.RetrieveSettings;
import org.opencds.cqf.fhir.cql.engine.terminology.TerminologySettings;
import org.opencds.cqf.fhir.cr.hapi.common.CodeCacheResourceChangeListener;
import org.opencds.cqf.fhir.cr.hapi.common.CqlThreadFactory;
import org.opencds.cqf.fhir.cr.hapi.common.ElmCacheResourceChangeListener;
import org.opencds.cqf.fhir.cr.measure.CareGapsProperties;
import org.opencds.cqf.fhir.cr.measure.MeasureEvaluationOptions;
import org.opencds.cqf.fhir.utility.ValidationProfile;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutorService;

import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Configuration
@Conditional({CrConfigCondition.class})
public class RulerCrCommonConfig {

@Bean
@ConfigurationProperties(prefix = "hapi.fhir.cr")
CrProperties crProperties() {
return new CrProperties();
}

@Bean
RetrieveSettings retrieveSettings(CrProperties theCrProperties) {
return theCrProperties.getCql().getData();
}

@Bean
TerminologySettings terminologySettings(CrProperties theCrProperties) {
return theCrProperties.getCql().getTerminology();
}

@Bean
public EvaluationSettings evaluationSettings(
CrProperties theCrProperties,
RetrieveSettings theRetrieveSettings,
TerminologySettings theTerminologySettings,
Map<VersionedIdentifier, CompiledLibrary> theGlobalLibraryCache,
Map<ModelIdentifier, Model> theGlobalModelCache,
Map<String, List<Code>> theGlobalValueSetCache) {
var evaluationSettings = EvaluationSettings.getDefault();
var cqlOptions = evaluationSettings.getCqlOptions();

var cqlEngineOptions = cqlOptions.getCqlEngineOptions();
Set<CqlEngine.Options> options = EnumSet.noneOf(CqlEngine.Options.class);
var cqlRuntimeProperties = theCrProperties.getCql().getRuntime();
if (cqlRuntimeProperties.isEnableExpressionCaching()) {
options.add(CqlEngine.Options.EnableExpressionCaching);
}
if (cqlRuntimeProperties.isEnableValidation()) {
options.add(CqlEngine.Options.EnableValidation);
}
cqlEngineOptions.setOptions(options);
if (cqlRuntimeProperties.isDebugLoggingEnabled()) {
cqlEngineOptions.setDebugLoggingEnabled(true);
}
cqlOptions.setCqlEngineOptions(cqlEngineOptions);

var cqlCompilerOptions = new CqlCompilerOptions();

var cqlCompilerProperties = theCrProperties.getCql().getCompiler();

if (cqlCompilerProperties.isEnableDateRangeOptimization()) {
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.EnableDateRangeOptimization);
}
if (cqlCompilerProperties.isEnableAnnotations()) {
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.EnableAnnotations);
}
if (cqlCompilerProperties.isEnableLocators()) {
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.EnableLocators);
}
if (cqlCompilerProperties.isEnableResultsType()) {
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.EnableResultTypes);
}
cqlCompilerOptions.setVerifyOnly(cqlCompilerProperties.isVerifyOnly());
if (cqlCompilerProperties.isEnableDetailedErrors()) {
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.EnableDetailedErrors);
}
cqlCompilerOptions.setErrorLevel(cqlCompilerProperties.getErrorSeverityLevel());
if (cqlCompilerProperties.isDisableListTraversal()) {
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.DisableListTraversal);
}
if (cqlCompilerProperties.isDisableListDemotion()) {
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.DisableListDemotion);
}
if (cqlCompilerProperties.isDisableListPromotion()) {
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.DisableListPromotion);
}
if (cqlCompilerProperties.isEnableIntervalDemotion()) {
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.EnableIntervalDemotion);
}
if (cqlCompilerProperties.isEnableIntervalPromotion()) {
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.EnableIntervalPromotion);
}
if (cqlCompilerProperties.isDisableMethodInvocation()) {
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.DisableMethodInvocation);
}
if (cqlCompilerProperties.isRequireFromKeyword()) {
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.RequireFromKeyword);
}
cqlCompilerOptions.setValidateUnits(cqlCompilerProperties.isValidateUnits());
if (cqlCompilerProperties.isDisableDefaultModelInfoLoad()) {
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.DisableDefaultModelInfoLoad);
}
cqlCompilerOptions.setSignatureLevel(cqlCompilerProperties.getSignatureLevel());
cqlCompilerOptions.setCompatibilityLevel(cqlCompilerProperties.getCompatibilityLevel());
cqlCompilerOptions.setAnalyzeDataRequirements(cqlCompilerProperties.isAnalyzeDataRequirements());
cqlCompilerOptions.setCollapseDataRequirements(cqlCompilerProperties.isCollapseDataRequirements());

cqlOptions.setCqlCompilerOptions(cqlCompilerOptions);
evaluationSettings.setLibraryCache(theGlobalLibraryCache);
evaluationSettings.setModelCache(theGlobalModelCache);
evaluationSettings.setValueSetCache(theGlobalValueSetCache);
evaluationSettings.setRetrieveSettings(theRetrieveSettings);
evaluationSettings.setTerminologySettings(theTerminologySettings);
return evaluationSettings;
}

@Primary
@Bean
public ExecutorService cqlExecutor() {
CqlThreadFactory factory = new CqlThreadFactory();
ExecutorService executor = Executors.newFixedThreadPool(2, factory);
executor = new DelegatingSecurityContextExecutorService(executor);

return executor;
}

@Bean
CareGapsProperties careGapsProperties(CrProperties theCrProperties) {
var careGapsProperties = new CareGapsProperties();
// This check for the resource type really should be happening down in CR where the setting is actually used but
// that will have to wait for a future CR release
careGapsProperties.setCareGapsReporter(
theCrProperties.getCareGaps().getReporter().replace("Organization/", ""));
careGapsProperties.setCareGapsCompositionSectionAuthor(
theCrProperties.getCareGaps().getSection_author().replace("Organization/", ""));
return careGapsProperties;
}

@Bean
MeasureEvaluationOptions measureEvaluationOptions(
EvaluationSettings theEvaluationSettings, Map<String, ValidationProfile> theValidationProfiles) {
MeasureEvaluationOptions measureEvalOptions = new MeasureEvaluationOptions();
measureEvalOptions.setEvaluationSettings(theEvaluationSettings);
if (measureEvalOptions.isValidationEnabled()) {
measureEvalOptions.setValidationProfiles(theValidationProfiles);
}
return measureEvalOptions;
}

@Bean
public PostInitProviderRegisterer postInitProviderRegisterer(
RestfulServer theRestfulServer, ResourceProviderFactory theResourceProviderFactory) {
return new PostInitProviderRegisterer(theRestfulServer, theResourceProviderFactory);
}

@Bean
public Map<VersionedIdentifier, CompiledLibrary> globalLibraryCache() {
return new ConcurrentHashMap<>();
}

@Bean
public Map<ModelIdentifier, Model> globalModelCache() {
return new ConcurrentHashMap<>();
}

@Bean
public Map<String, List<Code>> globalValueSetCache() {
return new ConcurrentHashMap<>();
}

@Bean
public ElmCacheResourceChangeListener elmCacheResourceChangeListener(
IResourceChangeListenerRegistry theResourceChangeListenerRegistry,
DaoRegistry theDaoRegistry,
EvaluationSettings theEvaluationSettings) {
ElmCacheResourceChangeListener listener =
new ElmCacheResourceChangeListener(theDaoRegistry, theEvaluationSettings.getLibraryCache());
theResourceChangeListenerRegistry.registerResourceResourceChangeListener(
"Library", SearchParameterMap.newSynchronous(), listener, 1000);
return listener;
}

@Bean
public CodeCacheResourceChangeListener codeCacheResourceChangeListener(
IResourceChangeListenerRegistry theResourceChangeListenerRegistry,
EvaluationSettings theEvaluationSettings,
DaoRegistry theDaoRegistry) {

CodeCacheResourceChangeListener listener =
new CodeCacheResourceChangeListener(theDaoRegistry, theEvaluationSettings.getValueSetCache());
// registry
theResourceChangeListenerRegistry.registerResourceResourceChangeListener(
"ValueSet", SearchParameterMap.newSynchronous(), listener, 1000);

return listener;
}

@Bean
public ResourceChangeListenerRegistryInterceptor resourceChangeListenerRegistryInterceptor() {
return new ResourceChangeListenerRegistryInterceptor();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.opencds.cqf.ruler.config;

import org.opencds.cqf.external.annotations.OnDSTU3Condition;
import org.opencds.cqf.fhir.cr.hapi.config.dstu3.ApplyOperationConfig;
import org.opencds.cqf.fhir.cr.hapi.config.dstu3.CrDstu3Config;
import org.opencds.cqf.fhir.cr.hapi.config.dstu3.DataRequirementsOperationConfig;
import org.opencds.cqf.fhir.cr.hapi.config.dstu3.EvaluateOperationConfig;
import org.opencds.cqf.fhir.cr.hapi.config.dstu3.PackageOperationConfig;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Conditional({OnDSTU3Condition.class})
@Import({
RulerCrCommonConfig.class,
CrDstu3Config.class,
ApplyOperationConfig.class,
DataRequirementsOperationConfig.class,
EvaluateOperationConfig.class,
PackageOperationConfig.class
})
public class RulerCrDstu3Config {}
Loading
Loading