From c481d852127d108636fb0bdcc779123577fc206b Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Tue, 19 Dec 2023 11:04:25 +0100 Subject: [PATCH] #916 - Changing URL of remote KB requires server restart - Inject URL into live objects as part of setting up a connection - Clear query cache when changing the KB configuration - Unrelated documentation fix --- .../admin-guide/settings_segmentation.adoc | 8 +-- .../kb/KnowledgeBaseServiceImpl.java | 67 ++++++++++++++----- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/inception/inception-api-annotation/src/main/resources/META-INF/asciidoc/admin-guide/settings_segmentation.adoc b/inception/inception-api-annotation/src/main/resources/META-INF/asciidoc/admin-guide/settings_segmentation.adoc index bb06fdcc33d..4b19bdafbad 100644 --- a/inception/inception-api-annotation/src/main/resources/META-INF/asciidoc/admin-guide/settings_segmentation.adoc +++ b/inception/inception-api-annotation/src/main/resources/META-INF/asciidoc/admin-guide/settings_segmentation.adoc @@ -24,7 +24,7 @@ adding/removing/changing segmentation annotations (i.e. sentences or tokens). This section describes the global settings related to the support for editable segmentation annotations (i.e. sentences or tokens). -.Knowledge base settings overview +.Segmentation settings overview [cols="4*", options="header"] |=== | Setting @@ -33,8 +33,8 @@ This section describes the global settings related to the support for editable s | Example -| ui.sentence-layer-editable=true +| `ui.sentence-layer-editable` | Enable/disable editing sentences -| false -| true +| `false` +| `true` |=== \ No newline at end of file diff --git a/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/KnowledgeBaseServiceImpl.java b/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/KnowledgeBaseServiceImpl.java index 7c6d136aaf4..e5d1bb54dc1 100644 --- a/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/KnowledgeBaseServiceImpl.java +++ b/inception/inception-kb/src/main/java/de/tudarmstadt/ukp/inception/kb/KnowledgeBaseServiceImpl.java @@ -41,6 +41,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -70,7 +71,6 @@ import org.eclipse.rdf4j.query.QueryEvaluationException; import org.eclipse.rdf4j.query.TupleQuery; import org.eclipse.rdf4j.query.TupleQueryResult; -import org.eclipse.rdf4j.repository.Repository; import org.eclipse.rdf4j.repository.RepositoryConnection; import org.eclipse.rdf4j.repository.RepositoryException; import org.eclipse.rdf4j.repository.RepositoryResult; @@ -83,6 +83,7 @@ import org.eclipse.rdf4j.repository.sail.SailRepository; import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection; import org.eclipse.rdf4j.repository.sail.config.SailRepositoryConfig; +import org.eclipse.rdf4j.repository.sparql.SPARQLConnection; import org.eclipse.rdf4j.repository.sparql.SPARQLRepository; import org.eclipse.rdf4j.repository.sparql.config.SPARQLRepositoryConfig; import org.eclipse.rdf4j.rio.RDFFormat; @@ -307,7 +308,7 @@ public void registerKnowledgeBase(KnowledgeBase aKB, RepositoryImplConfig aCfg) // We want to have a separate Lucene index for every local repo, so we need to hack the // index dir in here because this is the place where we finally know the repo ID. - syncIndexParameters(aKB, aCfg); + setLuceneIndexConfigurtionParameters(aKB, aCfg); repoManager.addRepositoryConfig(new RepositoryConfig(repositoryId, aCfg)); entityManager.persist(aKB); @@ -392,12 +393,17 @@ public void updateKnowledgeBase(KnowledgeBase kb) @Transactional @Override - public void updateKnowledgeBase(KnowledgeBase kb, RepositoryImplConfig cfg) + public void updateKnowledgeBase(KnowledgeBase aKB, RepositoryImplConfig cfg) throws RepositoryException, RepositoryConfigException { - assertRegistration(kb); - repoManager.addRepositoryConfig(new RepositoryConfig(kb.getRepositoryId(), cfg)); - updateKnowledgeBase(kb); + assertRegistration(aKB); + repoManager.addRepositoryConfig(new RepositoryConfig(aKB.getRepositoryId(), cfg)); + + // Drop cached results from the KB being updated + queryCache.asMap().keySet() + .removeIf(key -> Objects.equals(key.kb.getRepositoryId(), aKB.getRepositoryId())); + + updateKnowledgeBase(aKB); } @SuppressWarnings("unchecked") @@ -480,14 +486,12 @@ public RepositoryImplConfig getKnowledgeBaseConfig(KnowledgeBase kb) public RepositoryConnection getConnection(KnowledgeBase kb) { assertRegistration(kb); - Repository repo = repoManager.getRepository(kb.getRepositoryId()); + var repo = repoManager.getRepository(kb.getRepositoryId()); - if (repo instanceof SPARQLRepository) { - SPARQLRepositoryConfig sparqlRepoConfig = (SPARQLRepositoryConfig) getKnowledgeBaseConfig( - kb); - SPARQLRepository sparqlRepo = (SPARQLRepository) repo; + if (repo instanceof SPARQLRepository sparqlRepo) { + var sparqlRepoConfig = (SPARQLRepositoryConfig) getKnowledgeBaseConfig(kb); applyBasicHttpAuthenticationConfigurationFromUrl(sparqlRepoConfig, sparqlRepo); - RemoteRepositoryTraits traits = readTraits(kb); + var traits = readTraits(kb); if (traits != null && traits.getAuthentication() != null) { switch (traits.getAuthentication().getType()) { @@ -508,7 +512,9 @@ public RepositoryConnection getConnection(KnowledgeBase kb) { skipCertificateChecks(kb.isSkipSslValidation()); - syncIndexParameters(kb, getDelegate()); + syncLuceneQueryLiveParameters(kb, getDelegate()); + + syncSparqlUrlLiveParameters(kb, getDelegate()); } @Override @@ -1384,11 +1390,11 @@ void reconfigureLocalKnowledgeBase(KnowledgeBase aKB) */ RepositoryImplConfig config = getNativeConfig(); - syncIndexParameters(aKB, config); + setLuceneIndexConfigurtionParameters(aKB, config); repoManager.addRepositoryConfig(new RepositoryConfig(aKB.getRepositoryId(), config)); } - private void syncIndexParameters(KnowledgeBase aKB, RepositoryImplConfig aCfg) + private void setLuceneIndexConfigurtionParameters(KnowledgeBase aKB, RepositoryImplConfig aCfg) { assertRegistration(aKB); @@ -1415,7 +1421,7 @@ private void syncIndexParameters(KnowledgeBase aKB, RepositoryImplConfig aCfg) } } - private void syncIndexParameters(KnowledgeBase kb, RepositoryConnection aConn) + private void syncLuceneQueryLiveParameters(KnowledgeBase kb, RepositoryConnection aConn) { try { if (aConn instanceof SailRepositoryConnection) { @@ -1436,6 +1442,35 @@ private void syncIndexParameters(KnowledgeBase kb, RepositoryConnection aConn) } } + private void syncSparqlUrlLiveParameters(KnowledgeBase kb, + RepositoryConnection aRepositoryConnection) + { + try { + if (aRepositoryConnection instanceof SPARQLConnection sparqlConnection) { + var sparqlRepoConfig = (SPARQLRepositoryConfig) getKnowledgeBaseConfig(kb); + var repository = sparqlConnection.getRepository(); + + var queryEndpointUrl = sparqlRepoConfig.getQueryEndpointUrl(); + var updateEndpointUrl = sparqlRepoConfig.getUpdateEndpointUrl(); + if (updateEndpointUrl == null) { + updateEndpointUrl = queryEndpointUrl; + } + + writeField(repository, "queryEndpointUrl", queryEndpointUrl, true); + writeField(repository, "updateEndpointUrl", updateEndpointUrl, true); + + var session = readField(sparqlConnection, "client", true); + writeField(session, "queryURL", queryEndpointUrl, true); + writeField(session, "updateURL", updateEndpointUrl, true); + } + } + catch (Exception e) { + throw new RuntimeException("Unable to sync URL into live SPARQL connection - " + + "maybe the SPARQLConnection or SPARQLProtocolSession implementation has changed.", + e); + } + } + @Override public void rebuildFullTextIndex(KnowledgeBase aKB) throws Exception {