Make additional caches to cover NativeHostService and ValidationService

This commit is contained in:
dotasek 2022-01-19 18:36:39 -05:00
parent 0a3e9d3f31
commit 4826424499
20 changed files with 7357 additions and 40 deletions

View File

@ -45,19 +45,15 @@ import java.util.Map;
public class TerminologyClientR5 implements TerminologyClient {
private final Logger logger = LoggerFactory.getLogger(TerminologyClientR5.class);
private final FHIRToolingClient client;
private ClientHeaders clientHeaders;
public TerminologyClientR5(String address, String userAgent) throws URISyntaxException {
logger.info("TerminologyClientR5(String address, String userAgent)");
this.client = new FHIRToolingClient(address, userAgent);
setClientHeaders(new ClientHeaders());
}
public TerminologyClientR5(String address, String userAgent, ClientHeaders clientHeaders) throws URISyntaxException {
logger.info("TerminologyClientR5(String address, String userAgent, ClientHeaders clientHeaders)");
this.client = new FHIRToolingClient(address, userAgent);
setClientHeaders(clientHeaders);
}

View File

@ -79,7 +79,6 @@ public class FHIRToolingClient {
base = baseServiceUrl;
resourceAddress = new ResourceAddress(baseServiceUrl);
this.maxResultSetSize = -1;
checkCapabilities();
}
public Client getClient() {
@ -582,6 +581,7 @@ public class FHIRToolingClient {
}
public String getServerVersion() {
checkCapabilities();
return capabilities == null ? null : capabilities.getSoftware().getVersion();
}
}

View File

@ -76,7 +76,6 @@ public class FHIRToolingClient {
base = baseServiceUrl;
resourceAddress = new ResourceAddress(baseServiceUrl);
this.maxResultSetSize = -1;
checkCapabilities();
}
public Client getClient() {
@ -549,6 +548,7 @@ public class FHIRToolingClient {
}
public String getServerVersion() {
checkCapabilities();
return capabilities == null ? null : capabilities.getSoftware().getVersion();
}
}

View File

@ -195,6 +195,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
protected String version; // although the internal resources are all R5, the version of FHIR they describe may not be
private String cacheId;
private boolean isTxCaching;
@Getter
private int serverQueryCount = 0;
private Set<String> cached = new HashSet<>();
private Map<String, Map<String, ResourceProxy>> allResourcesById = new HashMap<String, Map<String, ResourceProxy>>();
@ -598,7 +600,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (txcaps == null) {
try {
log("Terminology server: Check for supported code systems for "+system);
setTxCaps(txClient.getTerminologyCapabilities());
final TerminologyCapabilities capabilityStatement = txCache.hasTerminologyCapabilities() ? txCache.getTerminologyCapabilities() : txClient.getTerminologyCapabilities();
txCache.cacheTerminologyCapabilities(capabilityStatement);
setTxCaps(capabilityStatement);
} catch (Exception e) {
if (canRunWithoutTerminology) {
noTerminologyServer = true;

View File

@ -83,8 +83,6 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
import ca.uhn.fhir.parser.DataFormatException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*
* This is a stand alone implementation of worker context for use inside a tool.
@ -94,8 +92,6 @@ import org.slf4j.LoggerFactory;
public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerContext, ProfileKnowledgeProvider {
private final Logger dlogger = LoggerFactory.getLogger(SimpleWorkerContext.class);
public static class PackageResourceLoader extends CanonicalResourceProxy {
private String filename;
@ -289,9 +285,6 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
}
txClient.setLogger(txLog);
txClient.setUserAgent(userAgent);
//CACHE
dlogger.info("SimpleWorkerContext.connectToTSServer");
final CapabilityStatement capabilitiesStatementQuick = txCache.hasCapabilityStatement() ? txCache.getCapabilityStatement() : txClient.getCapabilitiesStatementQuick();
txCache.cacheCapabilityStatement(capabilitiesStatementQuick);

View File

@ -423,7 +423,7 @@ public class TerminologyCache {
return;
try {
OutputStreamWriter sw = new OutputStreamWriter(new FileOutputStream(Utilities.path(folder, nc.name+"CACHE_FILE_EXTENSION")), "UTF-8");
OutputStreamWriter sw = new OutputStreamWriter(new FileOutputStream(Utilities.path(folder, nc.name+CACHE_FILE_EXTENSION)), "UTF-8");
sw.write(ENTRY_MARKER+"\r\n");
JsonParser json = new JsonParser();
json.setOutputStyle(OutputStyle.PRETTY);

View File

@ -37,15 +37,11 @@ import org.hl7.fhir.r5.model.*;
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
import org.hl7.fhir.r5.utils.client.network.ByteUtils;
import org.hl7.fhir.r5.utils.client.network.Client;
import org.hl7.fhir.r5.utils.client.network.ClientHeaders;
import org.hl7.fhir.r5.utils.client.network.ResourceRequest;
import org.hl7.fhir.utilities.ToolingClientLogger;
import org.hl7.fhir.utilities.Utilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
@ -77,8 +73,6 @@ import java.util.*;
*/
public class FHIRToolingClient {
private final Logger logger = LoggerFactory.getLogger(FHIRToolingClient.class);
public static final String DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ssK";
public static final String DATE_FORMAT = "yyyy-MM-dd";
public static final String hostKey = "http.proxyHost";
@ -153,7 +147,6 @@ public class FHIRToolingClient {
}
public CapabilityStatement getCapabilitiesStatement() {
logger.info("FHIRToolingClient.getCapabilitiesStatement");
CapabilityStatement capabilityStatement = null;
try {
capabilityStatement = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false),
@ -161,8 +154,6 @@ public class FHIRToolingClient {
generateHeaders(),
"CapabilitiesStatement",
TIMEOUT_NORMAL).getReference();
logger.info("FHIRToolingClient.getCapabilitiesStatement - fetched capabilities from server: " + (capabilities != null ? capabilities.getVersion() : "no version"));
} catch (Exception e) {
throw new FHIRException("Error fetching the server's conformance statement", e);
}
@ -170,7 +161,6 @@ public class FHIRToolingClient {
}
public CapabilityStatement getCapabilitiesStatementQuick() throws EFhirClientException {
logger.info("FHIRToolingClient.getCapabilitiesStatementQuick");
if (capabilities != null) return capabilities;
try {
capabilities = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true),
@ -178,8 +168,6 @@ public class FHIRToolingClient {
generateHeaders(),
"CapabilitiesStatement-Quick",
TIMEOUT_NORMAL).getReference();
logger.info("FHIRToolingClient.getCapabilitiesStatementQuick - fetched capabilities from server: " + capabilities.getVersion());
} catch (Exception e) {
throw new FHIRException("Error fetching the server's capability statement: "+e.getMessage(), e);
}

View File

@ -4,12 +4,13 @@ import okhttp3.Interceptor;
import okhttp3.Response;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* An {@link Interceptor} for {@link okhttp3.OkHttpClient} that controls the number of times we retry a to execute a
* given request, before reporting a failure. This includes unsuccessful return codes and timeouts.
* An {@link Interceptor} for {@link okhttp3.OkHttpClient} that tracks visits to specific urls
*/
public class TxInterceptor implements Interceptor {
@ -26,10 +27,10 @@ public class TxInterceptor implements Interceptor {
return instance;
}
final Set<String> queriedUrls;
final Map<String, Integer> queriedUrls;
private TxInterceptor() {
queriedUrls = new HashSet<>();
queriedUrls = new HashMap<>();
}
@Override
@ -37,10 +38,10 @@ public class TxInterceptor implements Interceptor {
Response response = chain.proceed(chain.request());
final String key = getKey(response.request().method(), response.request().url().toString());
if (!queriedUrls.contains(key)) {
queriedUrls.add(key);
System.out.print("");
}
final int count = queriedUrls.containsKey(key) ? queriedUrls.get(key) : 1;
queriedUrls.put(key, count+1);
System.out.print("");
return response;
}

View File

@ -163,6 +163,16 @@ public class NativeHostServices {
validator.connectToTSServer(txServer, log, FhirPublication.R5);
}
/**
* Set up the validator with a terminology service
*
* @param txServer - the URL of the terminology service (http://tx.fhir.org/r4 default)
* @throws Exception
*/
public void connectToTxSvc(String txServer, String log, String txCache) throws Exception {
validator.connectToTSServer(txServer, log, txCache, FhirPublication.R5);
}
/**
* get back a JSON object with information about the process.
* @return

View File

@ -194,6 +194,10 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
igLoader = new IgLoader(getPcm(), getContext(), getVersion(), isDebug());
}
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, boolean canRunWithoutTerminologyServer, String vString, String userAgent) throws FHIRException, IOException, URISyntaxException {
this(src, txsrvr, txLog, null, version, canRunWithoutTerminologyServer, vString, userAgent);
}
public ValidationEngine(String src, String txsrvr, String txLog, String txCachePath, FhirPublication version, boolean canRunWithoutTerminologyServer, String vString, String userAgent) throws FHIRException, IOException, URISyntaxException {
loadCoreDefinitions(src, false, null);
getContext().setUserAgent(userAgent);
@ -203,6 +207,10 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
igLoader = new IgLoader(getPcm(), getContext(), getVersion(), isDebug());
}
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, String vString, String userAgent) throws FHIRException, IOException, URISyntaxException {
this(src, txsrvr, txLog, null, version, vString, userAgent);
}
public ValidationEngine(String src, String txsrvr, String txLog, String txCachePath, FhirPublication version, String vString, String userAgent) throws FHIRException, IOException, URISyntaxException {
loadCoreDefinitions(src, false, null);
getContext().setUserAgent(userAgent);
@ -212,6 +220,10 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
}
public ValidationEngine(String src, String vString, TimeTracker tt, String userAgent) throws FHIRException, IOException, URISyntaxException {
this(src, vString,null, tt, userAgent);
}
public ValidationEngine(String src, String vString, String txCachePath, TimeTracker tt, String userAgent) throws FHIRException, IOException, URISyntaxException {
loadCoreDefinitions(src, false, tt);
getContext().setUserAgent(userAgent);
setVersion(vString);

View File

@ -58,6 +58,8 @@ public class CliContext {
private String sv = null;
@JsonProperty("txLog")
private String txLog = null;
@JsonProperty("txCache")
private String txCache = null;
@JsonProperty("mapLog")
private String mapLog = null;
@JsonProperty("lang")
@ -372,6 +374,17 @@ public class CliContext {
return this;
}
@JsonProperty("txCache")
public String getTxCache() {
return txCache;
}
@JsonProperty("txLog")
public CliContext setTxCache(String txCache) {
this.txCache = txCache;
return this;
}
@JsonProperty("mapLog")
public String getMapLog() {
return mapLog;

View File

@ -287,7 +287,7 @@ public class ValidationService {
System.out.println("No such cached session exists for session id " + sessionId + ", re-instantiating validator.");
}
System.out.print(" Load FHIR v" + cliContext.getSv() + " from " + definitions);
ValidationEngine validator = new ValidationEngine(definitions, cliContext.getSv(), tt, "fhir/validator");
ValidationEngine validator = new ValidationEngine(definitions, cliContext.getSv(), cliContext.getTxCache(), tt, "fhir/validator");
sessionId = sessionCache.cacheSession(validator);
FhirPublication ver = FhirPublication.fromCode(cliContext.getSv());
@ -295,7 +295,7 @@ public class ValidationService {
System.out.println(" - " + validator.getContext().countAllCaches() + " resources (" + tt.milestone() + ")");
igLoader.loadIg(validator.getIgs(), validator.getBinaries(), "hl7.terminology", false);
System.out.print(" Terminology server " + cliContext.getTxServer());
String txver = validator.setTerminologyServer(cliContext.getTxServer(), cliContext.getTxLog(), ver);
String txver = validator.setTerminologyServer(cliContext.getTxServer(), cliContext.getTxLog(), cliContext.getTxCache(), ver);
System.out.println(" - Version " + txver + " (" + tt.milestone() + ")");
validator.setDebug(cliContext.isDoDebug());
for (String src : cliContext.getIgs()) {

View File

@ -37,6 +37,7 @@ public class Params {
public static final String SCAN = "-scan";
public static final String TERMINOLOGY = "-tx";
public static final String TERMINOLOGY_LOG = "-txLog";
public static final String TERMINOLOGY_CACHE = "-txCache";
public static final String LOG = "-log";
public static final String LANGUAGE = "-language";
public static final String IMPLEMENTATION_GUIDE = "-ig";
@ -228,7 +229,13 @@ public class Params {
throw new Error("Specified -txLog without indicating file");
else
cliContext.setTxLog(args[++i]);
} else if (args[i].equals(LOG)) {
} else if (args[i].equals(TERMINOLOGY_CACHE)) {
if (i + 1 == args.length)
throw new Error("Specified -txCache without indicating file");
else
cliContext.setTxCache(args[++i]);
}
else if (args[i].equals(LOG)) {
if (i + 1 == args.length)
throw new Error("Specified -log without indicating file");
else

View File

@ -7,6 +7,7 @@ import org.hl7.fhir.validation.ValidationEngine;
import org.hl7.fhir.validation.cli.model.CliContext;
import org.hl7.fhir.validation.cli.model.FileInfo;
import org.hl7.fhir.validation.cli.model.ValidationRequest;
import org.hl7.fhir.validation.tests.utilities.TestConstants;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@ -17,6 +18,7 @@ import org.mockito.Mockito;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@ -34,7 +36,7 @@ class ValidationServiceTest {
List<FileInfo> filesToValidate = new ArrayList<>();
filesToValidate.add(new FileInfo().setFileName("test_resource.json").setFileContent(resource).setFileType(Manager.FhirFormat.JSON.getExtension()));
ValidationRequest request = new ValidationRequest().setCliContext(new CliContext()).setFilesToValidate(filesToValidate);
ValidationRequest request = new ValidationRequest().setCliContext(new CliContext().setTxCache(Paths.get(TestConstants.TX_CACHE, "validationService").toString())).setFilesToValidate(filesToValidate);
// Validation run 1...nothing cached yet
myService.validateSources(request);
Mockito.verify(sessionCache, Mockito.times(1)).cacheSession(ArgumentMatchers.any(ValidationEngine.class));

View File

@ -3,8 +3,11 @@ package org.hl7.fhir.validation.tests;
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.validation.NativeHostServices;
import org.hl7.fhir.validation.tests.utilities.TestConstants;
import org.junit.jupiter.api.Test;
import java.nio.file.Paths;
public class NativeHostServiceTester {
@Test
@ -13,7 +16,7 @@ public class NativeHostServiceTester {
NativeHostServices svc = new NativeHostServices();
svc.init("hl7.fhir.r4.core#4.0.1");
svc.connectToTxSvc("http://tx.fhir.org/r4", null);
svc.connectToTxSvc("http://tx.fhir.org/r4", null, Paths.get(TestConstants.TX_CACHE, "nativeHost").toString());
System.out.println("base: "+svc.status());
svc.seeResource(TestingUtilities.loadTestResourceBytes("validator", "misc", "ValueSet-dicm-2-AnatomicModifier.json"), FhirFormat.JSON);

View File

@ -330,6 +330,8 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
}
checkOutcomes(errorsLogical, logical, "logical", name);
}
vCurr.getContext().getTxCache().getHitCount();
}
private FhirFormat determineFormat(JsonObject config, byte[] cnt) throws IOException {

View File

@ -0,0 +1,62 @@
{
"resourceType" : "CapabilityStatement",
"id" : "FhirServer",
"meta" : {
"tag" : [{
"system" : "http://hl7.org/fhir/v3/ObservationValue",
"code" : "SUBSETTED",
"display" : "Subsetted"
}]
},
"url" : "http://fhir.healthintersections.com.au/open/metadata",
"version" : "4.0.1-2.0.12-SNAPSHOT",
"name" : "FHIR Reference Server Conformance Statement",
"status" : "active",
"date" : "2022-01-10T11:07:19.254Z",
"contact" : [{
"telecom" : [{
"system" : "other",
"value" : "http://healthintersections.com.au/"
}]
}],
"kind" : "instance",
"instantiates" : ["http://hl7.org/fhir/CapabilityStatement/terminology-server"],
"software" : {
"name" : "Reference Server",
"version" : "2.0.12-SNAPSHOT",
"releaseDate" : "2021-12-20T02:28:03.769Z"
},
"fhirVersion" : "4.0.1",
"format" : ["application/fhir+xml",
"application/fhir+json"],
"rest" : [{
"mode" : "server",
"security" : {
"cors" : true
},
"operation" : [{
"name" : "expand",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-expand"
},
{
"name" : "lookup",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-lookup"
},
{
"name" : "validate-code",
"definition" : "http://hl7.org/fhir/OperationDefinition/Resource-validate"
},
{
"name" : "translate",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-translate"
},
{
"name" : "closure",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-closure"
},
{
"name" : "versions",
"definition" : "/OperationDefinition/fso-versions"
}]
}]
}

View File

@ -0,0 +1,62 @@
{
"resourceType" : "CapabilityStatement",
"id" : "FhirServer",
"meta" : {
"tag" : [{
"system" : "http://hl7.org/fhir/v3/ObservationValue",
"code" : "SUBSETTED",
"display" : "Subsetted"
}]
},
"url" : "http://fhir.healthintersections.com.au/open/metadata",
"version" : "4.0.1-2.0.12-SNAPSHOT",
"name" : "FHIR Reference Server Conformance Statement",
"status" : "active",
"date" : "2022-01-10T11:07:19.254Z",
"contact" : [{
"telecom" : [{
"system" : "other",
"value" : "http://healthintersections.com.au/"
}]
}],
"kind" : "instance",
"instantiates" : ["http://hl7.org/fhir/CapabilityStatement/terminology-server"],
"software" : {
"name" : "Reference Server",
"version" : "2.0.12-SNAPSHOT",
"releaseDate" : "2021-12-20T02:28:03.769Z"
},
"fhirVersion" : "4.0.1",
"format" : ["application/fhir+xml",
"application/fhir+json"],
"rest" : [{
"mode" : "server",
"security" : {
"cors" : true
},
"operation" : [{
"name" : "expand",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-expand"
},
{
"name" : "lookup",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-lookup"
},
{
"name" : "validate-code",
"definition" : "http://hl7.org/fhir/OperationDefinition/Resource-validate"
},
{
"name" : "translate",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-translate"
},
{
"name" : "closure",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-closure"
},
{
"name" : "versions",
"definition" : "/OperationDefinition/fso-versions"
}]
}]
}